diff --git a/.github/workflows/npm_trusted_release.yml b/.github/workflows/npm_trusted_release.yml index f3164a10..66e85bbc 100644 --- a/.github/workflows/npm_trusted_release.yml +++ b/.github/workflows/npm_trusted_release.yml @@ -77,7 +77,7 @@ jobs: set -euo pipefail case "$ENGINE" in all) - echo 'engines=["v8","hermes","jsc","quickjs","quickjs-ng","shermes","primjs"]' >> "$GITHUB_OUTPUT" + echo 'engines=["v8","hermes","jsc","quickjs","quickjs-ng","primjs"]' >> "$GITHUB_OUTPUT" ;; v8|hermes|jsc|quickjs|quickjs-ng|shermes|primjs) printf 'engines=["%s"]\n' "$ENGINE" >> "$GITHUB_OUTPUT" diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 9089549d..28f7bee1 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -1,25 +1,43 @@ { - "configurations": [ - { - "name": "Android", - "includePath": [ - "${workspaceFolder}/**", - "/Users/ammarahmed/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/**", - "${workspaceFolder}/test-app/runtime/src/main/cpp/jsc/include" - ], - "defines": [], - "compilerPath": "/Users/ammarahmed/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang-17", - "cStandard": "c17", - "cppStandard": "c++17", - "intelliSenseMode": "clang-x86", - "browse": { - "path": [ - "/Users/ammarahmed/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64", - "${workspaceFolder}/test-app/runtime/src/main/cpp/jsc/include" - ], - "limitSymbolsToIncludedHeaders": false - } - } - ], - "version": 4 -} \ No newline at end of file + "configurations": [ + { + "name": "Android", + "compilerPath": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android21-clang++", + "compilerArgs": ["-std=c++20"], + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "linux-clang-arm64", + "defines": [ + "USE_HOST_OBJECT=true", + "NAPI_EXPERIMENTAL=true", + "__BIONIC__=1", + "__V8__", + "__V8_13__" + ], + "includePath": [ + "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1", + "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include", + "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android", + "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include", + "${workspaceFolder}/test-app/runtime/src/main/cpp", + "${workspaceFolder}/test-app/runtime/src/main/cpp/zip/include", + "${workspaceFolder}/test-app/runtime/src/main/cpp/runtime/**", + "${workspaceFolder}/test-app/runtime/src/main/cpp/modules/**", + "${workspaceFolder}/test-app/runtime/src/main/cpp/napi/common", + "${workspaceFolder}/test-app/runtime/src/main/cpp/napi/v8", + "${workspaceFolder}/test-app/runtime/src/main/cpp/napi/v8/v8_inspector", + "${workspaceFolder}/test-app/runtime/src/main/cpp/napi/v8-13", + "${workspaceFolder}/test-app/runtime/src/main/cpp/napi/v8-13/include", + "${workspaceFolder}/test-app/runtime/src/main/cpp/napi/v8-13/v8_inspector" + ], + "browse": { + "path": [ + "${workspaceFolder}/test-app/runtime/src/main/cpp", + "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include" + ], + "limitSymbolsToIncludedHeaders": true + } + } + ], + "version": 4 +} diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 00000000..9aa3b4e5 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,73 @@ +# V8 → NAPI runtime migration ledger + +Tracks the port of substantive commits from the old V8-based runtime +(`nativescript/android-runtime`, branch `master`) into this NAPI-based runtime, +starting at `2bab8f5` (`fix(URL): allow undefined 2nd args`, #1826) through the +old runtime's HEAD (129 commits total). + +Plan: `~/.claude/plans/we-want-to-migrate-modular-prism.md` + +**Status:** the full range `2bab8f5..HEAD` has been triaged. ~60 `build(deps)`/CI/`chore`/`release` +commits are out of scope (fork tooling). Of the substantive commits: **23 ported/partial** +(all native/Java build-verified), several **already-present**, and the rest **deferred** with +rationale (each deferred row says why + what's needed to complete it). Deferred clusters: +**ESM** (`052cb21` + its dependents `7782720f`/`288491f`/`5ceb3d4`/`92c2654`/`45ed1f6`), +**timers** (`bfd7650`), **URLSearchParams spec** (`89893ae`), **workers→C++** (`a84d3c7`), +**inspector** (`55da2da`/`4b5ab0a`), **NDK r27d** (`0387a8d`). The **@CriticalNative** pair +(`085bc4f`+`3c956cf`) and **DexFactory** pair (`c9d41e6`+`fce8e29`) are now **ported** (compile-verified; +they carry device/version/release-only runtime risk — validate on real devices). Verification here is +compile/link + config-eval; on-device behavior is noted per-row where relevant. + +**Disposition:** `ported` · `already-present` · `partial` · `skipped` · `deferred` + +| # | old hash | subject | disposition | new commit | notes | +|---|----------|---------|-------------|------------|-------| +| 1 | 2bab8f5 | fix(URL): allow undefined 2nd args (#1826) | ported | ef20f1d | `URL::New` (modules/url/URL.cpp): gate base-URL branch on `argv[1]` not being undefined/null via `napi_util::is_of_type`; ported expanded `testURLImpl.js` verbatim (JS is engine-agnostic). Verified: native recompile (V8-13, all ABIs) exit 0. | +| 2 | 94ddb15 | fix: `exit(0)` causes ANR due to destroyed mutex (#1820) | ported | b46586b | Old fix was in `MetadataNode::BuildMetadata`; in napi runtime that error path moved to `MetadataBuilder.cpp:55` (identical direct-boot/locked-screen comment). Changed `exit(0)` → `_Exit(0)`. Verified: native recompile exit 0. | +| — | f290ed2 | perf: optimizations around generating JS classes from Metadata (#1824) | already-present | — | Large metadata-subsystem perf refactor (13 files). Confirmed by user: already implemented in the napi runtime's rewritten metadata code. Skipped. | +| 3 | a983931 | fix: gradle error when compileSdk or targetSdk is provided (#1825) | ported | 6f01665 | `test-app/app/build.gradle`: add `as int` cast to provided `compileSdk`/`targetSdk` in `computeCompileSdkVersion`/`computeTargetSdkVersion` (props arrive as String from `-P`). Verified: `:app:help -PcompileSdk=35 -PtargetSdk=35` config eval exit 0. | +| — | e293636 | fix: inner type not set when companion object defined as function (#1831) | already-present | — | New `MetadataNode::SetInnerTypes` (metadata/MetadataNode.cpp:1726-1733) already has the `napi_has_own_property` + `if(!hasOwnProperty)` guard before defining the inner-type accessor — napi port of the same fix. Skipped. | +| 5 | b31fc5f + 3633aed + 83f611b + 3513ce7 + 45fb275 | Ada v3 + URLPattern (#1830), Ada 3.1.1/3.1.3/3.2.7/3.3.0 (#1832/#1835/#1884) | ported | this commit | **Consolidated the whole Ada v3 chain** (Ada is a vendored single-file lib, so intermediate bumps collapse to the final): replaced `modules/url/ada/ada.{h,cpp}` 2.9.0→3.3.0 (verified no API breaks in URL/URLSearchParams). **Ported URLPattern** V8→napi: new `modules/url/URLPattern.{cpp,h}` with a `napi_regex_provider` (RegExp via global ctor + `.exec`, move-only `NapiRegex` ref wrapper, thread-local env for `create_instance`); wired `URLPattern::Init` into `NSRuntimeModules`. Registered spec-correct `hasRegExpGroups` (old C++ had typo `hasRegexpGroups`). Ported `testURLPattern.js` + registered in mainpage.js. Skipped the commit's gradle/CMake/Runtime-V8 bits (superseded / engine-specific). Verified: native build all ABIs exit 0. | +| 6 | bec401c | feat: NDK 27 and Support for Java 21 (#1819) | partial | this commit | **Ported (Java-21 source compat):** `NanoWSD.java` byte casts (`header |= (byte)…`); `NativeScriptAbstractMap` `SimpleEntry`/`SimpleImmutableEntry` gain `` bounds; generator `build.gradle` ×2 `'17'`→`JavaVersion.VERSION_17`; add `compileOptions VERSION_17` to runtime module. **Already-present:** `-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON` (runtime/build.gradle:173), armeabi/x86 android_support block already removed. **Skipped (superseded/N-A to fork):** CI workflows, `gradlew`/wrapper (fork on gradle 8.14.3 > 8.9), root `package.json` version_info, dts-generator submodule bump. Verified: `:runtime:compileDebugJavaWithJavac` under **JDK 21** exit 0. | +| — | c9a2a86 | feat: update Gradle 8.14.3 and Android build tools 8.12.1 (#1834) | already-present | — | Fork already on gradle wrapper 8.14.3 and `NS_DEFAULT_ANDROID_BUILD_TOOLS_VERSION=8.12.1`. Skipped. | +| — | e98367c | feat: performance api (#1838) | already-present | — | `runtime/performance/Performance.h` registers `global.performance`/`performance.now()` (installed at Runtime.cpp:313). Skipped. | +| 7 | 87f7f9c | feat: update libzip to 1.11.4 (#1845) | ported | this commit | Vendored binary dep. Replaced `cpp/zip/include/{zip.h,zipconf.h}` and the 4 prebuilt `libs/common//libzip.a` with upstream 1.11.4 (fork's zipconf was mislabeled "0.11"). Sole consumer `AssetExtractor.cpp` uses only stable API (zip_open/fread/stat_index/…). Verified: native compile+link all ABIs exit 0. **Caveat:** binary swap verified to link only — on-device asset extraction should be smoke-tested. | +| — | 0387a8d | feat: update NDK to latest LTS (r27d) (#1846) | deferred | — | Portable change is `defaultNdkVersion` 27.1.12297006 → **27.3.13750724** in runtime/build.gradle. Deferred: r27d is NOT installed in this env (only 27.0–27.2), and AGP's `ndkVersion defaultNdkVersion` would fail the build (blocking verification of later commits). **Action for user:** `sdkmanager "ndk;27.3.13750724"`, then bump `defaultNdkVersion`. CI/package.json NDK bumps skipped (fork-specific/superseded). | +| 8 | 78589fd | feat: kotlin 2.2.x support (#1848) | ported | this commit | `gradle.properties`: `ns_default_kotlin_version` + `ns_default_kotlinx_metadata_jvm_version` 2.0.0 → 2.2.20. `KotlinClassDescriptor.kt`: kotlinx-metadata 2.2.x renamed the API — `metaClass.enumEntries` → `metaClass.kmEnumEntries.map { it.name }` (`getEnumEntriesAsFields` already takes `Collection`). Verified: metadata-generator `compileKotlin` under 2.2.20 exit 0 + `:app:buildMetadata` runs the generator successfully. | +| 9 | f033061 | feat: queueMicrotask support (#1868) | ported | this commit | Registered global `queueMicrotask` in `Runtime::Init` (after Performance). The V8 original used `isolate->EnqueueMicrotask`; napi has no equivalent, so implemented engine-agnostically via `Promise.resolve().then(cb)` — preserves microtask ordering with promises (`['qm1','p','qm2']` case) and runs before timers. Validates the arg is a function (TypeError otherwise). Ported `testQueueMicrotask.js` + mainpage.js. Verified: native compile exit 0. **Caveat:** ordering/timing asserts not run on-device here. | +| — | 052cb21 | feat: ES modules (ESM) support (#1836) | deferred | — | **Large (26 files).** Analyzed in depth. Upstream ESM is **100% V8-native** (`v8::Module`, `ScriptCompiler::CompileModule`, `InstantiateModule`, `Evaluate`, `GetModuleNamespace`, isolate `SetHostInitializeImportMetaObjectCallback` / `SetHostImportModuleDynamicallyCallback`; ~650-line ModuleInternalCallbacks.cpp). **No napi ESM API exists**, so options are: (a) V8-only native via the napi↔v8 bridge (works only on V8 engine); (b) **engine-agnostic load-time ESM→CJS transpilation** (recommended if pursued: es-module-lexer + source rewrite + import.meta/dynamic-import polyfills through existing CommonJS path; live-binding snapshot caveat). Portable non-native parts (all engines): `Module.java` `.mjs` resolution (.js→.mjs order, index.mjs), `AppConfig.logScriptLoading` + `Runtime.getLogScriptLoadingEnabled`, SBG `generateUniqueFileIdentifier` (MD5, collision-safe for .mjs) + `isJsFile` .mjs, jsparser `sourceType:'module'` for .mjs. **Deferred by user pending design decision.** Related `7782720f` (http esm realms + HMR) also depends on this. | +| 10 | 5cb66ee | fix: prevent crash when jweak points to null (#1881) | ported | this commit | Engine-agnostic JNI/cache fix, applied to the same files under new paths. `jni/JEnv.h`: add `isSameObject`. `jni/LRUCache.h`: add optional `cacheValidCallback` (checked on lookup → evict stale entries via new `evictKey`) + member. `objectmanager/ObjectManager`: add `ValidateWeakGlobalRefCallback` (`!isSameObject(obj, NULL)`) and pass it to the weak-ref `m_cache`. Skipped upstream's cosmetic robin_hood/emplace swap (new LRUCache uses `std::unordered_map`). Verified: native compile all ABIs exit 0. | +| — | 7782720f | feat: http loaded es module realms + HMR DX enrichments (#1883) | deferred | — | Builds directly on the deferred ESM feature (modifies the V8 `ModuleInternalCallbacks`, adds HMRSupport + DevFlags on top of ESM realms, `testESModules.mjs`). Deferred together with [[052cb21]] ESM. | +| — | 45fb275 | feat: Ada 3.3.0 (#1884) | already-present | — | Covered by the consolidated Ada v3 upgrade in commit `8109ff9` (fork now on Ada 3.3.0). | +| 11 | c05e283 | fix: improve reThrowToJava exception handling and runtime retrieval (#1886) | ported | this commit | Made `ObjectManager::GetClassName` (both overloads) + its `JAVA_LANG_CLASS`/`GET_NAME_METHOD_ID` JNI ids **static** (added out-of-class defs), so `NativeScriptException` can resolve a Java class name during rethrow **without** `Runtime::GetRuntime(env)->GetObjectManager()` (avoids a throw-within-rethrow when the env/runtime is unavailable). Updated the 3 class-name-only sites in NativeScriptException; left `GetJavaExceptionFromEnv` (needs the instance). Skipped upstream's clang-format churn of ObjectManager. Runtime-retrieval robustness (`.at`→`.find`) already present in napi `GetRuntime`. Verified: native compile+link all ABIs exit 0. | +| 12 | 3ecd707 | fix: proguard builds (#1887) | ported | this commit | Comment out `buildMetadata.finalizedBy(currentTask)` for `minify*WithR8` (app/build.gradle:1181); add `consumerProguardFiles 'consumer-rules.pro'` to runtime defaultConfig; new `runtime/consumer-rules.pro` (keep `com.tns.*`, `com.tns.gen.**`, `com.tns.internal.**` + RuntimeVisibleAnnotations). Verified: gradle config eval exit 0. **Caveat:** full effect only observable in a release R8/minify build. | +| — | 288491f | fix: http realm cache key with query params (#1896) | deferred | — | Touches only `HMRSupport.cpp` + `ModuleInternalCallbacks.cpp` — both part of the deferred ESM / http-module-realms work ([[052cb21]], [[7782720f]]). Deferred with them. | +| 13 | 3e61cef | fix: URLSearchParams.forEach() crash and spec compliance (#1895) | partial | this commit | New `ForEach` already had spec arg order `(value, key, searchParams)`, thisArg, and stop-on-throw. Only remaining bug: iterated with `get_keys()`+`get(key)` (returns first value for duplicate keys) → switched to `get_entries()` structured-binding loop (`?a=1&a=2` now yields both). Ported the 4 forEach unit tests. Verified: native compile all ABIs exit 0. | +| — | 5ceb3d4 | feat: remote module security (#1899) | deferred | — | Secures the http-loaded module realms; C++ lands in `DevFlags.cpp/h` + `HMRSupport.cpp` + `ModuleInternalCallbacks.cpp` — none of which exist in the fork (they come from the deferred [[7782720f]] / [[052cb21]]). Java `AppConfig`/`Runtime` additions only make sense with that feature present. Deferred with ESM. | +| 14 | e924542 | feat: improved error logging for NativeScript exceptions (#1908) | partial | this commit | **Ported:** the engine-agnostic `std::set_terminate(LogAndAbortUncaught)` handler in `Runtime::Init(JavaVM)` — logs an uncaught native exception (message via new `NativeScriptException::what()`) before `_Exit`, instead of a bare abort. **Skipped:** the 726-line V8-based `NativeScriptException.cpp/h` logging rewrite — the fork's napi NativeScriptException already builds messages/stacks its own way (`GetErrorMessage`/`GetErrorStackTrace`/`GetFullMessage`/`PrintErrorMessage`) and the old logic is V8-stack-specific; not a clean map. Verified: native compile all ABIs exit 0. | +| 15 | 1fd144f | fix: multithreadedJS should use concurrent java maps (#1920) | ported | this commit | Broadened `Runtime.java` instance-map fields (`strongInstances`, `weakInstances`, `strongJavaObjectToID`, `weakJavaObjectToID`, `loadedJavaScriptExtends`) from concrete types to the `Map<>` interface (only Map methods are used; `NativeScriptHashMap` implements Map), and in the `Runtime(config, dynamicConfig)` ctor swap them to `ConcurrentHashMap`/`Collections.synchronizedMap(...)` when `getEnableMultithreadedJavascript()`. Ported `ConcurrentAccessTest.java` + `testConcurrentAccess.js` + mainpage require. Verified: `:runtime:` + `:app:compileDebugJavaWithJavac` exit 0. **Caveat:** concurrency behavior is device-only. | +| 22 | 085bc4f + 3c956cf | feat: @CriticalNative/@FastNative on safe methods (#1921) + optimized native method registration for Android 8-11 (#1942) | ported | this commit | Combined end-state (`3c956cf` supersedes `085bc4f`). **Java** (`Runtime.java`): `SUPPORTS_OPTIMIZED_NATIVE = SDK_INT>=26`; each hot native now has an annotated variant + a `*Legacy` variant + a dispatcher — `@CriticalNative generateNewObjectIdCritical`/`getCurrentRuntimeIdCritical`/`getPointerSizeCritical` (static, no-arg/primitive) and `@FastNative notifyGcFast`/`setManualInstrumentationModeFast`. **C++** (`com_tns_Runtime.cpp`): `RegisterOptimizedNatives` binds the critical/fast impls via `RegisterNatives` in `JNI_OnLoad` (dynamic lookup of annotated methods is broken on API 26-30); `*Legacy` externs auto-bind for older/ fallback. `generateNewObjectId` made static-safe via `GenerateNewObjectId(nullptr,nullptr)` (ignores env/obj); `getCurrentRuntimeId` uses `Runtime::Current()` (no JNI). notifyGc keeps the fork's `(int,int[])` → `"(I[I)Z"`. Verified: native+Java compile all ABIs exit 0. **Caveat:** ART calling-convention correctness is device-only — validate on Android 8-11 + 12+ and a release build. | +| 16 | df4e81b | fix: select correct runtime when calling from different threads (#1906) | ported | this commit | **Headline fix:** in `Runtime.callJSMethod(int runtimeId, …)`, re-select via `getObjectRuntime(javaObject)` not only when the id misses but also when the found runtime doesn't own the object (`runtime.getJavaObjectID(javaObject) == null`) — fixes a worker invoking a method on an object created in another runtime. **Diagnostic:** wrapped `GetJavaObjectByID` in `ObjectManager::GetJavaObjectByJsObject` with a clearer error (id + original message via the `what()` added in [[c05e283]]/#1908 port). Adapted to the fork's runtimeId-based dispatch; skipped upstream's NSE `ToString()`/`GetErrorMessage()` (fork already has its own message infra + `what()`). Verified: native+Java compile exit 0. | +| 17 | 54185ff | [jsparser]: disable sourcemap (#1796) | ported | this commit | `jsparser/webpack.config.js`: `devtool: false`. | +| 18 | e963d6c | fix: jsparser report webpack failure (#1797) | ported | this commit | `jsparser/js_parser.js`: `traverseFiles` throws when no files found (empty = broken webpack build) instead of silently succeeding. | +| 19 | dd2984b | fix(jsparser): skip non-Identifier keys in `.extend({})` (#1950) | ported | this commit | `jsparser/visitors/es5-visitors.js`: added `_getIdentifierKeyName` helper; both `.extend` property loops now skip spreads/computed/non-Identifier keys instead of crashing (e.g. bundled Zod `.extend({ ...other })`). Verified: jsparser `npm run build` (webpack) compiles clean (build/ is gitignored, rebuilt on demand). | +| 20 | 49da71b | fix: circular dependencies when using proguard (#1910) | ported | this commit | Comment out the `buildMetadata` task's `dependsOn compile*ArtProfile` and `dependsOn optimize*Resources` (app/build.gradle) — they created a circular task dependency under proguard/R8. Verified: `:app:help` config eval exit 0. **Caveat:** full effect only in a release R8 build. | +| 21 | 2b6cb03 | fix: ensure dex cache directory exists before proxy generation (#1938) | ported | this commit | `RuntimeHelper.java`: `mkdirs()` the `code_cache/secondary-dexes` dir and fall back to `appDir/secondary-dexes` when it's missing/unwritable. `ProxyGenerator.java` (runtime-binding-generator): create the parent dir before `createNewFile()` — prevents ENOENT crashes on newer Android. Verified: app + generators compile exit 0. | +| 23 | c9d41e6 + fce8e29 | fix(DexFactory): inject DEX into parent class loader (#1951) + register with a single class loader (#1968) | ported | this commit | Combined end-state (`fce8e29` supersedes `c9d41e6`). Enables `Class.forName()` to find runtime-generated proxies (e.g. FragmentFactory). `DexFactory`: new `injectIntoParentClassLoader` ctor flag; `resolveClass` adds the jar into the app's own `BaseDexClassLoader` via `injectDexIntoClassLoader` (API 24+ `addDexPath`; 23/<23 `appendDexElements` using `DexPathList.makePathElements`/`makeDexElements`) so the `DexFile` has a single owner (avoids ART "registered with multiple class loaders" on release builds), falling back to an isolated `DexClassLoader` on failure. `Runtime.java` passes `isMainThread` (workerId==0). Ported `testClassForNameDiscovery.js`. Verified: Java compile exit 0 (reflection has a try/catch fallback if hidden-API access is blocked). **Caveat:** hidden-API reflection is Android-version-sensitive — validate on real devices across versions **and a release/non-debuggable build**. | +| 24 | bfd7650 | fix(timers): order timers with the Java MessageQueue instead of ALooper fds | ported | this commit | Replaced the fork's ALooper-fd/pipe/watcher-thread/mutex/condvar timer delivery with a per-runtime `com.tns.TimerHandler` (new) bound to the runtime thread's Looper: each timer enqueues one anonymous due-token via `sendMessageAtTime`, and native `FireTimer()` (called from `handleMessage`) fires the earliest-due entry of `sortedTimers_` (now `vector` by exact sub-ms dueTime). `postTimer` posts due-now at `(long)now` (FIFO tie with `postDelayed(0)`) and future at `ceil(dueTime)`. Removed threadLoop/PumpTimerLoopCallback/fd/thread/mutex/condvar; added `extern "C" Java_com_tns_TimerHandler_nativeFireTimer` (symbol-bound). Also fixed the pre-existing callback-`napi_ref` leak by centralizing ref deletion in `TimerTask::Unschedule`. Ported `testNativeTimers.js`. Verified: native+Java compile all ABIs exit 0. **Caveat:** ordering semantics are device-only — run the regression tests on a device. | +| 25 | 89893ae | fix: URLSearchParams construction and iteration spec compliance (#1970) | ported | this commit | Rewrote the fork's napi `URLSearchParams` to the WebIDL spec: **constructor** now accepts string / record / sequence-of-pairs / primitive (via `napi_typeof` + `@@iterator` detection, `napi_get_all_property_names` for records, an ES-iterator driver for sequences with `IteratorClose` on abrupt completion, `napi_coerce_to_string` USVString coercion). **keys/values/entries** now return live spec iterators (a JS `{next}` object over ada `operator[]`, duplicate-key correct, `Symbol.iterator`→self, `Symbol.toStringTag`="URLSearchParams Iterator", freed via `napi_add_finalizer`); `prototype[@@iterator]===entries`. Added optional-value `delete`/`has`; `get` returns `null` (not undefined) on miss; brand checks ("Illegal invocation") + `ValueToString` coercion on every method. Ported the full 522-line spec test. Verified: native compile all ABIs exit 0. **Caveat:** spec behavior validated by the ported WPT-style tests **on-device**. | +| — | 92c2654 | fix: anchor relative dynamic imports at the file:// referrer's directory (#1976) | deferred | — | ESM-only: touches `ModuleInternalCallbacks.cpp` (deferred ESM file) + `.mjs` tests. Deferred with [[052cb21]]. | +| — | 45ed1f6 | fix: normalize "." and ".." in resolved module paths to dedupe modules (#1977) | deferred | — | ESM-only: `ModuleInternalCallbacks.cpp` + `.mjs` tests. Deferred with [[052cb21]]. | +| 26 | a84d3c7 | feat(workers): move worker threading and messaging to C++ (#1972) | partial | this commit | **Ported the engine-agnostic core (Path B):** moved worker threading/messaging from Java `HandlerThread` into C++ — new `runtime/workers/{WorkerWrapper,ConcurrentQueue,LooperTasks,WorkerMessage}`. Parent→worker via a `ConcurrentQueue` (eventfd+ALooper) inbox; worker→parent via the parent Runtime's `LooperTasks`. `WorkerWrapper` owns the worker `std::thread` (JVM attach → Java `initWorkerRuntime`/`runWorkerLoop`/`detachWorkerRuntime` → C++ inbox pump), nested-worker cascade, registry. Removed the Java `WorkerThread`/`WorkerThreadHandler`/`MainThreadHandler` worker branches, `initWorker`, the 6 worker native decls + JNI entrypoints, and `MessageType.java`/`JavaScriptErrorMessage.java`. **Perf:** removes 2 JNI hops + Java `Message`/`Handler` alloc + dispatch per postMessage. **Scoped out (V8-only, no napi surface):** `v8::ValueSerializer` structured clone and **SharedArrayBuffer** → payloads stay JSON on all engines (same semantics as before); `terminate()` is **cooperative** (no `v8::TerminateExecution` — a busy-loop worker isn't preempted). `napi_env`↔`WorkerWrapper` via a registry (no isolate data slot). Verified: native+Java compile all ABIs exit 0. **Caveat:** worker threading/lifecycle correctness is device-only — exercise the worker test suite on a device. | +| 27 | 55da2da + 4b5ab0a | feat(inspector): serve source maps to DevTools (#1969) + attach DevTools to Web Worker isolates (#1973) | ported | this commit | Ported both V8-inspector features onto the fork's napi+v8 hybrid inspector (`runtime/inspector/JsV8InspectorClient` reaches `env->isolate`). **#1969:** `Network.loadNetworkResource`/`IO.read`/`IO.close` disk-served source maps, `nsruntime://` sourceMapURL rewrite (+`disableSourceMapURLRewrite`), socket-thread message fast-path, resource-stream cleanup on disconnect. **#1973:** new `WorkerInspectorClient.{h,cpp}` (per-worker V8 inspector Target/flat-session CDP) + Target-domain worker-session routing + console history; hooked into the **new napi `WorkerWrapper`** — `CreateInspector(napi_env)`/`DestroyInspector()` in `BackgroundLooper` around `RunWorker`, `NotifyTerminating()` on cooperative terminate, `consoleLogCallback` via `WorkerWrapper::FromEnv`. Vendored `third_party/json.hpp`. All inspector code gated `#if defined(__V8__) && defined(APPLICATION_IN_DEBUG)` — **verified multi-engine-safe** (QuickJS build green). Verified: V8-13 debug + QuickJS native+Java compile exit 0. **Caveat:** actual DevTools attach / worker breakpoints / source-map fetch / pause-interrupt are device+DevTools-only — run a live debug session before shipping. | +| 4 | 3423e6f | feat: support 16 KB page sizes, gradle 8.5 (#1818) | partial | ca93e66 | **Ported:** 16 KB `-Wl,-z,max-page-size=16384` link option for arm64-v8a/x86_64 in `runtime/CMakeLists.txt` (verified present in ninja LINK_FLAGS); bumped `NS_DEFAULT_COMPILE_SDK_VERSION`/`NS_DEFAULT_BUILD_TOOLS_VERSION` 34→35 (both installed). **Skipped:** gradle-wrapper 8.4→8.7 and AGP 8.3.2→8.5.0 (new already newer: gradle 8.14.3 / AGP 8.12.1); STL `c++_shared`→`c++_static` (new deliberately uses `c++_shared` for multi-engine libc++ — would break engine `.so` setup). Verified: native reconfigure+relink exit 0. | + +## Verified duplication-check seeds (from planning; confirm at implementation time) + +**MISSING → implement:** `f033061` queueMicrotask · Ada v3.x chain (`b31fc5f`/`3633aed`/`3513ce7`/`83f611b`/`45fb275`) — new bundles Ada 2.9.0, old 3.3.0. + +**PARTIAL → port delta only:** `052cb21` ESM (deferred) · URLSearchParams spec follow-ups (`3e61cef`/`89893ae`/`288491f`). + +**ALREADY-PRESENT → skip w/ evidence:** `e98367c` performance api (Performance.h) · `e293636` companion-object inner-type (MetadataNode::SetInnerTypes hasOwnProperty guard) · `1fd144f`/`df4e81b` multithreaded runtime selection (Runtime.java ConcurrentHashMap + dual-path getCurrentRuntimeId). + +**Build deltas (new behind old):** compileSdk/targetSdk 34→35, buildTools 34→35, Kotlin 2.0.0→2.2.20, NDK default 27.1→27.3. AGP/Gradle 8.12.1, JDK 17, minSdk 21 already match. Apply only per-commit version/flag deltas; preserve multi-engine gradle/CMake machinery. diff --git a/build.gradle b/build.gradle index fadae203..bfd4adf3 100644 --- a/build.gradle +++ b/build.gradle @@ -330,10 +330,6 @@ task copyFilesToProjectTemeplate { into "$DIST_FRAMEWORK_PATH" } - ant.propertyfile(file: "$TEST_APP_PATH/gradle.properties") { - entry(key: "ns_engine", value: "V8") - } - copy { from "$TEST_APP_PATH/gradle-helpers/paths.gradle" into "$DIST_FRAMEWORK_PATH/gradle-helpers" diff --git a/package.json b/package.json index fe10844e..9b39fdf3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@nativescript/android", "description": "NativeScript for Android using Node-API", - "version": "8.8.5", + "version": "9.0.0", "repository": { "type": "git", "url": "https://github.com/NativeScript/android.git" diff --git a/packages/android-shermes/LICENSE b/packages/android-shermes/LICENSE deleted file mode 100755 index 45141222..00000000 --- a/packages/android-shermes/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright (c) 2020, nStudio, LLC - - 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. diff --git a/packages/android-shermes/README.md b/packages/android-shermes/README.md deleted file mode 100644 index 5d95941e..00000000 --- a/packages/android-shermes/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# @nativescript/android-shermes - -NativeScript runtime package for Android, built with the Static Hermes (shermes) JavaScript engine. - -## Build - -From the repo root: - -```sh -./gradlew -Pengine=SHERMES -``` - -This produces the npm artifact in `dist_shermes/`. diff --git a/packages/android-shermes/package.json b/packages/android-shermes/package.json deleted file mode 100644 index 86b3de10..00000000 --- a/packages/android-shermes/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "@nativescript/android-shermes", - "version": "0.0.1", - "description": "NativeScript Runtime for Android (Static Hermes engine)", - "keywords": [ - "NativeScript", - "Android", - "runtime", - "hermes", - "shermes" - ], - "repository": { - "type": "git", - "url": "https://github.com/NativeScript/napi-android", - "directory": "packages/android-shermes" - }, - "author": { - "name": "NativeScript Team", - "email": "oss@nativescript.org" - }, - "license": "Apache-2.0" -} diff --git a/scripts/build.js b/scripts/build.js index b9e1c854..2a22d84e 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -7,8 +7,17 @@ const { spawn } = require('child_process'); const path = require('path'); const readline = require('readline'); -const VALID_ENGINES = ['V8-10',"V8-11","V8-13", 'QUICKJS', "QUICKJS_NG", 'HERMES', 'JSC', 'SHERMES', 'PRIMJS']; -const HOST_OBJECTS_SUPPORTED = new Set(['V8-10','V8-11',"V8-13", 'QUICKJS',"QUICKJS_NG", 'PRIMJS']); +const VALID_ENGINES = ['V8-10',"V8-11","V8-13", 'QUICKJS', "QUICKJS_NG", 'HERMES', 'JSC', 'PRIMJS']; +const HOST_OBJECTS_SUPPORTED = new Set(['V8-10','V8-11',"V8-13", 'QUICKJS',"QUICKJS_NG",'HERMES', 'PRIMJS', "JSC"]); + +// Host objects are enabled by default whenever the selected engine supports +// them. They can be force-disabled with --disable-host-objects (or by +// answering "no" to the interactive prompt). +function hostObjectsEnabled(opts) { + if (!HOST_OBJECTS_SUPPORTED.has(opts.engine)) return false; + if (opts['disable-host-objects']) return false; + return true; +} function parseArgs(argv) { const opts = {}; @@ -51,20 +60,6 @@ async function interactiveFill(opts) { opts.engine = VALID_ENGINES.includes(pick) ? pick : 'V8-10'; } - // Only prompt for host objects if the chosen engine supports it - if (HOST_OBJECTS_SUPPORTED.has(opts.engine)) { - if (typeof opts['use-host-objects'] === 'undefined') { - const ans = await prompt('Use host objects? [y/N]', rl, 'N'); - if (/^y(es)?$/i.test(ans)) opts['use-host-objects'] = true; - } - } else { - // ensure the flag is not set for unsupported engines - if (opts['use-host-objects']) { - console.log(`Warning: host objects not supported for engine ${opts.engine}; ignoring --use-host-objects`); - delete opts['use-host-objects']; - } - } - return opts; } @@ -72,29 +67,9 @@ async function interactiveFill(opts) { if (!opts.engine) { console.log('Select JS engine:'); VALID_ENGINES.forEach((e, i) => console.log(` ${i + 1}) ${e}`)); - const ans = await prompt('Choose number or name', rl, 'V8'); + const ans = await prompt('Choose number or name', rl, 'V8-10'); const pick = /^\d+$/.test(ans) ? VALID_ENGINES[Number(ans) - 1] : ans; - opts.engine = VALID_ENGINES.includes(pick) ? pick : 'V8'; - } - - const booleanPrompts = [ - { key: 'use-host-objects', prop: 'useHostObjects', desc: 'Use host objects (useHostObjects)' }, - ]; - - for (const p of booleanPrompts) { - // skip host-objects prompt if the selected engine does not support it - if (p.key === 'use-host-objects' && !HOST_OBJECTS_SUPPORTED.has(opts.engine)) { - if (opts['use-host-objects']) { - console.log(`Warning: host objects not supported for engine ${opts.engine}; ignoring --use-host-objects`); - delete opts['use-host-objects']; - } - continue; - } - - if (typeof opts[p.key] === 'undefined') { - const ans = await prompt(`${p.desc}? [y/N]`, rl, 'N'); - if (/^y(es)?$/i.test(ans)) opts[p.key] = true; - } + opts.engine = VALID_ENGINES.includes(pick) ? pick : 'V8-10'; } } finally { @@ -107,9 +82,9 @@ async function interactiveFill(opts) { function buildGradleArgs(opts) { const props = []; if (opts.engine) props.push(`-Pengine=${opts.engine}`); - if (opts['use-host-objects']) props.push('-PuseHostObjects'); + if (hostObjectsEnabled(opts)) props.push('-PuseHostObjects'); if (opts['as-napi-module']) props.push('-PasNapiModule'); - + return props; } diff --git a/scripts/get-next-version.js b/scripts/get-next-version.js index 2a370ccc..832380d2 100644 --- a/scripts/get-next-version.js +++ b/scripts/get-next-version.js @@ -15,7 +15,6 @@ function resolveCurrentVersion() { "android-jsc": "../packages/android-jsc/package.json", "android-quickjs": "../packages/android-quickjs/package.json", "android-quickjs-ng": "../packages/android-quickjs-ng/package.json", - "android-shermes": "../packages/android-shermes/package.json", "android-primjs": "../packages/android-primjs/package.json", }; diff --git a/scripts/get-npm-tag.js b/scripts/get-npm-tag.js index 8b4b7b91..d5615722 100644 --- a/scripts/get-npm-tag.js +++ b/scripts/get-npm-tag.js @@ -12,7 +12,6 @@ if (!currentVersion) { "android-jsc": "../packages/android-jsc/package.json", "android-quickjs": "../packages/android-quickjs/package.json", "android-quickjs-ng": "../packages/android-quickjs-ng/package.json", - "android-shermes": "../packages/android-shermes/package.json", "android-primjs": "../packages/android-primjs/package.json", }; diff --git a/test-app/.idea/appInsightsSettings.xml b/test-app/.idea/appInsightsSettings.xml new file mode 100644 index 00000000..371f2e29 --- /dev/null +++ b/test-app/.idea/appInsightsSettings.xml @@ -0,0 +1,26 @@ + + + + + + \ No newline at end of file diff --git a/test-app/app/build.gradle b/test-app/app/build.gradle index 5d7846de..0f145459 100644 --- a/test-app/app/build.gradle +++ b/test-app/app/build.gradle @@ -78,10 +78,10 @@ def pluginsJarLibraries = new LinkedList() def allJarLibraries = new LinkedList() def computeCompileSdkVersion = { -> - project.hasProperty("compileSdk") ? compileSdk : NS_DEFAULT_COMPILE_SDK_VERSION as int + project.hasProperty("compileSdk") ? compileSdk as int : NS_DEFAULT_COMPILE_SDK_VERSION as int } def computeTargetSdkVersion = { -> - project.hasProperty("targetSdk") ? targetSdk : NS_DEFAULT_COMPILE_SDK_VERSION as int + project.hasProperty("targetSdk") ? targetSdk as int : NS_DEFAULT_COMPILE_SDK_VERSION as int } def computeMinSdkVersion = { -> project.hasProperty("minSdk") ? minSdk : NS_DEFAULT_MIN_SDK_VERSION as int @@ -232,8 +232,18 @@ android { minSdkVersion minSdkVer targetSdkVersion computeTargetSdkVersion() ndk { + if (ns_engine == "JSC") { + outLogger.withStyle(Style.Info).println "\t ! JSC engine only ships arm64-v8a and x86_64 prebuilts; " + + "the app will be built for those ABIs only (armeabi-v7a and x86 are excluded)." + } if (onlyX86) { - abiFilters 'x86' + // The updated JSC only ships 64-bit libraries, so fall back to + // x86_64 when a single-ABI (emulator) build is requested. + abiFilters ns_engine == "JSC" ? 'x86_64' : 'x86' + } else if (ns_engine == "JSC") { + // The newer JSC engine only provides arm64-v8a and x86_64 + // prebuilts, so restrict the app to those two ABIs. + abiFilters 'x86_64', 'arm64-v8a' } else { abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' } @@ -886,12 +896,12 @@ task buildMetadata(type: BuildToolTask) { } - def compileArtProfileTaskName = "compile${buildTypeName}ArtProfile" - def compileArtProfileTask = tasks.findByName(compileArtProfileTaskName) + // def compileArtProfileTaskName = "compile${buildTypeName}ArtProfile" + // def compileArtProfileTask = tasks.findByName(compileArtProfileTaskName) - if (compileArtProfileTask) { - dependsOn compileArtProfileTask - } + // if (compileArtProfileTask) { + // dependsOn compileArtProfileTask + // } def extractNativeSymbolTablesTaskName = "extract${buildTypeName}NativeSymbolTables" @@ -902,12 +912,12 @@ task buildMetadata(type: BuildToolTask) { } - def optimizeResourcesTaskName = "optimize${buildTypeName}Resources" - def optimizeResourcesTask = tasks.findByName(optimizeResourcesTaskName) + // def optimizeResourcesTaskName = "optimize${buildTypeName}Resources" + // def optimizeResourcesTask = tasks.findByName(optimizeResourcesTaskName) - if (optimizeResourcesTask) { - dependsOn optimizeResourcesTask - } + // if (optimizeResourcesTask) { + // dependsOn optimizeResourcesTask + // } def bundleResourcesTaskName = "bundle${buildTypeName}Resources" def bundleResourcesTask = tasks.findByName(bundleResourcesTaskName) @@ -1178,7 +1188,7 @@ tasks.configureEach({ DefaultTask currentTask -> // // ensure buildMetadata is done before R8 to allow custom proguard from metadata if (currentTask =~ /minify.*WithR8/) { - buildMetadata.finalizedBy(currentTask) + // buildMetadata.finalizedBy(currentTask) } if (currentTask =~ /assemble.*Debug/ || currentTask =~ /assemble.*Release/) { currentTask.finalizedBy("validateAppIdMatch") diff --git a/test-app/app/src/main/assets/app/mainpage.js b/test-app/app/src/main/assets/app/mainpage.js index c5c36eca..3511a56d 100644 --- a/test-app/app/src/main/assets/app/mainpage.js +++ b/test-app/app/src/main/assets/app/mainpage.js @@ -73,5 +73,10 @@ require("./tests/testPostFrameCallback"); require("./tests/console/logTests.js"); require('./tests/testURLImpl.js'); require('./tests/testURLSearchParamsImpl.js'); +require('./tests/testURLPattern.js'); +require('./tests/testQueueMicrotask.js'); +require('./tests/testConcurrentAccess.js'); +require('./tests/testClassForNameDiscovery.js'); +require('./tests/testNativeTimers.js'); diff --git a/test-app/app/src/main/assets/app/tests/kotlin/companions/testCompanionObjectsSupport.js b/test-app/app/src/main/assets/app/tests/kotlin/companions/testCompanionObjectsSupport.js index 119417d6..a14047a2 100644 --- a/test-app/app/src/main/assets/app/tests/kotlin/companions/testCompanionObjectsSupport.js +++ b/test-app/app/src/main/assets/app/tests/kotlin/companions/testCompanionObjectsSupport.js @@ -90,4 +90,48 @@ describe("Tests Kotlin companion objects support", function () { expect(str).toBe("someString"); }); + + it("Test Kotlin enum class companion object without a name should be supported", function () { + console.log(com.tns.tests.kotlin.companions.KotlinEnumClassWithCompanionWithNestedClass.Companion); + var stringFromCompanion = com.tns.tests.kotlin.companions.KotlinEnumClassWithCompanionWithNestedClass.Companion.getStringFromCompanion(); + expect(stringFromCompanion).toBe("testCompanion"); + + var providedStringFromCompanion = com.tns.tests.kotlin.companions.KotlinEnumClassWithCompanionWithNestedClass.Companion.getProvidedStringFromCompanion("providedString"); + expect(providedStringFromCompanion).toBe("providedString"); + + var simpleObjectFromCompanion = com.tns.tests.kotlin.companions.KotlinEnumClassWithCompanionWithNestedClass.Companion.getSimpleObjectFromCompanion(); + expect(simpleObjectFromCompanion.getSomeString()).toBe("test"); + + var simpleKotlinObject = new com.tns.tests.kotlin.SimpleKotlinObject(); + var providedSimpleObjectFromCompanion = com.tns.tests.kotlin.companions.KotlinEnumClassWithCompanionWithNestedClass.Companion.getProvidedSimpleObjectFromCompanion(simpleKotlinObject); + expect(simpleKotlinObject.equals(providedSimpleObjectFromCompanion)).toBe(true); + + var stringJvmStaticFromCompanion = com.tns.tests.kotlin.companions.KotlinEnumClassWithCompanionWithNestedClass.getStringJvmStaticFromCompanion(); + expect(stringJvmStaticFromCompanion).toBe("testCompanion"); + + var providedStringJvmStaticFromCompanion = com.tns.tests.kotlin.companions.KotlinEnumClassWithCompanionWithNestedClass.getProvidedStringJvmStaticFromCompanion("providedString"); + expect(providedStringJvmStaticFromCompanion).toBe("providedString"); + }); + + it("Test Kotlin enum class named companion object without a name should be supported", function () { + var stringFromCompanion = com.tns.tests.kotlin.companions.KotlinEnumClassWithNamedCompanionWithNestedClass.NamedCompanion.getStringFromNamedCompanion(); + expect(stringFromCompanion).toBe("testCompanion"); + + var providedStringFromCompanion = com.tns.tests.kotlin.companions.KotlinEnumClassWithNamedCompanionWithNestedClass.NamedCompanion.getProvidedStringFromNamedCompanion("providedString"); + expect(providedStringFromCompanion).toBe("providedString"); + + var simpleObjectFromCompanion = com.tns.tests.kotlin.companions.KotlinEnumClassWithNamedCompanionWithNestedClass.NamedCompanion.getSimpleObjectFromNamedCompanion(); + expect(simpleObjectFromCompanion.getSomeString()).toBe("test"); + + var simpleKotlinObject = new com.tns.tests.kotlin.SimpleKotlinObject(); + var providedSimpleObjectFromCompanion = com.tns.tests.kotlin.companions.KotlinEnumClassWithNamedCompanionWithNestedClass.NamedCompanion.getProvidedSimpleObjectFromNamedCompanion(simpleKotlinObject); + expect(simpleKotlinObject.equals(providedSimpleObjectFromCompanion)).toBe(true); + + var stringJvmStaticFromCompanion = com.tns.tests.kotlin.companions.KotlinEnumClassWithNamedCompanionWithNestedClass.getStringJvmStaticFromNamedCompanion(); + expect(stringJvmStaticFromCompanion).toBe("testCompanion"); + + var providedStringJvmStaticFromCompanion = com.tns.tests.kotlin.companions.KotlinEnumClassWithNamedCompanionWithNestedClass.getProvidedStringJvmStaticFromNamedCompanion("providedString"); + expect(providedStringJvmStaticFromCompanion).toBe("providedString"); + }); + }); \ No newline at end of file diff --git a/test-app/app/src/main/assets/app/tests/testClassForNameDiscovery.js b/test-app/app/src/main/assets/app/tests/testClassForNameDiscovery.js new file mode 100644 index 00000000..4dcad0ee --- /dev/null +++ b/test-app/app/src/main/assets/app/tests/testClassForNameDiscovery.js @@ -0,0 +1,67 @@ +describe("Tests Class.forName discovery of runtime generated classes", function () { + + // Android framework components (e.g. FragmentFactory) resolve classes with + // Class.forName(className, false, context.getClassLoader()). Runtime generated + // proxies must be discoverable through the app's class loader, otherwise + // framework lookups crash with ClassNotFoundException (see issue #1962 / PR #1951). + // + // The extend calls below are built dynamically so the static binding generator + // cannot pre-generate the proxies and DexFactory.resolveClass takes the runtime + // generation + parent class loader injection path. + var ext = "ex" + "tend"; + + // the app's PathClassLoader — the same loader the framework uses, + // e.g. in FragmentFactory.loadFragmentClass via context.getClassLoader() + var appClassLoader = com.tns.Runtime.class.getClassLoader(); + + it("When_extending_a_class_at_runtime_it_should_be_discoverable_through_the_app_class_loader", function () { + var MyObject = java.lang.Object[ext]("ClassForNameDiscoveryObject", { + toString: function () { + return "discoverable"; + } + }); + + var instance = new MyObject(); + var className = instance.getClass().getName(); + + var found = java.lang.Class.forName(className, false, appClassLoader); + + expect(found.getName()).toBe(className); + expect(found.equals(instance.getClass())).toBe(true); + }); + + it("When_implementing_an_interface_at_runtime_it_should_be_discoverable_through_the_app_class_loader", function () { + var MyRunnable = java.lang.Runnable[ext]("ClassForNameDiscoveryRunnable", { + run: function () { + } + }); + + var instance = new MyRunnable(); + var className = instance.getClass().getName(); + + var found = java.lang.Class.forName(className, false, appClassLoader); + + expect(found.getName()).toBe(className); + expect(found.equals(instance.getClass())).toBe(true); + }); + + it("When_a_runtime_generated_class_is_instantiated_through_reflection_it_should_dispatch_to_the_JS_implementation", function () { + var MyObject = java.lang.Object[ext]("ClassForNameDiscoveryInstantiated", { + toString: function () { + return "created via reflection"; + } + }); + + // make sure the implementation object is registered before Java constructs an instance + var instance = new MyObject(); + var className = instance.getClass().getName(); + + // FragmentFactory resolves the class by name and instantiates it through + // reflection. Class.newInstance() invokes the no-arg constructor without + // the varargs marshalling getDeclaredConstructor() would need. + var found = java.lang.Class.forName(className, false, appClassLoader); + var created = found.newInstance(); + + expect(created.toString()).toBe("created via reflection"); + }); +}); diff --git a/test-app/app/src/main/assets/app/tests/testConcurrentAccess.js b/test-app/app/src/main/assets/app/tests/testConcurrentAccess.js new file mode 100644 index 00000000..c8ac32c1 --- /dev/null +++ b/test-app/app/src/main/assets/app/tests/testConcurrentAccess.js @@ -0,0 +1,78 @@ +// WARNING: IF THIS TEST FAILS IT COMPLETELY BREAKS ALL OTHER TESTS! + +describe("Tests concurrent access to JNI", function () { + // Customizable test parameters + const BACKGROUND_THREADS = 5; + const SYNC_CALLS = 2; + const ITERATIONS_PER_CALL = 100; + const TIMEOUT_MS = 3000; + + it("test_high_contention_concurrent_access_with_multiple_objects", (done) => { + console.log('STARTING PROBLEMATIC TEST. THIS MIGHT CRASH OR CAUSE ISSUES IN OTHER TESTS IF IT FAILS. If this is close to the end of the log, check test_high_contention_concurrent_access_with_multiple_objects'); + let callbackInvocations = 0; + + const callback = new com.tns.tests.ConcurrentAccessTest.Callback({ + invoke: ( + list1, + list2, + list3, + list4, + list5, + list6, + list7, + list8, + list9, + list10, + ) => { + callbackInvocations++; + // Assert that accessing size() on any of the lists doesn't throw + expect(() => list1.size()).not.toThrow(); + expect(() => list2.size()).not.toThrow(); + expect(() => list3.size()).not.toThrow(); + expect(() => list4.size()).not.toThrow(); + expect(() => list5.size()).not.toThrow(); + expect(() => list6.size()).not.toThrow(); + expect(() => list7.size()).not.toThrow(); + expect(() => list8.size()).not.toThrow(); + expect(() => list9.size()).not.toThrow(); + expect(() => list10.size()).not.toThrow(); + + // Verify that the lists actually have content + expect(list1.size()).toBe(5); + expect(list2.size()).toBe(5); + expect(list3.size()).toBe(5); + expect(list4.size()).toBe(5); + expect(list5.size()).toBe(5); + expect(list6.size()).toBe(5); + expect(list7.size()).toBe(5); + expect(list8.size()).toBe(5); + expect(list9.size()).toBe(5); + expect(list10.size()).toBe(5); + }, + }); + + // Start multiple background threads + for (let i = 0; i < BACKGROUND_THREADS; i++) { + com.tns.tests.ConcurrentAccessTest.callFromBackgroundThread( + callback, + ITERATIONS_PER_CALL, + ); + } + + // Call synchronously multiple times + for (let i = 0; i < SYNC_CALLS; i++) { + com.tns.tests.ConcurrentAccessTest.callSynchronously( + callback, + ITERATIONS_PER_CALL, + ); + } + + // Wait for all threads to complete + setTimeout(() => { + const expectedInvocations = + (BACKGROUND_THREADS + SYNC_CALLS) * ITERATIONS_PER_CALL; + expect(callbackInvocations).toBe(expectedInvocations); + done(); + }, TIMEOUT_MS); + }); +}); diff --git a/test-app/app/src/main/assets/app/tests/testNativeTimers.js b/test-app/app/src/main/assets/app/tests/testNativeTimers.js index 6dd4cc23..11b7db76 100644 --- a/test-app/app/src/main/assets/app/tests/testNativeTimers.js +++ b/test-app/app/src/main/assets/app/tests/testNativeTimers.js @@ -1,7 +1,7 @@ describe('native timer', () => { /** @type {global.setTimeout} */ - let setTimeout = global.__ns__setTimeout; + let setTimeout = global.__ns__setTimeout; /** @type {global.setInterval} */ let setInterval = global.__ns__setInterval; /** @type global.setTimeout */ /** @type {global.clearTimeout} */ @@ -94,7 +94,50 @@ describe('native timer', () => { done(); }); }); - xit('frees up resources after complete', (done) => { + // these specs schedule from a java-posted runnable so they run outside any + // timer callback: jasmine chains specs through timer callbacks, and when + // the runtime is built with NS_TIMERS_NESTING_CLAMP the nesting clamp + // (>=5 levels -> 4ms minimum) would otherwise make setTimeout(0) + // legitimately lose to a postDelayed(0) + it('preserves order with java handler posts', (done) => { + const order = []; + const handler = new android.os.Handler(android.os.Looper.myLooper()); + handler.post(new java.lang.Runnable({ + run: () => { + setTimeout(() => order.push(1)); + handler.postDelayed(new java.lang.Runnable({ run: () => order.push(2) }), 0); + setTimeout(() => order.push(3)); + setTimeout(() => { + expect(order.join(',')).toBe('1,2,3'); + done(); + }, 100); + } + })); + }); + + it('interleaves many timers with a java handler post', (done) => { + const order = []; + const handler = new android.os.Handler(android.os.Looper.myLooper()); + handler.post(new java.lang.Runnable({ + run: () => { + for (let i = 0; i < 50; i++) { + setTimeout(() => order.push('t')); + } + handler.postDelayed(new java.lang.Runnable({ run: () => order.push('j') }), 0); + for (let i = 0; i < 50; i++) { + setTimeout(() => order.push('t')); + } + setTimeout(() => { + // the java runnable must land exactly between the two timer batches + expect(order.indexOf('j')).toBe(50); + expect(order.length).toBe(101); + done(); + }, 100); + } + })); + }); + + it('frees up resources after complete', (done) => { let timeout = 0; let interval = 0; let weakRef; diff --git a/test-app/app/src/main/assets/app/tests/testQueueMicrotask.js b/test-app/app/src/main/assets/app/tests/testQueueMicrotask.js new file mode 100644 index 00000000..6dba7a5f --- /dev/null +++ b/test-app/app/src/main/assets/app/tests/testQueueMicrotask.js @@ -0,0 +1,35 @@ +describe('queueMicrotask', () => { + it('should be defined as a function', () => { + expect(typeof queueMicrotask).toBe('function'); + }); + + it('should throw TypeError when callback is not a function', () => { + expect(() => queueMicrotask(null)).toThrow(); + expect(() => queueMicrotask(123)).toThrow(); + expect(() => queueMicrotask({})).toThrow(); + }); + + it('runs after current stack but before setTimeout(0)', (done) => { + const order = []; + queueMicrotask(() => order.push('microtask')); + setTimeout(() => { + order.push('timeout'); + expect(order).toEqual(['microtask', 'timeout']); + done(); + }, 0); + // at this point, nothing should have run yet + expect(order.length).toBe(0); + }); + + it('preserves ordering with Promise microtasks', (done) => { + const order = []; + queueMicrotask(() => order.push('qm1')); + Promise.resolve().then(() => order.push('p')); + queueMicrotask(() => order.push('qm2')); + + setTimeout(() => { + expect(order).toEqual(['qm1', 'p', 'qm2']); + done(); + }, 0); + }); +}); diff --git a/test-app/app/src/main/assets/app/tests/testURLImpl.js b/test-app/app/src/main/assets/app/tests/testURLImpl.js index 08c34094..0ca91e14 100644 --- a/test-app/app/src/main/assets/app/tests/testURLImpl.js +++ b/test-app/app/src/main/assets/app/tests/testURLImpl.js @@ -1,31 +1,61 @@ -describe("Test URL ", function () { +describe("URL", function () { + it("throws on invalid URL", function () { + var exceptionCaught = false; + try { + const url = new URL(""); + } catch (e) { + exceptionCaught = true; + } + expect(exceptionCaught).toBe(true); + }); - it("Test invalid URL parsing", function(){ - var exceptionCaught = false; - try { - const url = new URL(''); - }catch(e){ - exceptionCaught = true; - } - expect(exceptionCaught).toBe(true); + it("does not throw on valid URL", function () { + var exceptionCaught = false; + try { + const url = new URL("https://google.com"); + } catch (e) { + exceptionCaught = true; + } + expect(exceptionCaught).toBe(false); }); - it("Test valid URL parsing", function(){ - var exceptionCaught = false; - try { - const url = new URL('https://google.com'); - }catch(e){ - exceptionCaught = true; - } - expect(exceptionCaught).toBe(false); + it("parses simple urls", function () { + const url = new URL("https://google.com"); + expect(url.protocol).toBe("https:"); + expect(url.hostname).toBe("google.com"); + expect(url.pathname).toBe("/"); + expect(url.port).toBe(""); + expect(url.search).toBe(""); + expect(url.hash).toBe(""); + expect(url.username).toBe(""); + expect(url.password).toBe(""); + expect(url.origin).toBe("https://google.com"); + expect(url.searchParams.size).toBe(0); }); + it("parses with undefined base", function () { + const url = new URL("https://google.com", undefined); + expect(url.protocol).toBe("https:"); + expect(url.hostname).toBe("google.com"); + }); - it("Test URL fields", function(){ - var exceptionCaught = false; - const url = new URL('https://google.com'); - expect(url.protocol).toBe('https:'); - expect(url.hostname).toBe('google.com'); + it("parses with null base", function () { + const url = new URL("https://google.com", null); + expect(url.protocol).toBe("https:"); + expect(url.hostname).toBe("google.com"); }); -}); + it("parses query strings", function () { + const url = new URL("https://google.com?q=hello"); + expect(url.search).toBe("?q=hello"); + expect(url.searchParams.get("q")).toBe("hello"); + expect(url.pathname).toBe("/"); + }); + + it("parses query strings with pathname", function () { + const url = new URL("https://google.com/some/path?q=hello"); + expect(url.search).toBe("?q=hello"); + expect(url.searchParams.get("q")).toBe("hello"); + expect(url.pathname).toBe("/some/path"); + }); + }); diff --git a/test-app/app/src/main/assets/app/tests/testURLPattern.js b/test-app/app/src/main/assets/app/tests/testURLPattern.js new file mode 100644 index 00000000..0c2d1c1f --- /dev/null +++ b/test-app/app/src/main/assets/app/tests/testURLPattern.js @@ -0,0 +1,49 @@ + +describe("URLPattern", function () { + it("throws on invalid URLPattern", function () { + var exceptionCaught = false; + try { + const pattern = new URLPattern(1); + } catch (e) { + exceptionCaught = true; + } + expect(exceptionCaught).toBe(true); + }); + + it("does not throw on valid URLPattern", function () { + var exceptionCaught = false; + try { + const pattern = new URLPattern("https://example.com/books/:id"); + } catch (e) { + exceptionCaught = true; + } + expect(exceptionCaught).toBe(false); + }); + + it("parses simple pattern", function () { + const pattern = new URLPattern("https://example.com/books/:id"); + expect(pattern.protocol).toBe("https"); + expect(pattern.hostname).toBe("example.com"); + expect(pattern.pathname).toBe("/books/:id"); + expect(pattern.port).toBe(""); + expect(pattern.search).toBe("*"); + expect(pattern.hash).toBe("*"); + expect(pattern.username).toBe("*"); + expect(pattern.password).toBe("*"); + expect(pattern.hasRegExpGroups).toBe(false); + }); + + + it("parses with undefined base", function () { + const pattern = new URLPattern("https://google.com", undefined); + expect(pattern.protocol).toBe("https"); + expect(pattern.hostname).toBe("google.com"); + }); + + it("parses with null base", function () { + const pattern = new URLPattern("https://google.com", null); + expect(pattern.protocol).toBe("https"); + expect(pattern.hostname).toBe("google.com"); + }); + +}); diff --git a/test-app/app/src/main/assets/app/tests/testURLSearchParamsImpl.js b/test-app/app/src/main/assets/app/tests/testURLSearchParamsImpl.js index 5437250d..b326af9a 100644 --- a/test-app/app/src/main/assets/app/tests/testURLSearchParamsImpl.js +++ b/test-app/app/src/main/assets/app/tests/testURLSearchParamsImpl.js @@ -1,15 +1,16 @@ describe("Test URLSearchParams ", function () { const fooBar = "foo=1&bar=2"; it("Test URLSearchParams keys", function(){ + // keys() returns a spec iterator, not an array — consume it via spread. const params = new URLSearchParams(fooBar); - const keys = params.keys(); + const keys = [...params.keys()]; expect(keys[0]).toBe("foo"); expect(keys[1]).toBe("bar"); }); it("Test URLSearchParams values", function(){ const params = new URLSearchParams(fooBar); - const values = params.values(); + const values = [...params.values()]; expect(values[0]).toBe("1"); expect(values[1]).toBe("2"); }); @@ -17,7 +18,7 @@ describe("Test URLSearchParams ", function () { it("Test URLSearchParams entries", function(){ const params = new URLSearchParams(fooBar); - const entries = params.entries(); + const entries = [...params.entries()]; expect(entries[0][0]).toBe("foo"); expect(entries[0][1]).toBe("1"); @@ -26,6 +27,74 @@ describe("Test URLSearchParams ", function () { }); + it("Test URLSearchParams keys/values/entries return spec iterators", function(){ + const params = new URLSearchParams(fooBar); + // A spec iterator has a next() and is itself iterable. + expect(typeof params.entries().next).toBe("function"); + expect(typeof params.keys().next).toBe("function"); + expect(typeof params.values().next).toBe("function"); + const it = params.entries(); + const first = it.next(); + expect(first.done).toBe(false); + expect(first.value[0]).toBe("foo"); + expect(first.value[1]).toBe("1"); + }); + + it("Test URLSearchParams entries preserves duplicate keys", function(){ + // Regression: the old get_keys()+get() path returned the first value for + // every occurrence of a repeated key. + const params = new URLSearchParams("a=1&a=2&b=3"); + const entries = [...params.entries()]; + expect(entries.length).toBe(3); + expect(entries[0][1]).toBe("1"); + expect(entries[1][1]).toBe("2"); + expect(entries[2][1]).toBe("3"); + expect([...params.values()].join(",")).toBe("1,2,3"); + }); + + it("Test URLSearchParams default iterator aliases entries", function(){ + // The default @@iterator IS the entries method (browser identity). This binding + // installs members per-instance (not on the prototype), so assert on an instance + // AND assert it is actually a function — not the vacuous undefined === undefined. + const params = new URLSearchParams(fooBar); + expect(typeof params[Symbol.iterator]).toBe("function"); + expect(params[Symbol.iterator]).toBe(params.entries); + }); + + it("Test URLSearchParams iterator carries the spec brand", function(){ + const params = new URLSearchParams(fooBar); + expect(Object.prototype.toString.call(params.entries())).toBe("[object URLSearchParams Iterator]"); + }); + + it("Test URLSearchParams iterator is live", function(){ + // Spec iterators reflect mutations made after they are created. + const params = new URLSearchParams("a=1&b=2"); + const it = params.entries(); + expect(it.next().value[0]).toBe("a"); // consume "a" + params.append("c", "3"); // mutate mid-iteration + const rest = []; + let r; + while (!(r = it.next()).done) { + rest.push(r.value[0]); + } + expect(rest.join(",")).toBe("b,c"); // sees the appended "c" + }); + + it("Test URLSearchParams closes the source iterator on a bad pair", function(){ + // On an abrupt completion (a too-long pair) the source iterator must be + // closed, so a generator's finally runs and resource-backed iterables free. + let closed = false; + function* gen() { + try { + yield ["a", "1", "2"]; // 3-element pair → TypeError + } finally { + closed = true; + } + } + expect(function(){ new URLSearchParams(gen()); }).toThrow(); + expect(closed).toBe(true); + }); + it("Test URLSearchParams size", function(){ const params = new URLSearchParams(fooBar); @@ -43,7 +112,27 @@ describe("Test URLSearchParams ", function () { const params = new URLSearchParams(fooBar); params.append("first", "Osei"); params.delete("first"); - expect(params.get("first")).toBe(undefined); + // Spec: get() returns null for a missing name (url.bs:4016). + expect(params.get("first")).toBe(null); + }); + + it("Test URLSearchParams get returns null for a missing name", function(){ + // Spec get(name): "...otherwise null" (url.bs:4016). + const params = new URLSearchParams("a=1"); + expect(params.get("missing")).toBe(null); + }); + + it("Test URLSearchParams delete with value removes only matching pairs", function(){ + // Spec delete(name, value): when value is given, remove only tuples + // matching BOTH name and value (url.bs:4000). The value is a USVString, + // so a non-string (the number 1) coerces to "1". + const params = new URLSearchParams("a=1&a=2&a=1&b=1"); + params.delete("a", 1); + expect(params.getAll("a").join(",")).toBe("2"); + expect(params.getAll("b").join(",")).toBe("1"); + // Single-arg delete still removes every pair with that name. + params.delete("a"); + expect(params.has("a")).toBe(false); }); @@ -52,6 +141,47 @@ describe("Test URLSearchParams ", function () { expect(params.has("foo")).toBe(true); }); + it("Test URLSearchParams has with value matches name and value", function(){ + // Spec has(name, value): true only for a tuple matching BOTH (url.bs:4028). + // The value is a USVString, so non-strings (number, boolean) coerce. + const params = new URLSearchParams("a=1&a=2&flag=true"); + expect(params.has("a", "1")).toBe(true); + expect(params.has("a", 2)).toBe(true); // number coerces to "2" + expect(params.has("a", "3")).toBe(false); + expect(params.has("flag", true)).toBe(true); // boolean coerces to "true" + expect(params.has("missing", "1")).toBe(false); + // Single-arg has still matches by name only. + expect(params.has("a")).toBe(true); + }); + + it("Test URLSearchParams has/delete throw when the value cannot be coerced", function(){ + // The value argument is a USVString; a Symbol (or a throwing toString) + // cannot convert, so the call must throw rather than silently matching "" + // (WebIDL USVString conversion, url.bs:4000 / 4028). + const params = new URLSearchParams("a=1"); + expect(function(){ params.has("a", Symbol("x")); }).toThrow(); + expect(function(){ params.delete("a", Symbol("x")); }).toThrow(); + }); + + it("Test URLSearchParams has/delete treat an explicit undefined value as omitted", function(){ + // Per WPT (urlsearchparams-has / -delete "respects undefined as second + // arg"), an explicit `undefined` second argument is treated as omitted + // (name-only), NOT as the string "undefined". + const params = new URLSearchParams("a=b&a=d&c&e&"); + expect(params.has("a", "b")).toBe(true); + expect(params.has("a", "c")).toBe(false); + expect(params.has("a", undefined)).toBe(true); // undefined -> name-only + + const del = new URLSearchParams(); + del.append("a", "b"); + del.append("a", "c"); + del.append("b", "c"); + del.append("b", "d"); + del.delete("b", "c"); + del.delete("a", undefined); // undefined -> delete by name + expect(del.toString()).toBe("b=d"); + }); + it("Test URLSearchParams changes propagates to URL parent", function(){ const toBe = 'https://github.com/triniwiz?first=Osei'; const url = new URL('https://github.com/triniwiz'); @@ -61,4 +191,332 @@ describe("Test URLSearchParams ", function () { expect(url.toString()).toBe(toBe); }); + it("Test URLSearchParams forEach", function(){ + const params = new URLSearchParams(fooBar); + const results = []; + params.forEach((value, key, searchParams) => { + results.push({ key, value }); + expect(searchParams).toBe(params); + }); + expect(results.length).toBe(2); + expect(results[0].key).toBe("foo"); + expect(results[0].value).toBe("1"); + expect(results[1].key).toBe("bar"); + expect(results[1].value).toBe("2"); + }); + + it("Test URLSearchParams forEach with URL", function(){ + const url = new URL('https://example.com?si=abc123&name=test'); + const results = []; + url.searchParams.forEach((value, key) => { + results.push({ key, value }); + }); + expect(results.length).toBe(2); + expect(results[0].key).toBe("si"); + expect(results[0].value).toBe("abc123"); + expect(results[1].key).toBe("name"); + expect(results[1].value).toBe("test"); + }); + + it("Test URLSearchParams forEach with thisArg", function(){ + const params = new URLSearchParams(fooBar); + const context = { results: [] }; + params.forEach(function(value, key) { + this.results.push({ key, value }); + }, context); + expect(context.results.length).toBe(2); + expect(context.results[0].key).toBe("foo"); + expect(context.results[0].value).toBe("1"); + }); + + it("Test URLSearchParams forEach with duplicate keys", function(){ + const params = new URLSearchParams("foo=1&foo=2&bar=3"); + const results = []; + params.forEach((value, key) => { + results.push({ key, value }); + }); + expect(results.length).toBe(3); + expect(results[0].key).toBe("foo"); + expect(results[0].value).toBe("1"); + expect(results[1].key).toBe("foo"); + expect(results[1].value).toBe("2"); + expect(results[2].key).toBe("bar"); + expect(results[2].value).toBe("3"); + }); + + it("Test URLSearchParams from record object", function(){ + const params = new URLSearchParams({ foo: "1", bar: "2" }); + expect(params.get("foo")).toBe("1"); + expect(params.get("bar")).toBe("2"); + expect(params.size).toBe(2); + // A plain object must expand to its entries, not collapse into a + // single "[object Object]" key. + expect(params.has("[object Object]")).toBe(false); + }); + + it("Test URLSearchParams from record serializes every pair in toString", function(){ + const params = new URLSearchParams({ one: "1", two: "2" }); + expect(params.toString()).toBe("one=1&two=2"); + }); + + it("Test URLSearchParams from record coerces values to strings", function(){ + const params = new URLSearchParams({ a: 1, b: true }); + expect(params.get("a")).toBe("1"); + expect(params.get("b")).toBe("true"); + }); + + it("Test URLSearchParams from record encodes special characters", function(){ + const params = new URLSearchParams({ q: "a b&c" }); + expect(params.get("q")).toBe("a b&c"); + expect(params.toString()).toBe("q=a+b%26c"); + }); + + it("Test URLSearchParams from array of pairs", function(){ + const params = new URLSearchParams([["foo", "1"], ["bar", "2"], ["foo", "3"]]); + expect(params.get("foo")).toBe("1"); + expect(params.getAll("foo").length).toBe(2); + expect(params.get("bar")).toBe("2"); + expect(params.size).toBe(3); + }); + + it("Test URLSearchParams empty record and no-arg produce empty query", function(){ + expect(new URLSearchParams().toString()).toBe(""); + expect(new URLSearchParams({}).toString()).toBe(""); + }); + + it("Test URLSearchParams from record throws when a value cannot be coerced to a string", function(){ + // Per spec the record/sequence init coerces every value to a USVString; + // a value that cannot convert (a Symbol here) must throw rather than + // silently dropping or emptying the entry. + expect(function(){ new URLSearchParams({ bad: Symbol("x") }); }).toThrow(); + }); + + // --- Iterable (sequence) init: any iterable of pairs, not only arrays. --- + + it("Test URLSearchParams from a Map", function(){ + const params = new URLSearchParams(new Map([["a", "1"], ["b", "2"]])); + expect(params.toString()).toBe("a=1&b=2"); + }); + + it("Test URLSearchParams from a Set of pairs", function(){ + const params = new URLSearchParams(new Set([["x", "1"], ["y", "2"]])); + expect(params.toString()).toBe("x=1&y=2"); + }); + + it("Test URLSearchParams copy-constructs from another URLSearchParams", function(){ + // A URLSearchParams is iterable, so per spec it resolves to the sequence + // (copy) form — including duplicate keys, which proves the @@iterator walks + // entries rather than collapsing them. + const source = new URLSearchParams("a=1&a=2&b=3"); + const copy = new URLSearchParams(source); + expect(copy.toString()).toBe("a=1&a=2&b=3"); + expect(copy.getAll("a").length).toBe(2); + }); + + it("Test URLSearchParams from a generator of pairs", function(){ + function* pairs() { + yield ["a", "1"]; + yield ["b", "2"]; + } + const params = new URLSearchParams(pairs()); + expect(params.toString()).toBe("a=1&b=2"); + }); + + it("Test URLSearchParams from sequence with non-array inner pairs", function(){ + // Each pair need only be a 2-element iterable, not specifically an array. + // A Set is iterable but not an Array, so it exercises the inner iterator path. + const params = new URLSearchParams([new Set(["k", "v"])]); + expect(params.get("k")).toBe("v"); + }); + + it("Test URLSearchParams sequence init throws on a too-long pair", function(){ + expect(function(){ new URLSearchParams([["a", "1", "2"]]); }).toThrow(); + }); + + it("Test URLSearchParams sequence init throws on a too-short pair", function(){ + expect(function(){ new URLSearchParams([["a"]]); }).toThrow(); + }); + + it("Test URLSearchParams sequence init throws on a non-iterable element", function(){ + expect(function(){ new URLSearchParams([null]); }).toThrow(); + expect(function(){ new URLSearchParams([1]); }).toThrow(); + }); + + it("Test URLSearchParams sequence init throws on a primitive string element", function(){ + // WebIDL converts each element to sequence, whose first step throws + // when the element is not an Object. A 2-code-point string must NOT be accepted + // as the pair ("a","b"). + expect(function(){ new URLSearchParams(["ab"]); }).toThrow(); + }); + + it("Test URLSearchParams sequence init accepts a String-object element", function(){ + // A String *object* IS an Object and is iterable, so it is a valid 2-char pair. + const params = new URLSearchParams([new String("ab")]); + expect(params.get("a")).toBe("b"); + }); + + it("Test URLSearchParams throws when @@iterator is present but not callable", function(){ + // Per WebIDL GetMethod, a non-callable @@iterator is a TypeError, not a + // silent fall-back to the record form. + expect(function(){ new URLSearchParams({ [Symbol.iterator]: 5 }); }).toThrow(); + }); + + // --- The type itself is iterable. --- + + it("Test URLSearchParams is spread-iterable via Symbol.iterator", function(){ + const params = new URLSearchParams("a=1&b=2"); + const entries = [...params]; + expect(entries.length).toBe(2); + expect(entries[0][0]).toBe("a"); + expect(entries[0][1]).toBe("1"); + expect(entries[1][0]).toBe("b"); + expect(entries[1][1]).toBe("2"); + }); + + it("Test URLSearchParams works in a for..of loop", function(){ + const params = new URLSearchParams("a=1&a=2"); + const seen = []; + for (const [key, value] of params) { + seen.push(key + "=" + value); + } + expect(seen.length).toBe(2); + expect(seen[0]).toBe("a=1"); + expect(seen[1]).toBe("a=2"); + }); + + // --- Primitive init: coerced to USVString, then parsed. --- + + it("Test URLSearchParams from a number", function(){ + expect(new URLSearchParams(123).toString()).toBe("123="); + }); + + it("Test URLSearchParams from a boolean", function(){ + expect(new URLSearchParams(true).toString()).toBe("true="); + }); + + it("Test URLSearchParams from a bigint", function(){ + expect(new URLSearchParams(10n).toString()).toBe("10="); + }); + + it("Test URLSearchParams strips a single leading question mark", function(){ + expect(new URLSearchParams("?a=1").get("a")).toBe("1"); + }); + + it("Test URLSearchParams throws when init is a Symbol", function(){ + expect(function(){ new URLSearchParams(Symbol("x")); }).toThrow(); + }); + + it("Test URLSearchParams from undefined or no argument is empty", function(){ + expect(new URLSearchParams(undefined).toString()).toBe(""); + expect(new URLSearchParams().toString()).toBe(""); + }); + + it("Test URLSearchParams from null parses as the string null", function(){ + // The IDL union has no null special case (the type is not nullable and + // a record is not a dictionary), so null coerces like any primitive. + const params = new URLSearchParams(null); + expect(params.toString()).toBe("null="); + expect(params.get("null")).toBe(""); + }); + + it("Test URLSearchParams throws when a record key is a Symbol", function(){ + // Per WebIDL record conversion every own enumerable key is converted to + // a USVString, and converting a Symbol throws. + expect(function(){ new URLSearchParams({ a: "1", [Symbol("x")]: "v" }); }).toThrow(); + }); + + // --- The name argument is a USVString: coerced, not assumed. --- + + it("Test URLSearchParams coerces a non-string name in get/getAll/has/delete", function(){ + const params = new URLSearchParams("1=a&true=b&null=c"); + expect(params.get(1)).toBe("a"); + expect(params.getAll(1).length).toBe(1); + expect(params.getAll(1)[0]).toBe("a"); + expect(params.has(true)).toBe(true); + expect(params.get(null)).toBe("c"); + params.delete(true); + expect(params.has("true")).toBe(false); + expect(params.has("1")).toBe(true); + }); + + it("Test URLSearchParams coerces an object name via toString", function(){ + const params = new URLSearchParams("a=1"); + const name = { toString: function(){ return "a"; } }; + expect(params.get(name)).toBe("1"); + expect(params.has(name)).toBe(true); + params.delete(name); + expect(params.has("a")).toBe(false); + }); + + it("Test URLSearchParams throws when the name is a Symbol", function(){ + const params = new URLSearchParams("a=1"); + expect(function(){ params.get(Symbol("x")); }).toThrow(); + expect(function(){ params.getAll(Symbol("x")); }).toThrow(); + expect(function(){ params.has(Symbol("x")); }).toThrow(); + expect(function(){ params.delete(Symbol("x")); }).toThrow(); + expect(params.get("a")).toBe("1"); + }); + + it("Test URLSearchParams coerces non-string arguments in append and set", function(){ + const params = new URLSearchParams(); + params.append(1, 2); + expect(params.get("1")).toBe("2"); + params.set(true, { toString: function(){ return "x"; } }); + expect(params.get("true")).toBe("x"); + params.append("a", null); + expect(params.get("a")).toBe("null"); + }); + + it("Test URLSearchParams append and set throw when an argument is a Symbol", function(){ + const params = new URLSearchParams("a=1"); + expect(function(){ params.append(Symbol("x"), "v"); }).toThrow(); + expect(function(){ params.append("k", Symbol("x")); }).toThrow(); + expect(function(){ params.set(Symbol("x"), "v"); }).toThrow(); + expect(function(){ params.set("k", Symbol("x")); }).toThrow(); + // Nothing was appended or replaced by the failed calls. + expect(params.toString()).toBe("a=1"); + }); + + // --- Brand checks: iterators require a genuine receiver. --- + + it("Test URLSearchParams entries/keys/values throw on a foreign receiver", function(){ + const params = new URLSearchParams("a=1"); + expect(function(){ params.entries.call({}); }).toThrow(); + expect(function(){ params.keys.call({}); }).toThrow(); + expect(function(){ params.values.call({}); }).toThrow(); + }); + + it("Test URLSearchParams methods throw on a foreign receiver", function(){ + const params = new URLSearchParams("a=1"); + expect(function(){ params.get.call({}, "a"); }).toThrow(); + expect(function(){ params.getAll.call({}, "a"); }).toThrow(); + expect(function(){ params.has.call({}, "a"); }).toThrow(); + expect(function(){ params.append.call({}, "a", "b"); }).toThrow(); + expect(function(){ params.set.call({}, "a", "b"); }).toThrow(); + expect(function(){ params.delete.call({}, "a"); }).toThrow(); + expect(function(){ params.forEach.call({}, function(){}); }).toThrow(); + expect(function(){ params.sort.call({}); }).toThrow(); + expect(function(){ params.toString.call({}); }).toThrow(); + }); + + it("Test URLSearchParams iterator next() throws on a foreign receiver", function(){ + const params = new URLSearchParams("a=1"); + const iterator = params.entries(); + const next = iterator.next; + expect(function(){ next.call({}); }).toThrow(); + // The iterator keeps working when invoked correctly afterwards. + const first = iterator.next(); + expect(first.done).toBe(false); + expect(first.value[0]).toBe("a"); + }); + + it("Test URLSearchParams entries retargets to another instance receiver", function(){ + const a = new URLSearchParams("a=1"); + const b = new URLSearchParams("b=2"); + const entries = [...a.entries.call(b)]; + expect(entries.length).toBe(1); + expect(entries[0][0]).toBe("b"); + expect(entries[0][1]).toBe("2"); + }); + }); diff --git a/test-app/app/src/main/assets/internal/ts_helpers.js b/test-app/app/src/main/assets/internal/ts_helpers.js index 83823ac8..0ebe1720 100644 --- a/test-app/app/src/main/assets/internal/ts_helpers.js +++ b/test-app/app/src/main/assets/internal/ts_helpers.js @@ -12,10 +12,10 @@ d; if ( - typeof global.Reflect === "object" && - typeof global.Reflect.decorate === "function" + typeof globalThis.Reflect === "object" && + typeof globalThis.Reflect.decorate === "function" ) { - r = global.Reflect.decorate(decorators, target, key, desc); + r = globalThis.Reflect.decorate(decorators, target, key, desc); } else { for (var i = decorators.length - 1; i >= 0; i--) { if ((d = decorators[i])) { @@ -56,6 +56,7 @@ var __extends = function (Child, Parent) { var extendNativeClass = !!Parent.extend && Parent.extend.toString().indexOf("[native code]") > -1; + if (!extendNativeClass) { __extends_ts(Child, Parent); return; @@ -189,82 +190,25 @@ } }; } + Object.defineProperty(globalThis, "__native", { value: __native }); + Object.defineProperty(globalThis, "__extends", { value: __extends }); + Object.defineProperty(globalThis, "__decorate", { value: __decorate }); - Object.defineProperty(global, "__native", { value: __native }); - Object.defineProperty(global, "__extends", { value: __extends }); - Object.defineProperty(global, "__decorate", { value: __decorate }); - if (!global.__ns__worker) { - global.JavaProxy = JavaProxy; - } - global.Interfaces = Interfaces; - if (global.WeakRef && !global.WeakRef.prototype.get) { - global.WeakRef.prototype.get = global.WeakRef.prototype.deref; + if (!globalThis.__ns__worker) { + globalThis.JavaProxy = JavaProxy; } + globalThis.Interfaces = Interfaces; - global.setNativeArrayProp = (target, prop, value, receiver) => { - if (typeof prop !== "symbol" && !isNaN(prop)) { - receiver.setValueAtIndex(parseInt(prop), value); - return true; - } - target[prop] = value; - return true; - }; - - global.getNativeArrayProp = (target, prop, receiver) => { - if (typeof prop !== "symbol" && !isNaN(prop)) { - return receiver.getValueAtIndex(parseInt(prop)); - } - - if (prop === Symbol.iterator) { - var index = 0; - const l = target.length; - return function () { - return { - next: function () { - if (index < l) { - return { - value: receiver.getValueAtIndex(index++), - done: false, - }; - } else { - return { done: true }; - } - }, - }; - }; - } - if (prop === "map") { - return function (callback) { - const values = receiver.getAllValues(); - const result = []; - const l = target.length; - for (var i = 0; i < l; i++) { - result.push(callback(values[i], i, target)); - } - return result; - }; - } - - if (prop === "toString") { - return function () { - const result = receiver.getAllValues(); - return result.join(","); - }; - } + if (globalThis.WeakRef && !globalThis.WeakRef.prototype.get) { + globalThis.WeakRef.prototype.get = globalThis.WeakRef.prototype.deref; + } - if (prop === "forEach") { - return function (callback) { - const values = receiver.getAllValues(); - const l = values.length; - for (var i = 0; i < l; i++) { - callback(values[i], i, target); - } - }; - } - return target[prop]; - }; + // Native array access: numeric indexing and the map/forEach/toString/ + // Symbol.iterator helpers are now implemented natively (see MetadataNode's + // array prototype + the host object's indexed accessors), so the old JS + // getNativeArrayProp/setNativeArrayProp helpers are gone. function findInPrototypeChain(obj, prop) { while (obj) { @@ -292,8 +236,11 @@ get: function (target, prop) { if (prop === EXTERNAL_PROP) return this[EXTERNAL_PROP]; if (prop === REFERENCE_PROP_JSC) return this[REFERENCE_PROP_JSC]; - if (target.__is__javaArray) { - return global.getNativeArrayProp(target, prop, target); + // Numeric indices go straight to the native element accessor; the + // map/forEach/toString/Symbol.iterator helpers live on the array + // prototype now, so everything else just forwards to the target. + if (target.__is__javaArray && typeof prop !== "symbol" && !isNaN(prop)) { + return target.getValueAtIndex(parseInt(prop)); } return target[prop]; }, diff --git a/test-app/app/src/main/java/com/tns/AndroidJsV8Inspector.java b/test-app/app/src/main/java/com/tns/AndroidJsV8Inspector.java index 1a285e19..d1cb270b 100644 --- a/test-app/app/src/main/java/com/tns/AndroidJsV8Inspector.java +++ b/test-app/app/src/main/java/com/tns/AndroidJsV8Inspector.java @@ -37,6 +37,8 @@ class AndroidJsV8Inspector { protected native final void dispatchMessage(String message); + private native String handleMessageOnSocketThread(String message); + private Handler mainHandler; private final Object debugBrkLock; @@ -294,6 +296,27 @@ protected void onMessage(final NanoWSD.WebSocketFrame message) { Log.d("Inspector", "To dbg backend: " + message.getTextPayload() + " ThreadId:" + Thread.currentThread().getId()); } + // Network.loadNetworkResource / IO.read / IO.close are served from + // disk on this thread so source maps load even while the isolate is + // paused at a breakpoint or busy running JS; Target domain commands + // and worker-session messages (top-level sessionId) are routed here + // too. Debugger.pause schedules a V8 interrupt and still flows + // through the queue. A null return means "not handled" (queue it); + // an empty string means handled with nothing left to send. + String fastPathResponse = handleMessageOnSocketThread(message.getTextPayload()); + if (fastPathResponse != null) { + if (!fastPathResponse.isEmpty()) { + try { + send(fastPathResponse); + } catch (IOException e) { + if (com.tns.Runtime.isDebuggable()) { + e.printStackTrace(); + } + } + } + return; + } + inspectorMessages.offer(message.getTextPayload()); if (!AndroidJsV8Inspector.ReadyToProcessMessages.get()) { diff --git a/test-app/app/src/main/java/com/tns/RuntimeHelper.java b/test-app/app/src/main/java/com/tns/RuntimeHelper.java index 90a64f16..fa154296 100644 --- a/test-app/app/src/main/java/com/tns/RuntimeHelper.java +++ b/test-app/app/src/main/java/com/tns/RuntimeHelper.java @@ -123,6 +123,18 @@ public static Runtime initRuntime(Context context) { ClassLoader classLoader = context.getClassLoader(); File dexDir = new File(rootDir, "code_cache/secondary-dexes"); + if (!dexDir.exists()) { + dexDir.mkdirs(); + } + if (!dexDir.exists() || !dexDir.canWrite()) { + if (logger.isEnabled()) { + logger.write("Unable to use dex dir: " + dexDir.getAbsolutePath() + ", falling back to files/secondary-dexes"); + } + dexDir = new File(appDir, "secondary-dexes"); + if (!dexDir.exists()) { + dexDir.mkdirs(); + } + } String dexThumb = null; try { dexThumb = Util.getDexThumb(context); diff --git a/test-app/app/src/main/java/com/tns/tests/ConcurrentAccessTest.java b/test-app/app/src/main/java/com/tns/tests/ConcurrentAccessTest.java new file mode 100644 index 00000000..acd9d853 --- /dev/null +++ b/test-app/app/src/main/java/com/tns/tests/ConcurrentAccessTest.java @@ -0,0 +1,76 @@ +package com.tns.tests; + +import java.util.ArrayList; + +public class ConcurrentAccessTest { + + public interface Callback { + void invoke(ArrayList list1, ArrayList list2, ArrayList list3, ArrayList list4, ArrayList list5, + ArrayList list6, ArrayList list7, ArrayList list8, ArrayList list9, ArrayList list10); + } + + public interface ErrorCallback { + void onError(Throwable error); + } + + /** + * Calls the callback from a background thread multiple times. + * @param callback The callback to invoke + * @param times Number of times to call the callback (default 50) + */ + public static void callFromBackgroundThread(final Callback callback, final int times) { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < times; i++) { + invokeCallbackWithArrayLists(callback, i); + } + } + }); + thread.start(); + } + + /** + * Calls the callback synchronously from the current thread. + * @param callback The callback to invoke + * @param times Number of times to call the callback (default 50) + */ + public static void callSynchronously(Callback callback, int times) { + for (int i = 0; i < times; i++) { + invokeCallbackWithArrayLists(callback, i); + } + } + + /** + * Helper method that creates 10 ArrayLists and invokes the callback with them. + * Each ArrayList contains some data based on the iteration number. + */ + private static void invokeCallbackWithArrayLists(Callback callback, int iteration) { + ArrayList list1 = new ArrayList<>(); + ArrayList list2 = new ArrayList<>(); + ArrayList list3 = new ArrayList<>(); + ArrayList list4 = new ArrayList<>(); + ArrayList list5 = new ArrayList<>(); + ArrayList list6 = new ArrayList<>(); + ArrayList list7 = new ArrayList<>(); + ArrayList list8 = new ArrayList<>(); + ArrayList list9 = new ArrayList<>(); + ArrayList list10 = new ArrayList<>(); + + // Add some data to each list + for (int i = 0; i < 5; i++) { + list1.add(iteration * 10 + i); + list2.add(iteration * 10 + i + 1); + list3.add(iteration * 10 + i + 2); + list4.add(iteration * 10 + i + 3); + list5.add(iteration * 10 + i + 4); + list6.add(iteration * 10 + i + 5); + list7.add(iteration * 10 + i + 6); + list8.add(iteration * 10 + i + 7); + list9.add(iteration * 10 + i + 8); + list10.add(iteration * 10 + i + 9); + } + + callback.invoke(list1, list2, list3, list4, list5, list6, list7, list8, list9, list10); + } +} \ No newline at end of file diff --git a/test-app/app/src/main/java/com/tns/tests/kotlin/companions/KotlinEnumClassWithCompanionWithNestedClass.kt b/test-app/app/src/main/java/com/tns/tests/kotlin/companions/KotlinEnumClassWithCompanionWithNestedClass.kt new file mode 100644 index 00000000..0934c40c --- /dev/null +++ b/test-app/app/src/main/java/com/tns/tests/kotlin/companions/KotlinEnumClassWithCompanionWithNestedClass.kt @@ -0,0 +1,28 @@ +package com.tns.tests.kotlin.companions + +import com.tns.tests.kotlin.SimpleKotlinObject + + +enum class KotlinEnumClassWithCompanionWithNestedClass { + TEST_ENTRY; + + companion object { + fun getStringFromCompanion(): String = "testCompanion" + fun getProvidedStringFromCompanion(providedString: String) = providedString + + fun getSimpleObjectFromCompanion(): SimpleKotlinObject = SimpleKotlinObject() + fun getProvidedSimpleObjectFromCompanion(providedSimpleObject: SimpleKotlinObject) = + providedSimpleObject + + @JvmStatic + fun getStringJvmStaticFromCompanion(): String = "testCompanion" + + @JvmStatic + fun getProvidedStringJvmStaticFromCompanion(providedString: String) = providedString + + class TestClass { + + } + } + +} diff --git a/test-app/app/src/main/java/com/tns/tests/kotlin/companions/KotlinEnumClassWithNamedCompanionWithNestedClass.kt b/test-app/app/src/main/java/com/tns/tests/kotlin/companions/KotlinEnumClassWithNamedCompanionWithNestedClass.kt new file mode 100644 index 00000000..e3abc190 --- /dev/null +++ b/test-app/app/src/main/java/com/tns/tests/kotlin/companions/KotlinEnumClassWithNamedCompanionWithNestedClass.kt @@ -0,0 +1,29 @@ +package com.tns.tests.kotlin.companions + +import com.tns.tests.kotlin.SimpleKotlinObject + +enum class KotlinEnumClassWithNamedCompanionWithNestedClass { + TEST_ENTRY; + + companion object NamedCompanion { + fun getStringFromNamedCompanion(): String = "testCompanion" + fun getProvidedStringFromNamedCompanion(providedString: String) = providedString + + fun getSimpleObjectFromNamedCompanion(): SimpleKotlinObject = SimpleKotlinObject() + fun getProvidedSimpleObjectFromNamedCompanion(providedSimpleObject: SimpleKotlinObject) = + providedSimpleObject + + @JvmStatic + fun getStringJvmStaticFromNamedCompanion(): String = "testCompanion" + + @JvmStatic + fun getProvidedStringJvmStaticFromNamedCompanion(providedString: String) = + providedString + + + class TestClass { + + } + } + +} \ No newline at end of file diff --git a/test-app/build-tools/android-metadata-generator/build.gradle b/test-app/build-tools/android-metadata-generator/build.gradle index 655af1f0..85ca0723 100644 --- a/test-app/build-tools/android-metadata-generator/build.gradle +++ b/test-app/build-tools/android-metadata-generator/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'java' apply plugin: 'kotlin' java { - sourceCompatibility = '17' - targetCompatibility = '17' + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } // todo: check if still needed diff --git a/test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/Builder.java b/test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/Builder.java index 23e2a4db..6c46b9cb 100644 --- a/test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/Builder.java +++ b/test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/Builder.java @@ -456,6 +456,30 @@ private static TreeNode getOrCreateNode(TreeNode root, NativeClassDescriptor cla for (int i = outerClasses.size() - 1; i >= 0; i--) { outer = outerClasses.get(i); String outerClassname = ClassUtil.getSimpleName(outer); + + // A Kotlin companion object is stored as a package-level sibling + // node named "$" (see createCompanionNode), + // not as a direct child. When the companion itself declares nested + // classes, those nested classes carry the companion in their outer + // chain. Descend into the companion sibling here instead of calling + // createChild, which would create a shadow "" child that + // hides the real companion node and drops its members. + NativeClassDescriptor outerEnclosing = ClassUtil.getEnclosingClass(outer); + if (node.parentNode != null && isNestedClassKotlinCompanionObject(outerEnclosing, outer)) { + String companionNodeName = node.getName() + "$" + outerClassname; + TreeNode companionChild = node.parentNode.getChild(companionNodeName); + if (companionChild == null) { + companionChild = node.createCompanionNode(outerClassname); + companionChild.nodeType = outer.isInterface() ? TreeNode.Interface + : TreeNode.Class; + if (outer.isStatic()) { + companionChild.nodeType |= TreeNode.Static; + } + } + node = companionChild; + continue; + } + TreeNode child = node.getChild(outerClassname); if (child == null) { child = node.createChild(outerClassname); @@ -470,8 +494,15 @@ private static TreeNode getOrCreateNode(TreeNode root, NativeClassDescriptor cla } TreeNode child = node.getChild(name); + boolean clazzIsCompanion = isNestedClassKotlinCompanionObject(outer, clazz); + if (child == null && clazzIsCompanion && node.parentNode != null) { + // The companion may already have been created as a package-level + // sibling if one of its nested classes was processed first; reuse it + // instead of creating a duplicate companion node. + child = node.parentNode.getChild(node.getName() + "$" + name); + } if (child == null) { - if (isNestedClassKotlinCompanionObject(outer, clazz)) { + if (clazzIsCompanion) { child = node.createCompanionNode(name); } else { child = node.createChild(name); diff --git a/test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/parsing/kotlin/classes/KotlinClassDescriptor.kt b/test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/parsing/kotlin/classes/KotlinClassDescriptor.kt index 43e6bf27..5343cf1f 100644 --- a/test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/parsing/kotlin/classes/KotlinClassDescriptor.kt +++ b/test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/parsing/kotlin/classes/KotlinClassDescriptor.kt @@ -62,9 +62,9 @@ class KotlinClassDescriptor(nativeClass: JavaClass, private val metadataAnnotati fields.add(possibleObjectInstanceField.get()) } - if (metaClass.enumEntries.isNotEmpty()) { - - val enumFields = getEnumEntriesAsFields(nativeClass, metaClass.enumEntries) + if (metaClass.kmEnumEntries.isNotEmpty()) { + val enums: Collection = metaClass.kmEnumEntries.map { it.name } + val enumFields = getEnumEntriesAsFields(nativeClass, enums) fields.addAll(enumFields) } diff --git a/test-app/build-tools/jsparser/js_parser.js b/test-app/build-tools/jsparser/js_parser.js index 5d5839fe..c50732c0 100644 --- a/test-app/build-tools/jsparser/js_parser.js +++ b/test-app/build-tools/jsparser/js_parser.js @@ -196,6 +196,9 @@ function traverseAndAnalyseFilesDir(inputDir, err) { } function traverseFiles(filesToTraverse) { + if (filesToTraverse.length === 0) { + throw "no file was found in " + inputDir + ". Something must be wrong with the webpack build"; + } for (let i = 0; i < filesToTraverse.length; i += 1) { const fp = filesToTraverse[i]; logger.info("Visiting JavaScript file: " + fp); diff --git a/test-app/build-tools/jsparser/visitors/es5-visitors.js b/test-app/build-tools/jsparser/visitors/es5-visitors.js index 2648eac8..44604c55 100644 --- a/test-app/build-tools/jsparser/visitors/es5-visitors.js +++ b/test-app/build-tools/jsparser/visitors/es5-visitors.js @@ -657,6 +657,20 @@ var es5_visitors = (function () { * HELPER METHODS */ + // Returns the Identifier name of a property's key, or null when the property + // is a SpreadElement, has a computed key, or uses a non-Identifier key + // (e.g. StringLiteral, NumericLiteral). Such properties cannot be mapped to + // a Java method binding, so callers should skip them. + function _getIdentifierKeyName(property) { + if (!property || property.computed) { + return null; + } + if (!property.key || !types.isIdentifier(property.key)) { + return null; + } + return property.key.name; + } + function getTypeScriptExtendSuperCallLocation(extendPath, config) { var constructorFunctionName; var returnIdentifierName; @@ -862,7 +876,11 @@ var es5_visitors = (function () { var objectProperties = node.properties; for (var index in objectProperties) { - overriddenMethodNames.push(objectProperties[index].key.name); + var keyName = _getIdentifierKeyName(objectProperties[index]); + if (keyName === null) { + continue; + } + overriddenMethodNames.push(keyName); } } @@ -897,10 +915,19 @@ var es5_visitors = (function () { will get 'method1' and 'method3' */ for (var index in objectProperties) { + var keyName = _getIdentifierKeyName(objectProperties[index]); + // Skip spreads, computed keys, and non-Identifier keys — they cannot be + // statically mapped to a Java binding. Without this guard, valid (non-NS) + // `.extend({ ...other, foo })` calls in bundled vendor code (e.g. Zod + // schemas) would crash the parser. + if (keyName === null) { + continue; + } + // if the user has declared interfaces that he is implementing if ( !interfacesFound && - objectProperties[index].key.name.toLowerCase() === "interfaces" && + keyName.toLowerCase() === "interfaces" && types.isArrayExpression(objectProperties[index].value) ) { interfacesFound = true; @@ -913,7 +940,7 @@ var es5_visitors = (function () { implementedInterfaces.push(interfaceName); } } else { - overriddenMethodNames.push(objectProperties[index].key.name); + overriddenMethodNames.push(keyName); } } } diff --git a/test-app/build-tools/jsparser/webpack.config.js b/test-app/build-tools/jsparser/webpack.config.js index f335f249..e2667f02 100644 --- a/test-app/build-tools/jsparser/webpack.config.js +++ b/test-app/build-tools/jsparser/webpack.config.js @@ -12,4 +12,5 @@ module.exports = { path: path.join(__dirname, "build"), filename: "js_parser.js", }, + devtool: false }; diff --git a/test-app/gradle.properties b/test-app/gradle.properties index 59473d4a..6e262547 100644 --- a/test-app/gradle.properties +++ b/test-app/gradle.properties @@ -21,8 +21,8 @@ android.enableJetifier=true android.useAndroidX=true # Default versions used throughout the gradle configurations -NS_DEFAULT_BUILD_TOOLS_VERSION=34.0.0 -NS_DEFAULT_COMPILE_SDK_VERSION=34 +NS_DEFAULT_BUILD_TOOLS_VERSION=35.0.0 +NS_DEFAULT_COMPILE_SDK_VERSION=35 NS_DEFAULT_MIN_SDK_VERSION=21 NS_DEFAULT_ANDROID_BUILD_TOOLS_VERSION=8.12.1 @@ -41,8 +41,8 @@ ns_default_google_java_format_version=1.6 ns_default_gson_version=2.10.1 ns_default_json_version=20180813 ns_default_junit_version=4.13.2 -ns_default_kotlin_version=2.0.0 -ns_default_kotlinx_metadata_jvm_version=2.0.0 +ns_default_kotlin_version=2.2.20 +ns_default_kotlinx_metadata_jvm_version=2.2.20 ns_default_mockito_core_version=3.0.0 ns_default_spotbugs_version=3.1.12 diff --git a/test-app/runtime-binding-generator/build.gradle b/test-app/runtime-binding-generator/build.gradle index d98d8376..d7f20b31 100644 --- a/test-app/runtime-binding-generator/build.gradle +++ b/test-app/runtime-binding-generator/build.gradle @@ -7,8 +7,8 @@ dependencies { } java { - sourceCompatibility = '17' - targetCompatibility = '17' + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } // Disable compilation tasks as these are compiled *with* the runtime and not separately diff --git a/test-app/runtime-binding-generator/src/main/java/com/tns/bindings/ProxyGenerator.java b/test-app/runtime-binding-generator/src/main/java/com/tns/bindings/ProxyGenerator.java index 546b4259..52506fbd 100644 --- a/test-app/runtime-binding-generator/src/main/java/com/tns/bindings/ProxyGenerator.java +++ b/test-app/runtime-binding-generator/src/main/java/com/tns/bindings/ProxyGenerator.java @@ -58,6 +58,10 @@ public String generateProxy(String proxyName, ClassDescriptor classToProxy, Hash private String saveProxy(String proxyName, byte[] proxyBytes) throws IOException { File file = new File(path + File.separator + proxyName + ".dex"); + File parentDir = file.getParentFile(); + if (parentDir != null && !parentDir.exists()) { + parentDir.mkdirs(); + } file.createNewFile(); FileOutputStream stream = new FileOutputStream(file); stream.write(proxyBytes); diff --git a/test-app/runtime/CMakeLists.txt b/test-app/runtime/CMakeLists.txt index e9c4f1ca..528fdd5b 100644 --- a/test-app/runtime/CMakeLists.txt +++ b/test-app/runtime/CMakeLists.txt @@ -21,13 +21,14 @@ endif () set(COMMON_CMAKE_ARGUMENTS "-Wno-error -Wno-deprecated-declarations -Wno-unused-result -mstackrealign -fexceptions -fno-builtin-stpcpy") set(MI_OVERRIDE OFF) -if (V8_13) - set(COMMON_CMAKE_ARGUMENTS "${COMMON_CMAKE_ARGUMENTS} -std=c++20") -elseif () - set(COMMON_CMAKE_ARGUMENTS "${COMMON_CMAKE_ARGUMENTS} -std=c++17") -endif () +# All engines build with C++20: the vendored ada 3.3.0 (used by the URL module, +# compiled for every engine) requires C++20 (std::endian, concepts). Previously +# only V8_13 got -std=c++20 (and the empty `elseif ()` set nothing for the rest), +# so non-V8-13 engine builds failed on ada.h. +set(COMMON_CMAKE_ARGUMENTS "${COMMON_CMAKE_ARGUMENTS} -std=c++20") -if (SHERMES) +if (HERMES) + # Hermes/JSI headers require RTTI. set(COMMON_CMAKE_ARGUMENTS "${COMMON_CMAKE_ARGUMENTS} -frtti") else () set(COMMON_CMAKE_ARGUMENTS "${COMMON_CMAKE_ARGUMENTS} -fno-rtti") @@ -77,6 +78,8 @@ include_directories( src/main/cpp/runtime/sighandler src/main/cpp/runtime/timers src/main/cpp/runtime/util + # workers: native worker threading & messaging (WorkerWrapper, ConcurrentQueue, LooperTasks) + src/main/cpp/runtime/workers src/main/cpp/runtime/jsonhelper src/main/cpp/runtime/version src/main/cpp/runtime/weakref @@ -86,6 +89,7 @@ include_directories( ) # Search for all CPP files in runtime/ directory and add them to our sources +# (includes runtime/inspector/WorkerInspectorClient.cpp for the V8 worker inspector) file(GLOB_RECURSE RUNTIME_FILES "${PROJECT_SOURCE_DIR}/src/main/cpp/runtime/*.cpp" "${PROJECT_SOURCE_DIR}/src/main/cpp/runtime/**/*.cpp" @@ -95,6 +99,7 @@ file(GLOB_RECURSE MODULE_FILES "${PROJECT_SOURCE_DIR}/src/main/cpp/modules/*.cpp" "${PROJECT_SOURCE_DIR}/src/main/cpp/modules/**/*.cpp" ) +# modules/url: URL, URLSearchParams, URLPattern (backed by vendored ada) set(SOURCES ${RUNTIME_FILES} ${MODULE_FILES}) @@ -109,7 +114,6 @@ if (QUICKJS OR QUICKJS_NG) set(SOURCES ${SOURCES} # quickjs - ${QJS_SOURCE_DIR}/cutils.c ${QJS_SOURCE_DIR}/libregexp.c ${QJS_SOURCE_DIR}/libunicode.c ${QJS_SOURCE_DIR}/quickjs.c @@ -121,6 +125,12 @@ if (QUICKJS OR QUICKJS_NG) ) + if (NOT QUICKJS_NG) + set(SOURCES ${SOURCES} + ${QJS_SOURCE_DIR}/cutils.c + ) + endif () + include_directories( src/main/cpp/napi/quickjs ${QJS_SOURCE_DIR} @@ -135,9 +145,8 @@ endif () if (PRIMJS) set(SOURCES ${SOURCES} src/main/cpp/napi/primjs/jsr.cpp - src/main/cpp/napi/primjs/code_cache.cc - src/main/cpp/napi/primjs/primjs-api.cc - src/main/cpp/napi/primjs/napi_env.cc + src/main/cpp/napi/primjs/js_native_api_adapter.cc + src/main/cpp/napi/primjs/js_native_api_extensions.cc ) include_directories( src/main/cpp/napi/primjs @@ -148,6 +157,8 @@ if (PRIMJS) endif () if (HERMES) + # Hermes is the static-hermes (hermesvm) engine. Headers are extracted from + # the hermes-engine AAR into napi/hermes/include. include_directories( src/main/cpp/napi/hermes src/main/cpp/napi/hermes/include @@ -158,17 +169,6 @@ if (HERMES) ) endif () -if (SHERMES) - include_directories( - src/main/cpp/napi/hermes - src/main/cpp/napi/hermes/include_shermes - src/main/cpp/napi/common - ) - set(SOURCES ${SOURCES} - src/main/cpp/napi/hermes/jsr.cpp - ) -endif () - if (JSC) include_directories( src/main/cpp/napi/jsc @@ -289,21 +289,31 @@ MESSAGE(STATUS "# CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS}) target_link_libraries(NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/common/${ANDROID_ABI}/libzip.a) #target_link_libraries(NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/common/${ANDROID_ABI}/libclang_rt.asan-aarch64-android.so) -if (SHERMES) - target_link_libraries(NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/shermes/${ANDROID_ABI}/libhermesvm.so) - target_link_libraries(NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/shermes/${ANDROID_ABI}/libjsi.so) - add_compile_definitions(NativeScript, PRIVATE __HERMES__) - add_compile_definitions(NativeScript, PRIVATE __SHERMES__) -endif () - if (HERMES) - target_link_libraries(NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/hermes/${ANDROID_ABI}/libhermes.so) - target_link_libraries(NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/hermes/${ANDROID_ABI}/libjsi.so) + # Select debug or release Hermes .so files based on build type. + # Optimized builds use the MinSizeRel release libraries; all other builds + # (including regular debug and debugOptimized-with-inspector) use the debug + # libraries, which include HERMES_ENABLE_DEBUGGER and full debug info. + if (OPTIMIZED_BUILD OR OPTIMIZED_WITH_INSPECTOR_BUILD) + set(HERMES_LIB_VARIANT release) + else () + set(HERMES_LIB_VARIANT debug) + endif () + + set(HERMES_LIB_DIR ${PROJECT_SOURCE_DIR}/src/main/libs/hermes/${HERMES_LIB_VARIANT}/${ANDROID_ABI}) + MESSAGE(STATUS "# Hermes lib variant: ${HERMES_LIB_VARIANT} (${HERMES_LIB_DIR})") + + target_link_libraries(NativeScript ${HERMES_LIB_DIR}/libhermesvm.so) + target_link_libraries(NativeScript ${HERMES_LIB_DIR}/libjsi.so) add_compile_definitions(NativeScript, PRIVATE __HERMES__) + + # napi_create_host_object / napi_get_host_object_data / napi_is_host_object + # are compiled into libhermesvm.so (via hermesNapi) when USE_HOST_OBJECT is + # set at Hermes build time. No separate .so to link here. endif () if (JSC) - target_link_libraries(NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/jsc/${ANDROID_ABI}/libjsc.so) + target_link_libraries(NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/jsc/${ANDROID_ABI}/libJavaScriptCore.so) add_compile_definitions(NativeScript, PRIVATE __JSC__) endif () @@ -327,8 +337,12 @@ if (V8_13) endif () if (PRIMJS) - # target_link_libraries(NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/primjs/${ANDROID_ABI}/libnapi.so) + # libnapi.so provides the napi host/setup entry points (napi_new_env, + # napi_attach_quickjs, napi_setup_loader, the quickjs<->napi bridges, ...) + # and installs the value-op vtable consumed by js_native_api_adapter.cc. + # It depends on libquick.so (the quickjs engine); link both. target_link_libraries(NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/primjs/${ANDROID_ABI}/libquick.so) + target_link_libraries(NativeScript ${PROJECT_SOURCE_DIR}/src/main/libs/primjs/${ANDROID_ABI}/libnapi.so) add_compile_definitions(NativeScript, PRIVATE __PRIMJS__) endif () @@ -357,6 +371,11 @@ endif () # target_link_libraries(NativeScript ${ANDROID_NDK_ROOT}/sources/cxx-stl/llvm-libc++/libs/${ANDROID_ABI}/libandroid_support.a) # endif() + +if("${ANDROID_ABI}" MATCHES "arm64-v8a$" OR "${ANDROID_ABI}" MATCHES "x86_64$") + target_link_options(NativeScript PRIVATE "-Wl,-z,max-page-size=16384") +endif() + # Command info: https://cmake.org/cmake/help/v3.4/command/find_library.html # Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by @@ -375,7 +394,7 @@ if (QUICKJS) else () target_link_libraries(NativeScript ${system-log} ${system-z} ${system-android}) endif () -elseif (HERMES OR SHERMES) +elseif (HERMES) find_package(fbjni REQUIRED CONFIG) target_link_libraries(NativeScript ${system-log} ${system-z} fbjni::fbjni ${system-android}) elseif (JSC OR V8 OR PRIMJS) diff --git a/test-app/runtime/build.gradle b/test-app/runtime/build.gradle index 06ac738f..378f62dd 100644 --- a/test-app/runtime/build.gradle +++ b/test-app/runtime/build.gradle @@ -1,14 +1,15 @@ apply plugin: 'com.android.library' -// can be: "V8-11", "V8-10","V8-13", "JSC", "HERMES", "QUICKJS", "QUICKJS_NG", "SHERMES", "PRIMJS" +// can be: "V8-11", "V8-10","V8-13", "JSC", "HERMES", "QUICKJS", "QUICKJS_NG", "PRIMJS" + +def jsEngine = "V8-13" -def jsEngine = "QUICKJS_NG" def hasEngine = project.hasProperty("engine") if (hasEngine) { jsEngine = engine } -def hasHostObjects = project.hasProperty("useHostObjects") +def hasHostObjects = true //project.hasProperty("useHostObjects") def isNapiModule = project.hasProperty("asNapiModule"); printf("Compiling NativeScript with %s.\n", jsEngine) @@ -140,9 +141,9 @@ android { arguments.add("-DQUICKJS_NG=1") } } else if (jsEngine == "HERMES") { + // SHERMES is kept as an alias for the static-hermes (hermesvm) + // engine, which is now the canonical HERMES engine. arguments.add("-DHERMES=1") - } else if (jsEngine == "SHERMES") { - arguments.add("-DSHERMES=1") } else if (jsEngine == "PRIMJS") { arguments.add("-DPRIMJS=1") }else if (jsEngine == "JSC") { @@ -176,11 +177,24 @@ android { ndk { minSdkVersion NS_DEFAULT_MIN_SDK_VERSION as int if (onlyX86) { - abiFilters 'x86' + // The updated JSC only ships 64-bit libraries, so fall back to + // x86_64 when a single-ABI (emulator) build is requested. + abiFilters jsEngine == "JSC" ? 'x86_64' : 'x86' + } else if (jsEngine == "JSC") { + // The newer JSC engine only provides arm64-v8a and x86_64 + // prebuilts, so restrict the runtime to those two ABIs. + abiFilters 'x86_64', 'arm64-v8a' } else { abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' } } + + consumerProguardFiles 'consumer-rules.pro' + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } buildTypes { @@ -207,7 +221,7 @@ android { exclude "**/libjsi.so" exclude "**/libfbjni.so" } - } else if (jsEngine == "HERMES" || jsEngine == "SHERMES") { + } else if (jsEngine == "HERMES") { packagingOptions { exclude "**/libjsc.so" exclude '**/libfbjni.so' @@ -243,7 +257,7 @@ dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') testImplementation "junit:junit:${ns_default_junit_version}" testImplementation "org.mockito:mockito-core:${ns_default_mockito_core_version}" - if (jsEngine == "HERMES" || jsEngine == "SHERMES") { + if (jsEngine == "HERMES") { implementation 'com.facebook.fbjni:fbjni:0.7.0' } } diff --git a/test-app/runtime/consumer-rules.pro b/test-app/runtime/consumer-rules.pro new file mode 100644 index 00000000..1bea022f --- /dev/null +++ b/test-app/runtime/consumer-rules.pro @@ -0,0 +1,11 @@ +# Keep all runtime classes +-keep class com.tns.* { *; } + +# Keep SBG-generated classes +-keep class com.tns.gen.** { *; } + +# Keep internal support/runtime classes +-keep class com.tns.internal.** { *; } + +# Preserve annotation metadata so reflection sees them +-keepattributes RuntimeVisibleAnnotations diff --git a/test-app/runtime/src/main/cpp/modules/NSRuntimeModules.h b/test-app/runtime/src/main/cpp/modules/NSRuntimeModules.h index c57b5453..731908c1 100644 --- a/test-app/runtime/src/main/cpp/modules/NSRuntimeModules.h +++ b/test-app/runtime/src/main/cpp/modules/NSRuntimeModules.h @@ -8,6 +8,7 @@ #include "js_native_api.h" #include "URL.h" #include "URLSearchParams.h" +#include "URLPattern.h" namespace tns { class NSRuntimeModules { @@ -15,6 +16,7 @@ namespace tns { static void Init(napi_env env) { URL::Init(env); URLSearchParams::Init(env); + URLPattern::Init(env); } }; } diff --git a/test-app/runtime/src/main/cpp/modules/url/URL.cpp b/test-app/runtime/src/main/cpp/modules/url/URL.cpp index ed109893..7b87c5ca 100644 --- a/test-app/runtime/src/main/cpp/modules/url/URL.cpp +++ b/test-app/runtime/src/main/cpp/modules/url/URL.cpp @@ -196,7 +196,13 @@ napi_value URL::New(napi_env env, napi_callback_info info) { url_aggregator url; std::string_view url_string_view(url_buffer.data(), url_buffer.size()); - if (argc > 1) { + // Only treat the 2nd argument as a base URL when it is provided and is + // neither undefined nor null; otherwise fall through to the no-base parse. + bool hasBase = argc > 1 && + !napi_util::is_of_type(env, argv[1], napi_undefined) && + !napi_util::is_of_type(env, argv[1], napi_null); + + if (hasBase) { // Handle base URL size_t base_str_size; NAPI_GUARD(napi_get_value_string_utf8(env, argv[1], nullptr, 0, &base_str_size)) { diff --git a/test-app/runtime/src/main/cpp/modules/url/URLPattern.cpp b/test-app/runtime/src/main/cpp/modules/url/URLPattern.cpp new file mode 100644 index 00000000..75247906 --- /dev/null +++ b/test-app/runtime/src/main/cpp/modules/url/URLPattern.cpp @@ -0,0 +1,529 @@ +// +// napi port of URLPatternImpl (upstream nativescript/android-runtime #1830). +// + +#include "URLPattern.h" +#include + +using namespace std; +using namespace tns; +using namespace ada; + +thread_local napi_env URLPattern::s_current_env = nullptr; + +namespace { + napi_value js_str(napi_env env, std::string_view s) { + napi_value v; + napi_create_string_utf8(env, s.data(), s.size(), &v); + return v; + } + + std::string to_std_string(napi_env env, napi_value v) { + size_t len = 0; + napi_get_value_string_utf8(env, v, nullptr, 0, &len); + std::string s(len, '\0'); + napi_get_value_string_utf8(env, v, s.data(), len + 1, &len); + return s; + } + + std::optional get_str_prop(napi_env env, napi_value obj, const char *key) { + napi_value v; + if (napi_get_named_property(env, obj, key, &v) != napi_ok) { + return std::nullopt; + } + if (napi_util::is_of_type(env, v, napi_string)) { + return to_std_string(env, v); + } + return std::nullopt; + } + + void clear_pending(napi_env env) { + bool pending = false; + napi_is_exception_pending(env, &pending); + if (pending) { + napi_value e; + napi_get_and_clear_last_exception(env, &e); + } + } + + URLPattern *GetInstance(napi_env env, napi_callback_info info) { + size_t argc = 0; + napi_value jsThis; + void *data; + if (napi_get_cb_info(env, info, &argc, nullptr, &jsThis, &data) != napi_ok) { + return nullptr; + } + URLPattern *instance = nullptr; + if (napi_unwrap(env, jsThis, reinterpret_cast(&instance)) != napi_ok) { + return nullptr; + } + return instance; + } + + napi_value GetPatternProperty(napi_env env, napi_callback_info info, + std::string_view (url_pattern::*getter)() const) { + URLPattern *instance = GetInstance(env, info); + if (instance == nullptr) { + return js_str(env, ""); + } + auto value = (instance->GetPattern()->*getter)(); + return js_str(env, value); + } +} + +// --------------------------------------------------------------------------- +// napi RegExp provider +// --------------------------------------------------------------------------- + +std::optional +napi_regex_provider::create_instance(std::string_view pattern, bool ignore_case) { + napi_env env = URLPattern::s_current_env; + if (env == nullptr) { + return std::nullopt; + } + + napi_value global; + napi_get_global(env, &global); + + napi_value regexpCtor; + if (napi_get_named_property(env, global, "RegExp", ®expCtor) != napi_ok) { + return std::nullopt; + } + + napi_value patternStr = js_str(env, pattern); + + // v8 impl always sets the unicode flag and optionally ignore-case. + std::string flags = "u"; + if (ignore_case) { + flags += "i"; + } + napi_value flagsStr = js_str(env, flags); + + napi_value argv[2] = {patternStr, flagsStr}; + napi_value regex; + if (napi_new_instance(env, regexpCtor, 2, argv, ®ex) != napi_ok) { + clear_pending(env); + return std::nullopt; + } + + napi_ref ref = napi_util::make_ref(env, regex, 1); + return NapiRegex(env, ref); +} + +std::optional>> +napi_regex_provider::regex_search(std::string_view input, const regex_type &pattern) { + napi_env env = pattern.env; + if (env == nullptr || pattern.ref == nullptr) { + return std::nullopt; + } + + napi_value regex = napi_util::get_ref_value(env, pattern.ref); + if (regex == nullptr) { + return std::nullopt; + } + + napi_value execFn; + if (napi_get_named_property(env, regex, "exec", &execFn) != napi_ok) { + return std::nullopt; + } + + napi_value inputStr = js_str(env, input); + napi_value argv[1] = {inputStr}; + napi_value result; + if (napi_call_function(env, regex, execFn, 1, argv, &result) != napi_ok) { + clear_pending(env); + return std::nullopt; + } + + if (napi_util::is_null_or_undefined(env, result)) { + return std::nullopt; + } + + std::vector> ret; + bool isArray = false; + napi_is_array(env, result, &isArray); + if (isArray) { + uint32_t len = 0; + napi_get_array_length(env, result, &len); + ret.reserve(len); + for (uint32_t i = 0; i < len; i++) { + napi_value item; + if (napi_get_element(env, result, i, &item) != napi_ok) { + return std::nullopt; + } + if (napi_util::is_undefined(env, item)) { + ret.emplace_back(std::nullopt); + } else if (napi_util::is_of_type(env, item, napi_string)) { + ret.emplace_back(to_std_string(env, item)); + } + } + } + + return ret; +} + +bool napi_regex_provider::regex_match(std::string_view input, const regex_type &pattern) { + napi_env env = pattern.env; + if (env == nullptr || pattern.ref == nullptr) { + return false; + } + + napi_value regex = napi_util::get_ref_value(env, pattern.ref); + if (regex == nullptr) { + return false; + } + + napi_value execFn; + if (napi_get_named_property(env, regex, "exec", &execFn) != napi_ok) { + return false; + } + + napi_value inputStr = js_str(env, input); + napi_value argv[1] = {inputStr}; + napi_value result; + if (napi_call_function(env, regex, execFn, 1, argv, &result) != napi_ok) { + clear_pending(env); + return false; + } + + return !napi_util::is_null_or_undefined(env, result); +} + +// --------------------------------------------------------------------------- +// URLPattern +// --------------------------------------------------------------------------- + +URLPattern::URLPattern(url_pattern pattern) + : pattern_(std::move(pattern)) {} + +url_pattern *URLPattern::GetPattern() { + return &this->pattern_; +} + +void URLPattern::Destructor(napi_env env, void *data, void *hint) { +#ifdef __HERMES__ + URLPattern *pattern = static_cast(hint); +#else + URLPattern *pattern = static_cast(data); +#endif + delete pattern; +} + +static std::optional ParseInput(napi_env env, napi_value input) { + if (!napi_util::is_object(env, input)) { + return {}; + } + + auto init = ada::url_pattern_init{}; + if (auto v = get_str_prop(env, input, "protocol")) init.protocol = *v; + if (auto v = get_str_prop(env, input, "username")) init.username = *v; + if (auto v = get_str_prop(env, input, "password")) init.password = *v; + if (auto v = get_str_prop(env, input, "hostname")) init.hostname = *v; + if (auto v = get_str_prop(env, input, "port")) init.port = *v; + if (auto v = get_str_prop(env, input, "pathname")) init.pathname = *v; + if (auto v = get_str_prop(env, input, "search")) init.search = *v; + if (auto v = get_str_prop(env, input, "hash")) init.hash = *v; + if (auto v = get_str_prop(env, input, "baseURL")) init.base_url = *v; + return init; +} + +static void SetComponent(napi_env env, napi_value object, const char *componentKey, + const ada::url_pattern_component_result &component) { + napi_value ret; + napi_create_object(env, &ret); + napi_set_named_property(env, ret, "input", js_str(env, component.input)); + + napi_value groupValue; + napi_create_object(env, &groupValue); + for (const auto &[key, value]: component.groups) { + if (value) { + napi_set_named_property(env, groupValue, key.c_str(), js_str(env, value.value())); + } else { + napi_set_named_property(env, groupValue, key.c_str(), napi_util::undefined(env)); + } + } + napi_set_named_property(env, ret, "groups", groupValue); + + napi_set_named_property(env, object, componentKey, ret); +} + +static void BuildJS(napi_env env, napi_value object, const ada::url_pattern_result &result) { + auto len = result.inputs.size(); + napi_value inputs; + napi_create_array_with_length(env, len, &inputs); + for (uint32_t i = 0; i < len; i++) { + const auto &item = result.inputs[i]; + if (std::holds_alternative(item)) { + auto view = std::get(item); + napi_set_element(env, inputs, i, js_str(env, view)); + } + } + napi_set_named_property(env, object, "inputs", inputs); + + SetComponent(env, object, "protocol", result.protocol); + SetComponent(env, object, "hash", result.hash); + SetComponent(env, object, "hostname", result.hostname); + SetComponent(env, object, "username", result.username); + SetComponent(env, object, "password", result.password); + SetComponent(env, object, "pathname", result.pathname); + SetComponent(env, object, "port", result.port); + SetComponent(env, object, "search", result.search); +} + +napi_value URLPattern::New(napi_env env, napi_callback_info info) { + NAPI_CALLBACK_BEGIN(3) + s_current_env = env; + + // No-args: construct an empty pattern. + if (argc == 0 || napi_util::is_undefined(env, argv[0])) { + auto init = ada::url_pattern_init{}; + auto pattern = ada::parse_url_pattern(std::move(init)); + if (!pattern) { + napi_throw_type_error(env, nullptr, "Failed to construct URLPattern"); + return nullptr; + } + auto *impl = new URLPattern(std::move(*pattern)); + napi_wrap(env, jsThis, impl, URLPattern::Destructor, impl, nullptr); + return jsThis; + } + + std::optional init{}; + std::optional input{}; + std::optional base_url{}; + std::optional options{}; + + if (napi_util::is_of_type(env, argv[0], napi_string)) { + input = to_std_string(env, argv[0]); + } else if (napi_util::is_object(env, argv[0])) { + auto parsed = ParseInput(env, argv[0]); + if (parsed) { + init = std::move(*parsed); + } + } else { + napi_throw_type_error(env, nullptr, "Input must be an object or a string"); + return nullptr; + } + + // 2nd arg may be a base URL string or an options object. + napi_value baseOrOptions = argv[1]; + if (napi_util::is_of_type(env, baseOrOptions, napi_string)) { + base_url = to_std_string(env, baseOrOptions); + } else if (napi_util::is_object(env, baseOrOptions)) { + napi_value ignoreCase; + if (napi_get_named_property(env, baseOrOptions, "ignoreCase", &ignoreCase) == napi_ok && + napi_util::is_of_type(env, ignoreCase, napi_boolean)) { + options = ada::url_pattern_options{.ignore_case = napi_util::get_bool(env, ignoreCase)}; + } + } + + // 3rd arg is the options object when a base URL was given as 2nd arg. + napi_value opts = argv[2]; + if (napi_util::is_object(env, opts)) { + napi_value ignoreCase; + if (napi_get_named_property(env, opts, "ignoreCase", &ignoreCase) == napi_ok && + napi_util::is_of_type(env, ignoreCase, napi_boolean)) { + options = ada::url_pattern_options{.ignore_case = napi_util::get_bool(env, ignoreCase)}; + } + } + + std::string_view base_url_view{}; + if (base_url) { + base_url_view = {base_url->data(), base_url->size()}; + } + + ada::url_pattern_input arg0; + if (init.has_value()) { + arg0 = *init; + } else { + arg0 = std::string_view(*input); + } + + auto pattern = ada::parse_url_pattern( + std::move(arg0), + base_url.has_value() ? &base_url_view : nullptr, + options.has_value() ? &options.value() : nullptr); + + if (!pattern) { + napi_throw_type_error(env, nullptr, "Failed to construct URLPattern"); + return nullptr; + } + + auto *impl = new URLPattern(std::move(*pattern)); + napi_wrap(env, jsThis, impl, URLPattern::Destructor, impl, nullptr); + return jsThis; +} + +napi_value URLPattern::GetHash(napi_env env, napi_callback_info info) { + return GetPatternProperty(env, info, &url_pattern::get_hash); +} + +napi_value URLPattern::GetHostName(napi_env env, napi_callback_info info) { + return GetPatternProperty(env, info, &url_pattern::get_hostname); +} + +napi_value URLPattern::GetPassword(napi_env env, napi_callback_info info) { + return GetPatternProperty(env, info, &url_pattern::get_password); +} + +napi_value URLPattern::GetPathName(napi_env env, napi_callback_info info) { + return GetPatternProperty(env, info, &url_pattern::get_pathname); +} + +napi_value URLPattern::GetPort(napi_env env, napi_callback_info info) { + return GetPatternProperty(env, info, &url_pattern::get_port); +} + +napi_value URLPattern::GetProtocol(napi_env env, napi_callback_info info) { + return GetPatternProperty(env, info, &url_pattern::get_protocol); +} + +napi_value URLPattern::GetSearch(napi_env env, napi_callback_info info) { + return GetPatternProperty(env, info, &url_pattern::get_search); +} + +napi_value URLPattern::GetUserName(napi_env env, napi_callback_info info) { + return GetPatternProperty(env, info, &url_pattern::get_username); +} + +napi_value URLPattern::GetHasRegexpGroups(napi_env env, napi_callback_info info) { + URLPattern *instance = GetInstance(env, info); + napi_value result; + bool value = instance != nullptr && instance->GetPattern()->has_regexp_groups(); + napi_get_boolean(env, value, &result); + return result; +} + +napi_value URLPattern::Test(napi_env env, napi_callback_info info) { + NAPI_CALLBACK_BEGIN(2) + s_current_env = env; + + URLPattern *instance = GetInstance(env, info); + if (instance == nullptr) { + napi_value result; + napi_get_boolean(env, false, &result); + return result; + } + + ada::url_pattern_input input; + std::string input_base; + + if (argc == 0 || napi_util::is_undefined(env, argv[0])) { + input = ada::url_pattern_init{}; + } else if (napi_util::is_of_type(env, argv[0], napi_string)) { + input_base = to_std_string(env, argv[0]); + input = std::string_view(input_base); + } else if (napi_util::is_object(env, argv[0])) { + auto parsed = ParseInput(env, argv[0]); + if (parsed) { + input = std::move(*parsed); + } + } else { + napi_throw_type_error(env, nullptr, "URLPattern input needs to be a string or an object"); + return nullptr; + } + + std::optional baseURL{}; + if (argc > 1 && !napi_util::is_undefined(env, argv[1])) { + if (!napi_util::is_of_type(env, argv[1], napi_string)) { + napi_throw_type_error(env, nullptr, "baseURL must be a string"); + return nullptr; + } + baseURL = to_std_string(env, argv[1]); + } + + std::optional baseURL_opt = + baseURL ? std::optional(*baseURL) : std::nullopt; + + napi_value result; + if (auto res = instance->GetPattern()->test(input, baseURL_opt ? &*baseURL_opt : nullptr)) { + napi_get_boolean(env, res.value(), &result); + } else { + napi_get_null(env, &result); + } + return result; +} + +napi_value URLPattern::Exec(napi_env env, napi_callback_info info) { + NAPI_CALLBACK_BEGIN(2) + s_current_env = env; + + URLPattern *instance = GetInstance(env, info); + if (instance == nullptr) { + return napi_util::undefined(env); + } + + ada::url_pattern_input input; + std::string input_base; + + if (argc == 0 || napi_util::is_undefined(env, argv[0])) { + input = ada::url_pattern_init{}; + } else if (napi_util::is_of_type(env, argv[0], napi_string)) { + input_base = to_std_string(env, argv[0]); + input = std::string_view(input_base); + } else if (napi_util::is_object(env, argv[0])) { + auto parsed = ParseInput(env, argv[0]); + if (parsed) { + input = std::move(*parsed); + } + } else { + napi_throw_type_error(env, nullptr, "URLPattern input needs to be a string or an object"); + return nullptr; + } + + std::optional baseURL{}; + if (argc > 1 && !napi_util::is_undefined(env, argv[1])) { + if (!napi_util::is_of_type(env, argv[1], napi_string)) { + napi_throw_type_error(env, nullptr, "baseURL must be a string"); + return nullptr; + } + baseURL = to_std_string(env, argv[1]); + } + + std::optional baseURL_opt = + baseURL ? std::optional(*baseURL) : std::nullopt; + + napi_value result; + napi_get_null(env, &result); + + if (auto res = instance->GetPattern()->exec(input, baseURL_opt ? &*baseURL_opt : nullptr)) { + auto value = res.value(); + if (value.has_value()) { + napi_create_object(env, &result); + BuildJS(env, result, value.value()); + } + } + return result; +} + +void URLPattern::Init(napi_env env) { + NAPI_PREAMBLE + napi_value ctor; + static const int instance_prop_count = 11; + napi_property_descriptor properties[instance_prop_count] = { + {"test", nullptr, Test, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"exec", nullptr, Exec, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"hasRegExpGroups", nullptr, nullptr, GetHasRegexpGroups, nullptr, nullptr, napi_default, nullptr}, + {"hash", nullptr, nullptr, GetHash, nullptr, nullptr, napi_default, nullptr}, + {"hostname", nullptr, nullptr, GetHostName, nullptr, nullptr, napi_default, nullptr}, + {"password", nullptr, nullptr, GetPassword, nullptr, nullptr, napi_default, nullptr}, + {"pathname", nullptr, nullptr, GetPathName, nullptr, nullptr, napi_default, nullptr}, + {"port", nullptr, nullptr, GetPort, nullptr, nullptr, napi_default, nullptr}, + {"protocol", nullptr, nullptr, GetProtocol, nullptr, nullptr, napi_default, nullptr}, + {"search", nullptr, nullptr, GetSearch, nullptr, nullptr, napi_default, nullptr}, + {"username", nullptr, nullptr, GetUserName, nullptr, nullptr, napi_default, nullptr}}; + + NAPI_GUARD(napi_define_class(env, "URLPattern", NAPI_AUTO_LENGTH, New, + nullptr, instance_prop_count, + properties, &ctor)) { + return; + } + + napi_value global; + NAPI_GUARD(napi_get_global(env, &global)) { + return; + } + + NAPI_GUARD(napi_set_named_property(env, global, "URLPattern", ctor)) { + return; + } +} diff --git a/test-app/runtime/src/main/cpp/modules/url/URLPattern.h b/test-app/runtime/src/main/cpp/modules/url/URLPattern.h new file mode 100644 index 00000000..5e1ee487 --- /dev/null +++ b/test-app/runtime/src/main/cpp/modules/url/URLPattern.h @@ -0,0 +1,115 @@ +// +// napi port of URLPatternImpl (upstream nativescript/android-runtime #1830). +// Backed by ada's url_pattern with a Node-API RegExp provider so it works +// across every engine the runtime supports (V8, QuickJS, Hermes, JSC, PrimJS). +// + +#ifndef TEST_APP_URLPATTERN_H +#define TEST_APP_URLPATTERN_H + +#include "native_api_util.h" +#include "ada/ada.h" +#include +#include +#include + +using namespace ada; + +namespace tns { + + // Move-only RAII wrapper around a napi_ref to a JS RegExp. Mirrors the + // move-only semantics of v8::Global used by the original impl, + // and stores its own env so it can release the reference on destruction. + class NapiRegex { + public: + napi_env env = nullptr; + napi_ref ref = nullptr; + + NapiRegex() = default; + NapiRegex(napi_env e, napi_ref r) : env(e), ref(r) {} + + NapiRegex(const NapiRegex &) = delete; + NapiRegex &operator=(const NapiRegex &) = delete; + + NapiRegex(NapiRegex &&other) noexcept: env(other.env), ref(other.ref) { + other.ref = nullptr; + other.env = nullptr; + } + + NapiRegex &operator=(NapiRegex &&other) noexcept { + if (this != &other) { + if (ref != nullptr && env != nullptr) { + napi_delete_reference(env, ref); + } + env = other.env; + ref = other.ref; + other.ref = nullptr; + other.env = nullptr; + } + return *this; + } + + ~NapiRegex() { + if (ref != nullptr && env != nullptr) { +#ifdef __V8__ + node_api_post_finalizer(env, [](napi_env env, void *d, void*) { + napi_delete_reference(env, (napi_ref) d); + }, ref, nullptr); +#else + napi_delete_reference(env, ref); +#endif + + + + } + } + }; + + class napi_regex_provider { + public: + napi_regex_provider() = default; + + using regex_type = NapiRegex; + + static std::optional create_instance(std::string_view pattern, + bool ignore_case); + + static std::optional>> regex_search( + std::string_view input, const regex_type &pattern); + + static bool regex_match(std::string_view input, const regex_type &pattern); + }; + + class URLPattern { + public: + static void Init(napi_env env); + static void Destructor(napi_env env, void *nativeObject, void *finalize_hint); + + explicit URLPattern(url_pattern pattern); + url_pattern *GetPattern(); + + // Set at the entry of every callback that drives ada's regex provider + // (New/Test/Exec), so create_instance can reach the current env. + static thread_local napi_env s_current_env; + + private: + static napi_value New(napi_env env, napi_callback_info info); + + static napi_value GetHash(napi_env env, napi_callback_info info); + static napi_value GetHostName(napi_env env, napi_callback_info info); + static napi_value GetPassword(napi_env env, napi_callback_info info); + static napi_value GetPathName(napi_env env, napi_callback_info info); + static napi_value GetPort(napi_env env, napi_callback_info info); + static napi_value GetProtocol(napi_env env, napi_callback_info info); + static napi_value GetSearch(napi_env env, napi_callback_info info); + static napi_value GetUserName(napi_env env, napi_callback_info info); + static napi_value GetHasRegexpGroups(napi_env env, napi_callback_info info); + + static napi_value Test(napi_env env, napi_callback_info info); + static napi_value Exec(napi_env env, napi_callback_info info); + + url_pattern pattern_; + }; +} + +#endif //TEST_APP_URLPATTERN_H diff --git a/test-app/runtime/src/main/cpp/modules/url/URLSearchParams.cpp b/test-app/runtime/src/main/cpp/modules/url/URLSearchParams.cpp index 8cf11da4..eb5ba1b5 100644 --- a/test-app/runtime/src/main/cpp/modules/url/URLSearchParams.cpp +++ b/test-app/runtime/src/main/cpp/modules/url/URLSearchParams.cpp @@ -1,24 +1,322 @@ #include "URLSearchParams.h" #include +#include using namespace ada; using namespace tns; namespace { + enum IterKind { ITER_KEYS = 0, ITER_VALUES = 1, ITER_ENTRIES = 2 }; + + // Per-iterator state: keeps the source URLSearchParams alive via a strong + // ref, holds a weak self-ref to the iterator object for the `next` receiver + // brand check, and tracks the current index. Freed by the iterator's finalizer. + struct IterState { + napi_ref src; + napi_ref iterSelf; // weak ref to the iterator object (brand identity) + uint32_t idx; + int kind; + }; + + napi_value js_str(napi_env env, std::string_view s) { + napi_value v; + napi_create_string_utf8(env, s.data(), s.length(), &v); + return v; + } + + void ThrowTypeError(napi_env env, const char *msg) { + napi_throw_type_error(env, nullptr, msg); + } + + // WebIDL USVString coercion: ToString (invokes user toString, throws for Symbol). + // Returns false leaving a pending exception on failure. + bool ValueToString(napi_env env, napi_value v, std::string &out) { + napi_value str; + if (napi_coerce_to_string(env, v, &str) != napi_ok) { + return false; + } + size_t len = 0; + if (napi_get_value_string_utf8(env, str, nullptr, 0, &len) != napi_ok) { + return false; + } + std::vector buf(len + 1); + napi_get_value_string_utf8(env, str, buf.data(), len + 1, nullptr); + out.assign(buf.data(), len); + return true; + } + + // Brand-checked instance retrieval: throws "Illegal invocation" (TypeError) when + // the receiver is not a wrapped URLSearchParams, matching the spec. URLSearchParams *GetInstance(napi_env env, napi_callback_info info) { - NAPI_PREAMBLE napi_value jsThis; - void *data; - NAPI_GUARD(napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, &data)) { + if (napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr) != napi_ok) { + return nullptr; + } + URLSearchParams *instance = nullptr; + if (napi_unwrap(env, jsThis, reinterpret_cast(&instance)) != napi_ok || + instance == nullptr) { + ThrowTypeError(env, "Illegal invocation"); return nullptr; } + return instance; + } + + napi_value WellKnownSymbol(napi_env env, const char *name) { + napi_value global, symbolCtor, sym; + napi_get_global(env, &global); + napi_get_named_property(env, global, "Symbol", &symbolCtor); + napi_get_named_property(env, symbolCtor, name, &sym); + return sym; + } + + napi_value SymbolIterator(napi_env env) { + return WellKnownSymbol(env, "iterator"); + } + + // ES IteratorClose: best-effort call to the iterator's return() on abrupt + // completion (so a generator's `finally` runs), preserving any pending exception. + void IteratorClose(napi_env env, napi_value iterObj) { + napi_value savedEx = nullptr; + bool pending = false; + napi_is_exception_pending(env, &pending); + if (pending) { + napi_get_and_clear_last_exception(env, &savedEx); + } + napi_value returnFn; + if (napi_get_named_property(env, iterObj, "return", &returnFn) == napi_ok && + napi_util::is_of_type(env, returnFn, napi_function)) { + napi_value res; + napi_call_function(env, iterObj, returnFn, 0, nullptr, &res); + bool p2 = false; + napi_is_exception_pending(env, &p2); + if (p2) { + napi_value e; + napi_get_and_clear_last_exception(env, &e); + } + } + if (savedEx != nullptr) { + napi_throw(env, savedEx); + } + } - URLSearchParams *instance; - NAPI_GUARD(napi_unwrap(env, jsThis, reinterpret_cast(&instance))) { + // The `next` function of a live URLSearchParams iterator. + napi_value IteratorNext(napi_env env, napi_callback_info info) { + void *data = nullptr; + napi_value jsThis; + napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, &data); + auto *st = static_cast(data); + + // Brand check: `next` must be invoked on the very iterator it belongs to. + // Compare the receiver against the iterator identity; a foreign receiver + // (e.g. next.call({})) throws, per spec. + if (st == nullptr) { + ThrowTypeError(env, "Illegal invocation"); + return nullptr; + } + napi_value iterObj; + bool sameReceiver = false; + if (napi_get_reference_value(env, st->iterSelf, &iterObj) == napi_ok && iterObj != nullptr) { + napi_strict_equals(env, jsThis, iterObj, &sameReceiver); + } + if (!sameReceiver) { + ThrowTypeError(env, "Illegal invocation"); return nullptr; } - return instance; + napi_value result; + napi_create_object(env, &result); + + napi_value srcObj; + URLSearchParams *self = nullptr; + if (napi_get_reference_value(env, st->src, &srcObj) != napi_ok || + napi_unwrap(env, srcObj, reinterpret_cast(&self)) != napi_ok || + self == nullptr) { + napi_set_named_property(env, result, "value", napi_util::undefined(env)); + napi_set_named_property(env, result, "done", napi_util::get_true(env)); + return result; + } + + auto *p = self->GetURLSearchParams(); + if (st->idx >= p->size()) { + napi_set_named_property(env, result, "value", napi_util::undefined(env)); + napi_set_named_property(env, result, "done", napi_util::get_true(env)); + return result; + } + + auto pair = (*p)[st->idx++]; // live, duplicate-key correct + napi_value value; + if (st->kind == ITER_KEYS) { + value = js_str(env, pair.first); + } else if (st->kind == ITER_VALUES) { + value = js_str(env, pair.second); + } else { + napi_create_array_with_length(env, 2, &value); + napi_set_element(env, value, 0, js_str(env, pair.first)); + napi_set_element(env, value, 1, js_str(env, pair.second)); + } + napi_set_named_property(env, result, "value", value); + napi_set_named_property(env, result, "done", napi_util::get_false(env)); + return result; + } + + // iterator[Symbol.iterator]() -> this (iterators are iterable). + napi_value IteratorSelf(napi_env env, napi_callback_info info) { + napi_value jsThis; + napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr); + return jsThis; + } + + napi_value MakeIterator(napi_env env, napi_value jsThis, int kind) { + // src: strong ref to the source URLSearchParams (kept alive for `next`). + auto *st = new IterState{napi_util::make_ref(env, jsThis, 1), nullptr, 0, kind}; + + napi_value iterator; + napi_create_object(env, &iterator); + + // Weak self-ref for the `next` receiver brand check (see IteratorNext). + // Weak (refcount 0) so it does not keep the iterator alive / create a cycle. + st->iterSelf = napi_util::make_ref(env, iterator, 0); + + napi_value nextFn; + napi_create_function(env, "next", NAPI_AUTO_LENGTH, IteratorNext, st, &nextFn); + napi_set_named_property(env, iterator, "next", nextFn); + + napi_value selfFn; + napi_create_function(env, "[Symbol.iterator]", NAPI_AUTO_LENGTH, IteratorSelf, nullptr, + &selfFn); + napi_set_property(env, iterator, SymbolIterator(env), selfFn); + + // Symbol.toStringTag = "URLSearchParams Iterator" for spec-correct + // Object.prototype.toString output. + napi_set_property(env, iterator, WellKnownSymbol(env, "toStringTag"), + js_str(env, "URLSearchParams Iterator")); + + // Release the state when the iterator is collected. Ref deletion is + // deferred on V8 (deleting a reference synchronously inside a finalizer + // is illegal there). + napi_add_finalizer(env, iterator, st, [](napi_env env, void *d, void *) { +#ifdef __V8__ + node_api_post_finalizer(env, [](napi_env env, void *d, void *) { +#endif + auto *s = static_cast(d); + napi_delete_reference(env, s->src); + napi_delete_reference(env, s->iterSelf); + delete s; +#ifdef __V8__ + }, d, nullptr); +#endif + }, st, nullptr); + + return iterator; + } + + // Drives the ES iterator protocol on `iterable`, invoking fn(itemValue) for each + // yielded value. Returns false (with a pending exception) on protocol error or if + // fn returns false. + template + bool ForEachOfIterable(napi_env env, napi_value iterable, F &&fn) { + napi_value iterMethod; + if (napi_get_property(env, iterable, SymbolIterator(env), &iterMethod) != napi_ok) { + return false; + } + if (!napi_util::is_of_type(env, iterMethod, napi_function)) { + ThrowTypeError(env, "value is not iterable"); + return false; + } + napi_value iterObj; + if (napi_call_function(env, iterable, iterMethod, 0, nullptr, &iterObj) != napi_ok) { + return false; + } + if (!napi_util::is_object(env, iterObj)) { + ThrowTypeError(env, "iterator result is not an object"); + return false; + } + napi_value nextFn; + napi_get_named_property(env, iterObj, "next", &nextFn); + if (!napi_util::is_of_type(env, nextFn, napi_function)) { + ThrowTypeError(env, "iterator.next is not a function"); + return false; + } + + while (true) { + napi_value res; + if (napi_call_function(env, iterObj, nextFn, 0, nullptr, &res) != napi_ok) { + return false; + } + if (!napi_util::is_object(env, res)) { + ThrowTypeError(env, "iterator result is not an object"); + return false; + } + napi_value doneVal; + napi_get_named_property(env, res, "done", &doneVal); + bool done = false; + napi_value doneCoerced; + if (napi_coerce_to_bool(env, doneVal, &doneCoerced) == napi_ok) { + napi_get_value_bool(env, doneCoerced, &done); + } + if (done) { + break; + } + napi_value value; + napi_get_named_property(env, res, "value", &value); + if (!fn(value)) { + // abrupt completion → close the source iterator (runs finally blocks) + IteratorClose(env, iterObj); + return false; + } + } + return true; + } + + // sequence> form. + bool BuildFromSequence(napi_env env, napi_value iterable, url_search_params ¶ms) { + return ForEachOfIterable(env, iterable, [&](napi_value entry) -> bool { + if (!napi_util::is_object(env, entry)) { + ThrowTypeError(env, "URLSearchParams init sequence entry is not iterable"); + return false; + } + std::vector pair; + bool ok = ForEachOfIterable(env, entry, [&](napi_value item) -> bool { + std::string s; + if (!ValueToString(env, item, s)) { + return false; + } + pair.push_back(std::move(s)); + return true; + }); + if (!ok) { + return false; + } + if (pair.size() != 2) { + ThrowTypeError(env, + "URLSearchParams init sequence entry does not contain exactly two elements"); + return false; + } + params.append(pair[0], pair[1]); + return true; + }); + } + + // record form. + bool BuildFromRecord(napi_env env, napi_value object, url_search_params ¶ms) { + napi_value keys; + if (napi_get_all_property_names(env, object, napi_key_own_only, napi_key_enumerable, + napi_key_numbers_to_strings, &keys) != napi_ok) { + return false; + } + uint32_t len = 0; + napi_get_array_length(env, keys, &len); + for (uint32_t i = 0; i < len; i++) { + napi_value key, value; + napi_get_element(env, keys, i, &key); + napi_get_property(env, object, key, &value); + std::string k, v; + if (!ValueToString(env, key, k) || !ValueToString(env, value, v)) { + return false; // e.g. Symbol key + } + params.append(k, v); + } + return true; } } @@ -34,21 +332,40 @@ napi_value URLSearchParams::New(napi_env env, napi_callback_info info) { url_search_params params; - if (argc > 0) { - size_t str_size; - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], nullptr, 0, &str_size)) { - return nullptr; - } - - std::vector buffer(str_size + 1); - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], buffer.data(), str_size + 1, nullptr)) { - return nullptr; + if (argc > 0 && !napi_util::is_undefined(env, argv[0])) { + if (napi_util::is_of_type(env, argv[0], napi_string)) { + std::string init; + if (!ValueToString(env, argv[0], init)) { + return nullptr; + } + params = url_search_params(init); + } else if (napi_util::is_object(env, argv[0])) { + napi_value iterMethod; + if (napi_get_property(env, argv[0], SymbolIterator(env), &iterMethod) != napi_ok) { + return nullptr; + } + if (napi_util::is_null_or_undefined(env, iterMethod)) { + if (!BuildFromRecord(env, argv[0], params)) { + return nullptr; + } + } else if (napi_util::is_of_type(env, iterMethod, napi_function)) { + if (!BuildFromSequence(env, argv[0], params)) { + return nullptr; + } + } else { + ThrowTypeError(env, "URLSearchParams init Symbol.iterator is not a function"); + return nullptr; + } + } else { + // number / boolean / bigint / null / symbol -> USVString + std::string init; + if (!ValueToString(env, argv[0], init)) { + return nullptr; + } + params = url_search_params(init); } - - params = url_search_params(std::string_view(buffer.data(), str_size)); } - URLSearchParams *searchParams = new URLSearchParams(params); napi_wrap(env, jsThis, searchParams, URLSearchParams::Destructor, searchParams, nullptr); @@ -71,56 +388,46 @@ napi_value URLSearchParams::Append(napi_env env, napi_callback_info info) { URLSearchParams *instance = GetInstance(env, info); if (!instance) return nullptr; - if (argc < 2) return nullptr; - - size_t key_size, value_size; - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], nullptr, 0, &key_size)) { - return nullptr; - } - NAPI_GUARD(napi_get_value_string_utf8(env, argv[1], nullptr, 0, &value_size)) { + if (argc < 2) { + ThrowTypeError(env, "URLSearchParams.append requires 2 arguments"); return nullptr; } - std::vector key_buffer(key_size + 1); - std::vector value_buffer(value_size + 1); - - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], key_buffer.data(), key_size + 1, nullptr)) { - return nullptr; - } - NAPI_GUARD(napi_get_value_string_utf8(env, argv[1], value_buffer.data(), value_size + 1, - nullptr)) { + std::string key, value; + if (!ValueToString(env, argv[0], key) || !ValueToString(env, argv[1], value)) { return nullptr; } - instance->GetURLSearchParams()->append(key_buffer.data(), value_buffer.data()); + instance->GetURLSearchParams()->append(key, value); return nullptr; } napi_value URLSearchParams::Has(napi_env env, napi_callback_info info) { - NAPI_CALLBACK_BEGIN(1) + NAPI_CALLBACK_BEGIN(2) URLSearchParams *instance = GetInstance(env, info); if (!instance) return nullptr; - if (argc < 1) return nullptr; + if (argc < 1) return napi_util::get_false(env); - size_t str_size; - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], nullptr, 0, &str_size)) { + std::string key; + if (!ValueToString(env, argv[0], key)) { return nullptr; } - std::vector buffer(str_size + 1); - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], buffer.data(), str_size + 1, nullptr)) { - return nullptr; + bool has; + if (argc > 1 && !napi_util::is_undefined(env, argv[1])) { + std::string value; + if (!ValueToString(env, argv[1], value)) { + return nullptr; + } + has = instance->GetURLSearchParams()->has(key, value); + } else { + has = instance->GetURLSearchParams()->has(key); } - bool has = instance->GetURLSearchParams()->has(buffer.data()); - napi_value result; - NAPI_GUARD(napi_get_boolean(env, has, &result)) { - return nullptr; - } - + napi_get_boolean(env, has, &result); return result; } @@ -130,55 +437,47 @@ napi_value URLSearchParams::Get(napi_env env, napi_callback_info info) { URLSearchParams *instance = GetInstance(env, info); if (!instance) return nullptr; - if (argc < 1) return nullptr; + if (argc < 1) return napi_util::null(env); - size_t str_size; - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], nullptr, 0, &str_size)) { + std::string key; + if (!ValueToString(env, argv[0], key)) { return nullptr; } - std::vector buffer(str_size + 1); - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], buffer.data(), str_size + 1, nullptr)) { - return nullptr; - } - - auto value = instance->GetURLSearchParams()->get(buffer.data()); + auto value = instance->GetURLSearchParams()->get(key); if (!value.has_value()) { - napi_value undefined; - NAPI_GUARD(napi_get_undefined(env, &undefined)) { - return nullptr; - } - return undefined; - } - - napi_value result; - NAPI_GUARD( - napi_create_string_utf8(env, value.value().data(), value.value().length(), &result)) { - return nullptr; + // Per spec, a missing name returns null. + return napi_util::null(env); } - return result; + return js_str(env, value.value()); } napi_value URLSearchParams::Delete(napi_env env, napi_callback_info info) { - NAPI_CALLBACK_BEGIN(1) + NAPI_CALLBACK_BEGIN(2) URLSearchParams *instance = GetInstance(env, info); if (!instance) return nullptr; - if (argc < 1) return nullptr; - - size_t str_size; - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], nullptr, 0, &str_size)) { + if (argc < 1) { + ThrowTypeError(env, "URLSearchParams.delete requires 1 argument"); return nullptr; } - std::vector buffer(str_size + 1); - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], buffer.data(), str_size + 1, nullptr)) { + std::string key; + if (!ValueToString(env, argv[0], key)) { return nullptr; } - instance->GetURLSearchParams()->remove(buffer.data()); + if (argc > 1 && !napi_util::is_undefined(env, argv[1])) { + std::string value; + if (!ValueToString(env, argv[1], value)) { + return nullptr; + } + instance->GetURLSearchParams()->remove(key, value); + } else { + instance->GetURLSearchParams()->remove(key); + } return nullptr; } @@ -188,35 +487,23 @@ napi_value URLSearchParams::GetAll(napi_env env, napi_callback_info info) { URLSearchParams *instance = GetInstance(env, info); if (!instance) return nullptr; - if (argc < 1) return nullptr; - - size_t str_size; - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], nullptr, 0, &str_size)) { + if (argc < 1) { + ThrowTypeError(env, "URLSearchParams.getAll requires 1 argument"); return nullptr; } - std::vector buffer(str_size + 1); - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], buffer.data(), str_size + 1, nullptr)) { + std::string key; + if (!ValueToString(env, argv[0], key)) { return nullptr; } - auto values = instance->GetURLSearchParams()->get_all(buffer.data()); + auto values = instance->GetURLSearchParams()->get_all(key); napi_value result; - NAPI_GUARD(napi_create_array_with_length(env, values.size(), &result)) { - return nullptr; - } - + napi_create_array_with_length(env, values.size(), &result); for (size_t i = 0; i < values.size(); i++) { - napi_value item; - NAPI_GUARD(napi_create_string_utf8(env, values[i].data(), values[i].length(), &item)) { - return nullptr; - } - NAPI_GUARD(napi_set_element(env, result, i, item)) { - return nullptr; - } + napi_set_element(env, result, i, js_str(env, values[i])); } - return result; } @@ -226,48 +513,31 @@ napi_value URLSearchParams::Set(napi_env env, napi_callback_info info) { URLSearchParams *instance = GetInstance(env, info); if (!instance) return nullptr; - if (argc < 2) return nullptr; - - size_t key_size, value_size; - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], nullptr, 0, &key_size)) { + if (argc < 2) { + ThrowTypeError(env, "URLSearchParams.set requires 2 arguments"); return nullptr; } - NAPI_GUARD(napi_get_value_string_utf8(env, argv[1], nullptr, 0, &value_size)) { - return nullptr; - } - - std::vector key_buffer(key_size + 1); - std::vector value_buffer(value_size + 1); - NAPI_GUARD(napi_get_value_string_utf8(env, argv[0], key_buffer.data(), key_size + 1, nullptr)) { - return nullptr; - } - NAPI_GUARD(napi_get_value_string_utf8(env, argv[1], value_buffer.data(), value_size + 1, - nullptr)) { + std::string key, value; + if (!ValueToString(env, argv[0], key) || !ValueToString(env, argv[1], value)) { return nullptr; } - instance->GetURLSearchParams()->set(key_buffer.data(), value_buffer.data()); + instance->GetURLSearchParams()->set(key, value); return nullptr; } napi_value URLSearchParams::GetSize(napi_env env, napi_callback_info info) { - NAPI_PREAMBLE URLSearchParams *instance = GetInstance(env, info); if (!instance) return nullptr; auto size = instance->GetURLSearchParams()->size(); - napi_value result; - NAPI_GUARD(napi_create_int32(env, static_cast(size), &result)) { - return nullptr; - } - + napi_create_int32(env, static_cast(size), &result); return result; } napi_value URLSearchParams::Sort(napi_env env, napi_callback_info info) { - NAPI_PREAMBLE URLSearchParams *instance = GetInstance(env, info); if (!instance) return nullptr; @@ -276,176 +546,63 @@ napi_value URLSearchParams::Sort(napi_env env, napi_callback_info info) { } napi_value URLSearchParams::ToString(napi_env env, napi_callback_info info) { - NAPI_PREAMBLE URLSearchParams *instance = GetInstance(env, info); if (!instance) return nullptr; auto value = instance->GetURLSearchParams()->to_string(); - - napi_value result; - NAPI_GUARD(napi_create_string_utf8(env, value.data(), value.length(), &result)) { - return nullptr; - } - - return result; + return js_str(env, value); } napi_value URLSearchParams::Keys(napi_env env, napi_callback_info info) { - NAPI_PREAMBLE - URLSearchParams *instance = GetInstance(env, info); - if (!instance) return nullptr; - - auto keys = instance->GetURLSearchParams()->get_keys(); - std::vector key_list; - - while (keys.has_next()) { - if (auto key = keys.next()) { - key_list.push_back(key.value()); - } - } - - napi_value result; - NAPI_GUARD(napi_create_array_with_length(env, key_list.size(), &result)) { - return nullptr; - } - - for (size_t i = 0; i < key_list.size(); i++) { - napi_value item; - NAPI_GUARD(napi_create_string_utf8(env, key_list[i].data(), key_list[i].length(), &item)) { - return nullptr; - } - NAPI_GUARD(napi_set_element(env, result, i, item)) { - return nullptr; - } - } - - return result; + napi_value jsThis; + napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr); + if (!GetInstance(env, info)) return nullptr; + return MakeIterator(env, jsThis, ITER_KEYS); } napi_value URLSearchParams::Values(napi_env env, napi_callback_info info) { - NAPI_PREAMBLE - URLSearchParams *instance = GetInstance(env, info); - if (!instance) return nullptr; - - auto keys = instance->GetURLSearchParams()->get_keys(); - std::vector value_list; - - while (keys.has_next()) { - if (auto key = keys.next()) { - if (auto value = instance->GetURLSearchParams()->get(key.value())) { - value_list.push_back(value.value()); - } - } - } - - napi_value result; - NAPI_GUARD(napi_create_array_with_length(env, value_list.size(), &result)) { - return nullptr; - } - - for (size_t i = 0; i < value_list.size(); i++) { - napi_value item; - NAPI_GUARD( - napi_create_string_utf8(env, value_list[i].data(), value_list[i].length(), &item)) { - return nullptr; - } - NAPI_GUARD(napi_set_element(env, result, i, item)) { - return nullptr; - } - } - - return result; + napi_value jsThis; + napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr); + if (!GetInstance(env, info)) return nullptr; + return MakeIterator(env, jsThis, ITER_VALUES); } napi_value URLSearchParams::Entries(napi_env env, napi_callback_info info) { - NAPI_PREAMBLE - URLSearchParams *instance = GetInstance(env, info); - if (!instance) return nullptr; - - auto keys = instance->GetURLSearchParams()->get_keys(); - std::vector> entries; - - while (keys.has_next()) { - if (auto key = keys.next()) { - if (auto value = instance->GetURLSearchParams()->get(key.value())) { - entries.emplace_back(key.value(), value.value()); - } - } - } - - napi_value result; - NAPI_GUARD(napi_create_array_with_length(env, entries.size(), &result)) { - return nullptr; - } - - for (size_t i = 0; i < entries.size(); i++) { - napi_value entry; - NAPI_GUARD(napi_create_array_with_length(env, 2, &entry)) { - return nullptr; - } - - napi_value key, value; - NAPI_GUARD(napi_create_string_utf8(env, entries[i].first.data(), entries[i].first.length(), - &key)) { - return nullptr; - } - NAPI_GUARD( - napi_create_string_utf8(env, entries[i].second.data(), entries[i].second.length(), - &value)) { - return nullptr; - } - - NAPI_GUARD(napi_set_element(env, entry, 0, key)) { - return nullptr; - } - NAPI_GUARD(napi_set_element(env, entry, 1, value)) { - return nullptr; - } - NAPI_GUARD(napi_set_element(env, result, i, entry)) { - return nullptr; - } - } - - return result; + napi_value jsThis; + napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr); + if (!GetInstance(env, info)) return nullptr; + return MakeIterator(env, jsThis, ITER_ENTRIES); } napi_value URLSearchParams::ForEach(napi_env env, napi_callback_info info) { - NAPI_CALLBACK_BEGIN(1) + NAPI_CALLBACK_BEGIN(2) URLSearchParams *instance = GetInstance(env, info); if (!instance) return nullptr; - if (argc < 1) return nullptr; + if (argc < 1 || !napi_util::is_of_type(env, argv[0], napi_function)) { + ThrowTypeError(env, "URLSearchParams.forEach requires a callback function"); + return nullptr; + } napi_value callback = argv[0]; napi_value thisArg = argc >= 2 ? argv[1] : nullptr; - auto keys = instance->GetURLSearchParams()->get_keys(); - while (keys.has_next()) { - if (auto key = keys.next()) { - if (auto value = instance->GetURLSearchParams()->get(key.value())) { - napi_value args[3]; - NAPI_GUARD( - napi_create_string_utf8(env, value.value().data(), value.value().length(), - &args[0])) { - return nullptr; - } - NAPI_GUARD(napi_create_string_utf8(env, key.value().data(), key.value().length(), - &args[1])) { - return nullptr; - } - args[2] = jsThis; - - napi_value global; - NAPI_GUARD(napi_get_global(env, &global)) { - return nullptr; - } - - napi_value result; - NAPI_GUARD(napi_call_function(env, thisArg ? thisArg : global, callback, 3, args, - &result)) { - return nullptr; - } + napi_value global; + napi_get_global(env, &global); + + // Use get_entries() so duplicate keys (e.g. ?a=1&a=2) each yield their own value. + auto entries = instance->GetURLSearchParams()->get_entries(); + while (entries.has_next()) { + if (auto entry = entries.next()) { + auto &[key, value] = entry.value(); + // Per spec, forEach callback receives (value, key, searchParams). + napi_value args[3] = {js_str(env, value), js_str(env, key), jsThis}; + napi_value result; + if (napi_call_function(env, thisArg ? thisArg : global, callback, 3, args, &result) != + napi_ok) { + // If the callback throws, stop iteration. + return nullptr; } } } @@ -480,6 +637,13 @@ void URLSearchParams::Init(napi_env env) { return; } + // Make prototype[Symbol.iterator] === entries (spec: default iterator is entries()). + napi_value proto, entriesFn; + if (napi_get_named_property(env, ctor, "prototype", &proto) == napi_ok && + napi_get_named_property(env, proto, "entries", &entriesFn) == napi_ok) { + napi_set_property(env, proto, SymbolIterator(env), entriesFn); + } + napi_value global; NAPI_GUARD(napi_get_global(env, &global)) { return; @@ -488,4 +652,4 @@ void URLSearchParams::Init(napi_env env) { NAPI_GUARD(napi_set_named_property(env, global, "URLSearchParams", ctor)) { return; } -} \ No newline at end of file +} diff --git a/test-app/runtime/src/main/cpp/modules/url/ada/ada.cpp b/test-app/runtime/src/main/cpp/modules/url/ada/ada.cpp index 8237277f..72f0e316 100644 --- a/test-app/runtime/src/main/cpp/modules/url/ada/ada.cpp +++ b/test-app/runtime/src/main/cpp/modules/url/ada/ada.cpp @@ -1,28 +1,29 @@ -/* auto-generated on 2024-07-06 17:38:56 -0400. Do not edit! */ +/* auto-generated on 2025-09-23 12:57:35 -0400. Do not edit! */ /* begin file src/ada.cpp */ #include "ada.h" /* begin file src/checkers.cpp */ #include +#include +#include namespace ada::checkers { -ada_really_inline ada_constexpr bool is_ipv4(std::string_view view) noexcept { +ada_really_inline constexpr bool is_ipv4(std::string_view view) noexcept { // The string is not empty and does not contain upper case ASCII characters. // // Optimization. To be considered as a possible ipv4, the string must end // with 'x' or a lowercase hex character. // Most of the time, this will be false so this simple check will save a lot // of effort. - char last_char = view.back(); // If the address ends with a dot, we need to prune it (special case). - if (last_char == '.') { + if (view.ends_with('.')) { view.remove_suffix(1); if (view.empty()) { return false; } - last_char = view.back(); } + char last_char = view.back(); bool possible_ipv4 = (last_char >= '0' && last_char <= '9') || (last_char >= 'a' && last_char <= 'f') || last_char == 'x'; @@ -38,7 +39,7 @@ ada_really_inline ada_constexpr bool is_ipv4(std::string_view view) noexcept { /** Optimization opportunity: we have basically identified the last number of the ipv4 if we return true here. We might as well parse it and have at least one number parsed when we get to parse_ipv4. */ - if (std::all_of(view.begin(), view.end(), ada::checkers::is_digit)) { + if (std::ranges::all_of(view, ada::checkers::is_digit)) { return true; } // It could be hex (0x), but not if there is a single character. @@ -46,7 +47,7 @@ ada_really_inline ada_constexpr bool is_ipv4(std::string_view view) noexcept { return false; } // It must start with 0x. - if (!std::equal(view.begin(), view.begin() + 2, "0x")) { + if (!view.starts_with("0x")) { return false; } // We must allow "0x". @@ -55,32 +56,32 @@ ada_really_inline ada_constexpr bool is_ipv4(std::string_view view) noexcept { } // We have 0x followed by some characters, we need to check that they are // hexadecimals. - return std::all_of(view.begin() + 2, view.end(), - ada::unicode::is_lowercase_hex); + view.remove_prefix(2); + return std::ranges::all_of(view, ada::unicode::is_lowercase_hex); } // for use with path_signature, we include all characters that need percent // encoding. static constexpr std::array path_signature_table = - []() constexpr { - std::array result{}; - for (size_t i = 0; i < 256; i++) { - if (i <= 0x20 || i == 0x22 || i == 0x23 || i == 0x3c || i == 0x3e || - i == 0x3f || i == 0x60 || i == 0x7b || i == 0x7d || i > 0x7e) { - result[i] = 1; - } else if (i == 0x25) { - result[i] = 8; - } else if (i == 0x2e) { - result[i] = 4; - } else if (i == 0x5c) { - result[i] = 2; - } else { - result[i] = 0; - } - } - return result; -} -(); + []() consteval { + std::array result{}; + for (size_t i = 0; i < 256; i++) { + if (i <= 0x20 || i == 0x22 || i == 0x23 || i == 0x3c || i == 0x3e || + i == 0x3f || i == 0x5e || i == 0x60 || i == 0x7b || i == 0x7d || + i > 0x7e) { + result[i] = 1; + } else if (i == 0x25) { + result[i] = 8; + } else if (i == 0x2e) { + result[i] = 4; + } else if (i == 0x5c) { + result[i] = 2; + } else { + result[i] = 0; + } + } + return result; + }(); ada_really_inline constexpr uint8_t path_signature( std::string_view input) noexcept { @@ -134,7 +135,7 @@ ada_really_inline constexpr bool verify_dns_length( ADA_PUSH_DISABLE_ALL_WARNINGS /* begin file src/ada_idna.cpp */ -/* auto-generated on 2023-09-19 15:58:51 -0400. Do not edit! */ +/* auto-generated on 2025-06-26 23:04:30 -0300. Do not edit! */ /* begin file src/idna.cpp */ /* begin file src/unicode_transcoding.cpp */ @@ -147,7 +148,7 @@ namespace ada::idna { size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) { const uint8_t* data = reinterpret_cast(buf); size_t pos = 0; - char32_t* start{utf32_output}; + const char32_t* start{utf32_output}; while (pos < len) { // try to convert the next block of 16 ASCII bytes if (pos + 16 <= len) { // if it is safe to read 16 more @@ -266,7 +267,7 @@ size_t utf32_length_from_utf8(const char* buf, size_t len) { size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) { const uint32_t* data = reinterpret_cast(buf); size_t pos = 0; - char* start{utf8_output}; + const char* start{utf8_output}; while (pos < len) { // try to convert the next block of 2 ASCII characters if (pos + 2 <= len) { // if it is safe to read 8 more @@ -326,7 +327,7 @@ size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) { #include /* begin file src/mapping_tables.cpp */ -// IDNA 15.0.0 +// IDNA 16.0.0 // clang-format off #ifndef ADA_IDNA_TABLES_H @@ -335,7 +336,7 @@ size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) { namespace ada::idna { -const uint32_t mappings[5164] = +const uint32_t mappings[5236] = { 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 32, 32, 776, 32, 772, 50, 51, 32, 769, @@ -364,360 +365,366 @@ const uint32_t mappings[5164] = 1125, 1127, 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151, 1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187, 1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, 1209, 1211, 1213, 1215, - 1218, 1220, 1222, 1224, 1226, 1228, 1230, 1233, 1235, 1237, 1239, 1241, 1243, 1245, - 1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1271, 1273, - 1275, 1277, 1279, 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299, 1301, - 1303, 1305, 1307, 1309, 1311, 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327, 1377, - 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, - 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, - 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, 1575, 1652, 1608, - 1652, 1735, 1652, 1610, 1652, 2325, 2364, 2326, 2364, 2327, 2364, 2332, 2364, 2337, - 2364, 2338, 2364, 2347, 2364, 2351, 2364, 2465, 2492, 2466, 2492, 2479, 2492, 2610, - 2620, 2616, 2620, 2582, 2620, 2583, 2620, 2588, 2620, 2603, 2620, 2849, 2876, 2850, - 2876, 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, 3851, 3906, 4023, 3916, 4023, - 3921, 4023, 3926, 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, 3956, 4018, 3968, - 4018, 3953, 3968, 4019, 3968, 4019, 3953, 3968, 3986, 4023, 3996, 4023, 4001, 4023, - 4006, 4023, 4011, 4023, 3984, 4021, 11559, 11565, 4316, 5104, 5105, 5106, 5107, - 5108, 5109, 42571, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, - 4315, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, - 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, - 4344, 4345, 4346, 4349, 4350, 4351, 592, 593, 7426, 604, 7446, 7447, 7453, 7461, - 594, 597, 607, 609, 613, 618, 7547, 669, 621, 7557, 671, 625, 624, 627, 628, 632, - 642, 427, 7452, 656, 657, 7681, 7683, 7685, 7687, 7689, 7691, 7693, 7695, 7697, - 7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717, 7719, 7721, 7723, 7725, - 7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745, 7747, 7749, 7751, 7753, - 7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773, 7775, 7777, 7779, 7781, - 7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801, 7803, 7805, 7807, 7809, - 7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829, 97, 702, 115, 115, 7841, - 7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861, 7863, 7865, 7867, 7869, - 7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889, 7891, 7893, 7895, 7897, - 7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917, 7919, 7921, 7923, 7925, - 7927, 7929, 7931, 7933, 7935, 7936, 7937, 7938, 7939, 7940, 7941, 7942, 7943, 7952, - 7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972, 7973, 7974, 7975, 7984, - 7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002, 8003, 8004, 8005, 8017, - 8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039, 7936, 953, 7937, - 953, 7938, 953, 7939, 953, 7940, 953, 7941, 953, 7942, 953, 7943, 953, 7968, 953, - 7969, 953, 7970, 953, 7971, 953, 7972, 953, 7973, 953, 7974, 953, 7975, 953, 8032, - 953, 8033, 953, 8034, 953, 8035, 953, 8036, 953, 8037, 953, 8038, 953, 8039, 953, - 8048, 953, 945, 953, 940, 953, 8118, 953, 8112, 8113, 32, 787, 32, 834, 32, 776, - 834, 8052, 953, 951, 953, 942, 953, 8134, 953, 8050, 32, 787, 768, 32, 787, 769, - 32, 787, 834, 912, 8144, 8145, 8054, 32, 788, 768, 32, 788, 769, 32, 788, 834, 944, - 8160, 8161, 8058, 8165, 32, 776, 768, 96, 8060, 953, 969, 953, 974, 953, 8182, 953, - 8056, 8208, 32, 819, 8242, 8242, 8242, 8242, 8242, 8245, 8245, 8245, 8245, 8245, - 33, 33, 32, 773, 63, 63, 63, 33, 33, 63, 48, 53, 54, 55, 56, 57, 43, 8722, 61, 40, - 41, 97, 47, 99, 97, 47, 115, 176, 99, 99, 47, 111, 99, 47, 117, 176, 102, 115, 109, - 116, 101, 108, 116, 109, 1488, 1489, 1490, 1491, 102, 97, 120, 8721, 49, 8260, 55, - 49, 8260, 57, 49, 8260, 49, 48, 49, 8260, 51, 50, 8260, 51, 49, 8260, 53, 50, 8260, - 53, 51, 8260, 53, 52, 8260, 53, 49, 8260, 54, 53, 8260, 54, 49, 8260, 56, 51, 8260, - 56, 53, 8260, 56, 55, 8260, 56, 105, 105, 105, 105, 105, 105, 118, 118, 105, 118, - 105, 105, 118, 105, 105, 105, 105, 120, 120, 105, 120, 105, 105, 48, 8260, 51, 8747, - 8747, 8747, 8747, 8747, 8750, 8750, 8750, 8750, 8750, 12296, 12297, 49, 50, 49, - 51, 49, 52, 49, 53, 49, 54, 49, 55, 49, 56, 49, 57, 50, 48, 40, 49, 41, 40, 50, - 41, 40, 51, 41, 40, 52, 41, 40, 53, 41, 40, 54, 41, 40, 55, 41, 40, 56, 41, 40, - 57, 41, 40, 49, 48, 41, 40, 49, 49, 41, 40, 49, 50, 41, 40, 49, 51, 41, 40, 49, - 52, 41, 40, 49, 53, 41, 40, 49, 54, 41, 40, 49, 55, 41, 40, 49, 56, 41, 40, 49, - 57, 41, 40, 50, 48, 41, 40, 97, 41, 40, 98, 41, 40, 99, 41, 40, 100, 41, 40, 101, - 41, 40, 102, 41, 40, 103, 41, 40, 104, 41, 40, 105, 41, 40, 106, 41, 40, 107, 41, - 40, 108, 41, 40, 109, 41, 40, 110, 41, 40, 111, 41, 40, 112, 41, 40, 113, 41, 40, - 114, 41, 40, 115, 41, 40, 116, 41, 40, 117, 41, 40, 118, 41, 40, 119, 41, 40, 120, - 41, 40, 121, 41, 40, 122, 41, 58, 58, 61, 61, 61, 10973, 824, 11312, 11313, 11314, - 11315, 11316, 11317, 11318, 11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, - 11327, 11328, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338, - 11339, 11340, 11341, 11342, 11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350, - 11351, 11352, 11353, 11354, 11355, 11356, 11357, 11358, 11359, 11361, 619, 7549, - 637, 11368, 11370, 11372, 11379, 11382, 575, 576, 11393, 11395, 11397, 11399, 11401, - 11403, 11405, 11407, 11409, 11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425, - 11427, 11429, 11431, 11433, 11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449, - 11451, 11453, 11455, 11457, 11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473, - 11475, 11477, 11479, 11481, 11483, 11485, 11487, 11489, 11491, 11500, 11502, 11507, - 11617, 27597, 40863, 19968, 20008, 20022, 20031, 20057, 20101, 20108, 20128, 20154, - 20799, 20837, 20843, 20866, 20886, 20907, 20960, 20981, 20992, 21147, 21241, 21269, - 21274, 21304, 21313, 21340, 21353, 21378, 21430, 21448, 21475, 22231, 22303, 22763, - 22786, 22794, 22805, 22823, 22899, 23376, 23424, 23544, 23567, 23586, 23608, 23662, - 23665, 24027, 24037, 24049, 24062, 24178, 24186, 24191, 24308, 24318, 24331, 24339, - 24400, 24417, 24435, 24515, 25096, 25142, 25163, 25903, 25908, 25991, 26007, 26020, - 26041, 26080, 26085, 26352, 26376, 26408, 27424, 27490, 27513, 27571, 27595, 27604, - 27611, 27663, 27668, 27700, 28779, 29226, 29238, 29243, 29247, 29255, 29273, 29275, - 29356, 29572, 29577, 29916, 29926, 29976, 29983, 29992, 30000, 30091, 30098, 30326, - 30333, 30382, 30399, 30446, 30683, 30690, 30707, 31034, 31160, 31166, 31348, 31435, - 31481, 31859, 31992, 32566, 32593, 32650, 32701, 32769, 32780, 32786, 32819, 32895, - 32905, 33251, 33258, 33267, 33276, 33292, 33307, 33311, 33390, 33394, 33400, 34381, - 34411, 34880, 34892, 34915, 35198, 35211, 35282, 35328, 35895, 35910, 35925, 35960, - 35997, 36196, 36208, 36275, 36523, 36554, 36763, 36784, 36789, 37009, 37193, 37318, - 37324, 37329, 38263, 38272, 38428, 38582, 38585, 38632, 38737, 38750, 38754, 38761, - 38859, 38893, 38899, 38913, 39080, 39131, 39135, 39318, 39321, 39340, 39592, 39640, - 39647, 39717, 39727, 39730, 39740, 39770, 40165, 40565, 40575, 40613, 40635, 40643, - 40653, 40657, 40697, 40701, 40718, 40723, 40736, 40763, 40778, 40786, 40845, 40860, - 40864, 46, 12306, 21316, 21317, 32, 12441, 32, 12442, 12424, 12426, 12467, 12488, - 4352, 4353, 4522, 4354, 4524, 4525, 4355, 4356, 4357, 4528, 4529, 4530, 4531, 4532, - 4533, 4378, 4358, 4359, 4360, 4385, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, - 4369, 4370, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, - 4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4372, 4373, 4551, 4552, 4556, - 4558, 4563, 4567, 4569, 4380, 4573, 4575, 4381, 4382, 4384, 4386, 4387, 4391, 4393, - 4395, 4396, 4397, 4398, 4399, 4402, 4406, 4416, 4423, 4428, 4593, 4594, 4439, 4440, - 4441, 4484, 4485, 4488, 4497, 4498, 4500, 4510, 4513, 19977, 22235, 19978, 20013, - 19979, 30002, 19993, 19969, 22825, 22320, 40, 4352, 41, 40, 4354, 41, 40, 4355, - 41, 40, 4357, 41, 40, 4358, 41, 40, 4359, 41, 40, 4361, 41, 40, 4363, 41, 40, 4364, - 41, 40, 4366, 41, 40, 4367, 41, 40, 4368, 41, 40, 4369, 41, 40, 4370, 41, 40, 44032, - 41, 40, 45208, 41, 40, 45796, 41, 40, 46972, 41, 40, 47560, 41, 40, 48148, 41, 40, - 49324, 41, 40, 50500, 41, 40, 51088, 41, 40, 52264, 41, 40, 52852, 41, 40, 53440, - 41, 40, 54028, 41, 40, 54616, 41, 40, 51452, 41, 40, 50724, 51204, 41, 40, 50724, - 54980, 41, 40, 19968, 41, 40, 20108, 41, 40, 19977, 41, 40, 22235, 41, 40, 20116, - 41, 40, 20845, 41, 40, 19971, 41, 40, 20843, 41, 40, 20061, 41, 40, 21313, 41, 40, - 26376, 41, 40, 28779, 41, 40, 27700, 41, 40, 26408, 41, 40, 37329, 41, 40, 22303, - 41, 40, 26085, 41, 40, 26666, 41, 40, 26377, 41, 40, 31038, 41, 40, 21517, 41, 40, - 29305, 41, 40, 36001, 41, 40, 31069, 41, 40, 21172, 41, 40, 20195, 41, 40, 21628, - 41, 40, 23398, 41, 40, 30435, 41, 40, 20225, 41, 40, 36039, 41, 40, 21332, 41, 40, - 31085, 41, 40, 20241, 41, 40, 33258, 41, 40, 33267, 41, 21839, 24188, 31631, 112, - 116, 101, 50, 50, 50, 52, 50, 53, 50, 54, 50, 55, 50, 56, 50, 57, 51, 48, 51, 51, - 51, 52, 51, 53, 52280, 44256, 51452, 51032, 50864, 31192, 30007, 36969, 20778, 21360, - 27880, 38917, 20889, 27491, 24038, 21491, 21307, 23447, 22812, 51, 54, 51, 55, 51, - 56, 51, 57, 52, 48, 52, 52, 52, 53, 52, 54, 52, 55, 52, 56, 52, 57, 53, 48, 49, - 26376, 50, 26376, 51, 26376, 52, 26376, 53, 26376, 54, 26376, 55, 26376, 56, 26376, - 57, 26376, 49, 48, 26376, 49, 49, 26376, 49, 50, 26376, 104, 103, 101, 114, 103, - 101, 118, 108, 116, 100, 12450, 12452, 12454, 12456, 12458, 12459, 12461, 12463, - 12465, 12469, 12471, 12473, 12475, 12477, 12479, 12481, 12484, 12486, 12490, 12491, - 12492, 12493, 12494, 12495, 12498, 12501, 12504, 12507, 12510, 12511, 12512, 12513, - 12514, 12516, 12518, 12520, 12521, 12522, 12523, 12524, 12525, 12527, 12528, 12529, - 12530, 20196, 21644, 12450, 12497, 12540, 12488, 12450, 12523, 12501, 12449, 12450, - 12531, 12506, 12450, 12450, 12540, 12523, 12452, 12491, 12531, 12464, 12452, 12531, - 12481, 12454, 12457, 12531, 12456, 12473, 12463, 12540, 12489, 12456, 12540, 12459, - 12540, 12458, 12531, 12473, 12458, 12540, 12512, 12459, 12452, 12522, 12459, 12521, - 12483, 12488, 12459, 12525, 12522, 12540, 12460, 12525, 12531, 12460, 12531, 12510, - 12462, 12460, 12462, 12491, 12540, 12461, 12517, 12522, 12540, 12462, 12523, 12480, - 12540, 12461, 12525, 12461, 12525, 12464, 12521, 12512, 12461, 12525, 12513, 12540, - 12488, 12523, 12461, 12525, 12527, 12483, 12488, 12464, 12521, 12512, 12488, 12531, - 12463, 12523, 12476, 12452, 12525, 12463, 12525, 12540, 12493, 12465, 12540, 12473, - 12467, 12523, 12490, 12467, 12540, 12509, 12469, 12452, 12463, 12523, 12469, 12531, - 12481, 12540, 12512, 12471, 12522, 12531, 12464, 12475, 12531, 12481, 12475, 12531, - 12488, 12480, 12540, 12473, 12487, 12471, 12489, 12523, 12490, 12494, 12494, 12483, - 12488, 12495, 12452, 12484, 12497, 12540, 12475, 12531, 12488, 12497, 12540, 12484, - 12496, 12540, 12524, 12523, 12500, 12450, 12473, 12488, 12523, 12500, 12463, 12523, - 12500, 12467, 12499, 12523, 12501, 12449, 12521, 12483, 12489, 12501, 12451, 12540, - 12488, 12502, 12483, 12471, 12455, 12523, 12501, 12521, 12531, 12504, 12463, 12479, - 12540, 12523, 12506, 12477, 12506, 12491, 12498, 12504, 12523, 12484, 12506, 12531, - 12473, 12506, 12540, 12472, 12505, 12540, 12479, 12509, 12452, 12531, 12488, 12508, - 12523, 12488, 12507, 12531, 12509, 12531, 12489, 12507, 12540, 12523, 12507, 12540, - 12531, 12510, 12452, 12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, 12510, - 12523, 12463, 12510, 12531, 12471, 12519, 12531, 12511, 12463, 12525, 12531, 12511, - 12522, 12511, 12522, 12496, 12540, 12523, 12513, 12460, 12513, 12460, 12488, 12531, - 12516, 12540, 12489, 12516, 12540, 12523, 12518, 12450, 12531, 12522, 12483, 12488, - 12523, 12522, 12521, 12523, 12500, 12540, 12523, 12540, 12502, 12523, 12524, 12512, - 12524, 12531, 12488, 12466, 12531, 48, 28857, 49, 28857, 50, 28857, 51, 28857, 52, - 28857, 53, 28857, 54, 28857, 55, 28857, 56, 28857, 57, 28857, 49, 48, 28857, 49, - 49, 28857, 49, 50, 28857, 49, 51, 28857, 49, 52, 28857, 49, 53, 28857, 49, 54, 28857, - 49, 55, 28857, 49, 56, 28857, 49, 57, 28857, 50, 48, 28857, 50, 49, 28857, 50, 50, - 28857, 50, 51, 28857, 50, 52, 28857, 104, 112, 97, 100, 97, 97, 117, 98, 97, 114, - 111, 118, 112, 99, 100, 109, 100, 109, 50, 100, 109, 51, 105, 117, 24179, 25104, - 26157, 21644, 22823, 27491, 26126, 27835, 26666, 24335, 20250, 31038, 110, 97, 956, - 97, 109, 97, 107, 97, 107, 98, 109, 98, 103, 98, 99, 97, 108, 107, 99, 97, 108, - 112, 102, 110, 102, 956, 102, 956, 103, 109, 103, 107, 103, 104, 122, 107, 104, - 122, 109, 104, 122, 116, 104, 122, 956, 108, 109, 108, 100, 108, 102, 109, 110, - 109, 956, 109, 109, 109, 99, 109, 107, 109, 109, 109, 50, 99, 109, 50, 107, 109, - 50, 109, 109, 51, 99, 109, 51, 107, 109, 51, 109, 8725, 115, 109, 8725, 115, 50, - 107, 112, 97, 109, 112, 97, 103, 112, 97, 114, 97, 100, 114, 97, 100, 8725, 115, - 114, 97, 100, 8725, 115, 50, 112, 115, 110, 115, 956, 115, 109, 115, 112, 118, 110, - 118, 956, 118, 109, 118, 107, 118, 112, 119, 110, 119, 956, 119, 109, 119, 107, - 119, 107, 969, 109, 969, 98, 113, 99, 8725, 107, 103, 100, 98, 103, 121, 104, 97, - 105, 110, 107, 107, 107, 116, 108, 110, 108, 111, 103, 108, 120, 109, 105, 108, - 109, 111, 108, 112, 104, 112, 112, 109, 112, 114, 115, 118, 119, 98, 118, 8725, - 109, 97, 8725, 109, 49, 26085, 50, 26085, 51, 26085, 52, 26085, 53, 26085, 54, 26085, - 55, 26085, 56, 26085, 57, 26085, 49, 48, 26085, 49, 49, 26085, 49, 50, 26085, 49, - 51, 26085, 49, 52, 26085, 49, 53, 26085, 49, 54, 26085, 49, 55, 26085, 49, 56, 26085, - 49, 57, 26085, 50, 48, 26085, 50, 49, 26085, 50, 50, 26085, 50, 51, 26085, 50, 52, - 26085, 50, 53, 26085, 50, 54, 26085, 50, 55, 26085, 50, 56, 26085, 50, 57, 26085, - 51, 48, 26085, 51, 49, 26085, 103, 97, 108, 42561, 42563, 42565, 42567, 42569, 42573, - 42575, 42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, 42593, 42595, 42597, - 42599, 42601, 42603, 42605, 42625, 42627, 42629, 42631, 42633, 42635, 42637, 42639, - 42641, 42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, 42793, 42795, 42797, - 42799, 42803, 42805, 42807, 42809, 42811, 42813, 42815, 42817, 42819, 42821, 42823, - 42825, 42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, 42843, 42845, 42847, - 42849, 42851, 42853, 42855, 42857, 42859, 42861, 42863, 42874, 42876, 7545, 42879, - 42881, 42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, 42907, 42909, 42911, - 42913, 42915, 42917, 42919, 42921, 620, 670, 647, 43859, 42933, 42935, 42937, 42939, - 42941, 42943, 42945, 42947, 42900, 7566, 42952, 42954, 42961, 42967, 42969, 42998, - 43831, 43858, 653, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, - 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048, - 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062, - 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076, - 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090, - 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 35912, - 26356, 36040, 28369, 20018, 21477, 22865, 21895, 22856, 25078, 30313, 32645, 34367, - 34746, 35064, 37007, 27138, 27931, 28889, 29662, 33853, 37226, 39409, 20098, 21365, - 27396, 29211, 34349, 40478, 23888, 28651, 34253, 35172, 25289, 33240, 34847, 24266, - 26391, 28010, 29436, 37070, 20358, 20919, 21214, 25796, 27347, 29200, 30439, 34310, - 34396, 36335, 38706, 39791, 40442, 30860, 31103, 32160, 33737, 37636, 35542, 22751, - 24324, 31840, 32894, 29282, 30922, 36034, 38647, 22744, 23650, 27155, 28122, 28431, - 32047, 32311, 38475, 21202, 32907, 20956, 20940, 31260, 32190, 33777, 38517, 35712, - 25295, 35582, 20025, 23527, 24594, 29575, 30064, 21271, 30971, 20415, 24489, 19981, - 27852, 25976, 32034, 21443, 22622, 30465, 33865, 35498, 27578, 27784, 25342, 33509, - 25504, 30053, 20142, 20841, 20937, 26753, 31975, 33391, 35538, 37327, 21237, 21570, - 24300, 26053, 28670, 31018, 38317, 39530, 40599, 40654, 26310, 27511, 36706, 24180, - 24976, 25088, 25754, 28451, 29001, 29833, 31178, 32244, 32879, 36646, 34030, 36899, - 37706, 21015, 21155, 21693, 28872, 35010, 24265, 24565, 25467, 27566, 31806, 29557, - 22265, 23994, 24604, 29618, 29801, 32666, 32838, 37428, 38646, 38728, 38936, 20363, - 31150, 37300, 38584, 24801, 20102, 20698, 23534, 23615, 26009, 29134, 30274, 34044, - 36988, 26248, 38446, 21129, 26491, 26611, 27969, 28316, 29705, 30041, 30827, 32016, - 39006, 25134, 38520, 20523, 23833, 28138, 36650, 24459, 24900, 26647, 38534, 21033, - 21519, 23653, 26131, 26446, 26792, 27877, 29702, 30178, 32633, 35023, 35041, 38626, - 21311, 28346, 21533, 29136, 29848, 34298, 38563, 40023, 40607, 26519, 28107, 33256, - 31520, 31890, 29376, 28825, 35672, 20160, 33590, 21050, 20999, 24230, 25299, 31958, - 23429, 27934, 26292, 36667, 38477, 24275, 20800, 21952, 22618, 26228, 20958, 29482, - 30410, 31036, 31070, 31077, 31119, 38742, 31934, 34322, 35576, 36920, 37117, 39151, - 39164, 39208, 40372, 37086, 38583, 20398, 20711, 20813, 21193, 21220, 21329, 21917, - 22022, 22120, 22592, 22696, 23652, 24724, 24936, 24974, 25074, 25935, 26082, 26257, - 26757, 28023, 28186, 28450, 29038, 29227, 29730, 30865, 31049, 31048, 31056, 31062, - 31117, 31118, 31296, 31361, 31680, 32265, 32321, 32626, 32773, 33261, 33401, 33879, - 35088, 35222, 35585, 35641, 36051, 36104, 36790, 38627, 38911, 38971, 24693, 148206, - 33304, 20006, 20917, 20840, 20352, 20805, 20864, 21191, 21242, 21845, 21913, 21986, - 22707, 22852, 22868, 23138, 23336, 24274, 24281, 24425, 24493, 24792, 24910, 24840, - 24928, 25140, 25540, 25628, 25682, 25942, 26395, 26454, 28379, 28363, 28702, 30631, - 29237, 29359, 29809, 29958, 30011, 30237, 30239, 30427, 30452, 30538, 30528, 30924, - 31409, 31867, 32091, 32574, 33618, 33775, 34681, 35137, 35206, 35519, 35531, 35565, - 35722, 36664, 36978, 37273, 37494, 38524, 38875, 38923, 39698, 141386, 141380, 144341, - 15261, 16408, 16441, 152137, 154832, 163539, 40771, 40846, 102, 102, 102, 105, 102, - 108, 102, 102, 108, 1396, 1398, 1396, 1381, 1396, 1387, 1406, 1398, 1396, 1389, - 1497, 1460, 1522, 1463, 1506, 1492, 1499, 1500, 1501, 1512, 1514, 1513, 1473, 1513, - 1474, 1513, 1468, 1473, 1513, 1468, 1474, 1488, 1463, 1488, 1464, 1488, 1468, 1489, - 1468, 1490, 1468, 1491, 1468, 1492, 1468, 1493, 1468, 1494, 1468, 1496, 1468, 1497, - 1468, 1498, 1468, 1499, 1468, 1500, 1468, 1502, 1468, 1504, 1468, 1505, 1468, 1507, - 1468, 1508, 1468, 1510, 1468, 1511, 1468, 1512, 1468, 1514, 1468, 1493, 1465, 1489, - 1471, 1499, 1471, 1508, 1471, 1488, 1500, 1649, 1659, 1662, 1664, 1658, 1663, 1657, - 1700, 1702, 1668, 1667, 1670, 1671, 1677, 1676, 1678, 1672, 1688, 1681, 1705, 1711, - 1715, 1713, 1722, 1723, 1728, 1729, 1726, 1746, 1747, 1709, 1734, 1736, 1739, 1733, - 1737, 1744, 1609, 1574, 1575, 1574, 1749, 1574, 1608, 1574, 1735, 1574, 1734, 1574, - 1736, 1574, 1744, 1574, 1609, 1740, 1574, 1580, 1574, 1581, 1574, 1605, 1574, 1610, - 1576, 1580, 1576, 1581, 1576, 1582, 1576, 1605, 1576, 1609, 1576, 1610, 1578, 1580, - 1578, 1581, 1578, 1582, 1578, 1605, 1578, 1609, 1578, 1610, 1579, 1580, 1579, 1605, - 1579, 1609, 1579, 1610, 1580, 1581, 1580, 1605, 1581, 1605, 1582, 1580, 1582, 1581, - 1582, 1605, 1587, 1580, 1587, 1581, 1587, 1582, 1587, 1605, 1589, 1581, 1589, 1605, - 1590, 1580, 1590, 1581, 1590, 1582, 1590, 1605, 1591, 1581, 1591, 1605, 1592, 1605, - 1593, 1580, 1593, 1605, 1594, 1580, 1594, 1605, 1601, 1580, 1601, 1581, 1601, 1582, - 1601, 1605, 1601, 1609, 1601, 1610, 1602, 1581, 1602, 1605, 1602, 1609, 1602, 1610, - 1603, 1575, 1603, 1580, 1603, 1581, 1603, 1582, 1603, 1604, 1603, 1605, 1603, 1609, - 1603, 1610, 1604, 1580, 1604, 1581, 1604, 1582, 1604, 1605, 1604, 1609, 1604, 1610, - 1605, 1580, 1605, 1605, 1605, 1609, 1605, 1610, 1606, 1580, 1606, 1581, 1606, 1582, - 1606, 1605, 1606, 1609, 1606, 1610, 1607, 1580, 1607, 1605, 1607, 1609, 1607, 1610, - 1610, 1581, 1610, 1582, 1610, 1609, 1584, 1648, 1585, 1648, 1609, 1648, 32, 1612, - 1617, 32, 1613, 1617, 32, 1614, 1617, 32, 1615, 1617, 32, 1616, 1617, 32, 1617, - 1648, 1574, 1585, 1574, 1586, 1574, 1606, 1576, 1585, 1576, 1586, 1576, 1606, 1578, - 1585, 1578, 1586, 1578, 1606, 1579, 1585, 1579, 1586, 1579, 1606, 1605, 1575, 1606, - 1585, 1606, 1586, 1606, 1606, 1610, 1585, 1610, 1586, 1574, 1582, 1574, 1607, 1576, - 1607, 1578, 1607, 1589, 1582, 1604, 1607, 1606, 1607, 1607, 1648, 1579, 1607, 1587, - 1607, 1588, 1605, 1588, 1607, 1600, 1614, 1617, 1600, 1615, 1617, 1600, 1616, 1617, - 1591, 1609, 1591, 1610, 1593, 1609, 1593, 1610, 1594, 1609, 1594, 1610, 1587, 1609, - 1587, 1610, 1588, 1609, 1588, 1610, 1581, 1609, 1580, 1609, 1580, 1610, 1582, 1609, - 1589, 1609, 1589, 1610, 1590, 1609, 1590, 1610, 1588, 1580, 1588, 1581, 1588, 1582, - 1588, 1585, 1587, 1585, 1589, 1585, 1590, 1585, 1575, 1611, 1578, 1580, 1605, 1578, - 1581, 1580, 1578, 1581, 1605, 1578, 1582, 1605, 1578, 1605, 1580, 1578, 1605, 1581, - 1578, 1605, 1582, 1581, 1605, 1610, 1581, 1605, 1609, 1587, 1581, 1580, 1587, 1580, - 1581, 1587, 1580, 1609, 1587, 1605, 1581, 1587, 1605, 1580, 1587, 1605, 1605, 1589, - 1581, 1581, 1589, 1605, 1605, 1588, 1581, 1605, 1588, 1580, 1610, 1588, 1605, 1582, - 1588, 1605, 1605, 1590, 1581, 1609, 1590, 1582, 1605, 1591, 1605, 1581, 1591, 1605, - 1605, 1591, 1605, 1610, 1593, 1580, 1605, 1593, 1605, 1605, 1593, 1605, 1609, 1594, - 1605, 1605, 1594, 1605, 1610, 1594, 1605, 1609, 1601, 1582, 1605, 1602, 1605, 1581, - 1602, 1605, 1605, 1604, 1581, 1605, 1604, 1581, 1610, 1604, 1581, 1609, 1604, 1580, - 1580, 1604, 1582, 1605, 1604, 1605, 1581, 1605, 1581, 1580, 1605, 1581, 1610, 1605, - 1580, 1581, 1605, 1582, 1605, 1605, 1580, 1582, 1607, 1605, 1580, 1607, 1605, 1605, - 1606, 1581, 1605, 1606, 1581, 1609, 1606, 1580, 1605, 1606, 1580, 1609, 1606, 1605, - 1610, 1606, 1605, 1609, 1610, 1605, 1605, 1576, 1582, 1610, 1578, 1580, 1610, 1578, - 1580, 1609, 1578, 1582, 1610, 1578, 1582, 1609, 1578, 1605, 1610, 1578, 1605, 1609, - 1580, 1605, 1610, 1580, 1581, 1609, 1580, 1605, 1609, 1587, 1582, 1609, 1589, 1581, - 1610, 1588, 1581, 1610, 1590, 1581, 1610, 1604, 1580, 1610, 1604, 1605, 1610, 1610, - 1580, 1610, 1610, 1605, 1610, 1605, 1605, 1610, 1602, 1605, 1610, 1606, 1581, 1610, - 1593, 1605, 1610, 1603, 1605, 1610, 1606, 1580, 1581, 1605, 1582, 1610, 1604, 1580, - 1605, 1603, 1605, 1605, 1580, 1581, 1610, 1581, 1580, 1610, 1605, 1580, 1610, 1601, - 1605, 1610, 1576, 1581, 1610, 1587, 1582, 1610, 1606, 1580, 1610, 1589, 1604, 1746, - 1602, 1604, 1746, 1575, 1604, 1604, 1607, 1575, 1603, 1576, 1585, 1605, 1581, 1605, - 1583, 1589, 1604, 1593, 1605, 1585, 1587, 1608, 1604, 1593, 1604, 1610, 1607, 1608, - 1587, 1604, 1605, 1589, 1604, 1609, 1589, 1604, 1609, 32, 1575, 1604, 1604, 1607, - 32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605, 1580, 1604, 32, 1580, 1604, - 1575, 1604, 1607, 1585, 1740, 1575, 1604, 44, 12289, 12310, 12311, 8212, 8211, 95, - 123, 125, 12308, 12309, 12304, 12305, 12298, 12299, 12300, 12301, 12302, 12303, - 91, 93, 35, 38, 42, 45, 60, 62, 92, 36, 37, 64, 32, 1611, 1600, 1611, 1600, 1617, - 32, 1618, 1600, 1618, 1569, 1570, 1571, 1572, 1573, 1577, 1604, 1570, 1604, 1571, - 1604, 1573, 34, 39, 94, 124, 126, 10629, 10630, 12539, 12453, 12515, 162, 163, 172, - 166, 165, 8361, 9474, 8592, 8593, 8594, 8595, 9632, 9675, 66600, 66601, 66602, 66603, - 66604, 66605, 66606, 66607, 66608, 66609, 66610, 66611, 66612, 66613, 66614, 66615, - 66616, 66617, 66618, 66619, 66620, 66621, 66622, 66623, 66624, 66625, 66626, 66627, - 66628, 66629, 66630, 66631, 66632, 66633, 66634, 66635, 66636, 66637, 66638, 66639, - 66776, 66777, 66778, 66779, 66780, 66781, 66782, 66783, 66784, 66785, 66786, 66787, - 66788, 66789, 66790, 66791, 66792, 66793, 66794, 66795, 66796, 66797, 66798, 66799, - 66800, 66801, 66802, 66803, 66804, 66805, 66806, 66807, 66808, 66809, 66810, 66811, - 66967, 66968, 66969, 66970, 66971, 66972, 66973, 66974, 66975, 66976, 66977, 66979, - 66980, 66981, 66982, 66983, 66984, 66985, 66986, 66987, 66988, 66989, 66990, 66991, - 66992, 66993, 66995, 66996, 66997, 66998, 66999, 67000, 67001, 67003, 67004, 720, - 721, 665, 675, 43878, 677, 676, 7569, 600, 606, 681, 612, 610, 667, 668, 615, 644, - 682, 683, 122628, 42894, 622, 122629, 654, 122630, 630, 631, 634, 122632, 638, 680, - 678, 43879, 679, 11377, 655, 673, 674, 664, 448, 449, 450, 122634, 122654, 68800, - 68801, 68802, 68803, 68804, 68805, 68806, 68807, 68808, 68809, 68810, 68811, 68812, - 68813, 68814, 68815, 68816, 68817, 68818, 68819, 68820, 68821, 68822, 68823, 68824, - 68825, 68826, 68827, 68828, 68829, 68830, 68831, 68832, 68833, 68834, 68835, 68836, - 68837, 68838, 68839, 68840, 68841, 68842, 68843, 68844, 68845, 68846, 68847, 68848, - 68849, 68850, 71872, 71873, 71874, 71875, 71876, 71877, 71878, 71879, 71880, 71881, - 71882, 71883, 71884, 71885, 71886, 71887, 71888, 71889, 71890, 71891, 71892, 71893, - 71894, 71895, 71896, 71897, 71898, 71899, 71900, 71901, 71902, 71903, 93792, 93793, - 93794, 93795, 93796, 93797, 93798, 93799, 93800, 93801, 93802, 93803, 93804, 93805, - 93806, 93807, 93808, 93809, 93810, 93811, 93812, 93813, 93814, 93815, 93816, 93817, - 93818, 93819, 93820, 93821, 93822, 93823, 119127, 119141, 119128, 119141, 119128, - 119141, 119150, 119128, 119141, 119151, 119128, 119141, 119152, 119128, 119141, - 119153, 119128, 119141, 119154, 119225, 119141, 119226, 119141, 119225, 119141, - 119150, 119226, 119141, 119150, 119225, 119141, 119151, 119226, 119141, 119151, - 305, 567, 8711, 8706, 1231, 125218, 125219, 125220, 125221, 125222, 125223, 125224, - 125225, 125226, 125227, 125228, 125229, 125230, 125231, 125232, 125233, 125234, - 125235, 125236, 125237, 125238, 125239, 125240, 125241, 125242, 125243, 125244, - 125245, 125246, 125247, 125248, 125249, 125250, 125251, 1646, 1697, 1647, 48, 44, - 49, 44, 50, 44, 51, 44, 52, 44, 53, 44, 54, 44, 55, 44, 56, 44, 57, 44, 12308, 115, - 12309, 119, 122, 104, 118, 115, 100, 112, 112, 118, 119, 99, 109, 114, 100, 106, - 12411, 12363, 12467, 12467, 23383, 21452, 22810, 35299, 20132, 26144, 28961, 21069, - 24460, 20877, 26032, 21021, 32066, 36009, 22768, 21561, 28436, 25237, 25429, 36938, - 25351, 25171, 31105, 31354, 21512, 28288, 30003, 21106, 21942, 37197, 12308, 26412, - 12309, 12308, 19977, 12309, 12308, 20108, 12309, 12308, 23433, 12309, 12308, 28857, - 12309, 12308, 25171, 12309, 12308, 30423, 12309, 12308, 21213, 12309, 12308, 25943, - 12309, 24471, 21487, 20029, 20024, 20033, 131362, 20320, 20411, 20482, 20602, 20633, - 20687, 13470, 132666, 20820, 20836, 20855, 132380, 13497, 20839, 132427, 20887, - 20900, 20172, 20908, 168415, 20995, 13535, 21051, 21062, 21111, 13589, 21253, 21254, - 21321, 21338, 21363, 21373, 21375, 133676, 28784, 21450, 21471, 133987, 21483, 21489, - 21510, 21662, 21560, 21576, 21608, 21666, 21750, 21776, 21843, 21859, 21892, 21931, - 21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, 22516, 22541, 22411, 22578, - 22577, 22700, 136420, 22770, 22775, 22790, 22818, 22882, 136872, 136938, 23020, - 23067, 23079, 23000, 23142, 14062, 23304, 23358, 137672, 23491, 23512, 23539, 138008, - 23551, 23558, 14209, 23648, 23744, 23693, 138724, 23875, 138726, 23918, 23915, 23932, - 24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434, 139651, 14460, 24240, 24243, - 24246, 172946, 140081, 33281, 24354, 14535, 144056, 156122, 24418, 24427, 14563, - 24474, 24525, 24535, 24569, 24705, 14650, 14620, 141012, 24775, 24904, 24908, 24954, - 25010, 24996, 25007, 25054, 25115, 25181, 25265, 25300, 25424, 142092, 25405, 25340, - 25448, 25475, 25572, 142321, 25634, 25541, 25513, 14894, 25705, 25726, 25757, 25719, - 14956, 25964, 143370, 26083, 26360, 26185, 15129, 15112, 15076, 20882, 20885, 26368, - 26268, 32941, 17369, 26401, 26462, 26451, 144323, 15177, 26618, 26501, 26706, 144493, - 26766, 26655, 26900, 26946, 27043, 27114, 27304, 145059, 27355, 15384, 27425, 145575, - 27476, 15438, 27506, 27551, 27579, 146061, 138507, 146170, 27726, 146620, 27839, - 27853, 27751, 27926, 27966, 28009, 28024, 28037, 146718, 27956, 28207, 28270, 15667, - 28359, 147153, 28153, 28526, 147294, 147342, 28614, 28729, 28699, 15766, 28746, - 28797, 28791, 28845, 132389, 28997, 148067, 29084, 29224, 29264, 149000, 29312, - 29333, 149301, 149524, 29562, 29579, 16044, 29605, 16056, 29767, 29788, 29829, 29898, - 16155, 29988, 150582, 30014, 150674, 139679, 30224, 151457, 151480, 151620, 16380, - 16392, 151795, 151794, 151833, 151859, 30494, 30495, 30603, 16454, 16534, 152605, - 30798, 16611, 153126, 153242, 153285, 31211, 16687, 31306, 31311, 153980, 154279, - 16898, 154539, 31686, 31689, 16935, 154752, 31954, 17056, 31976, 31971, 32000, 155526, - 32099, 17153, 32199, 32258, 32325, 17204, 156200, 156231, 17241, 156377, 32634, - 156478, 32661, 32762, 156890, 156963, 32864, 157096, 32880, 144223, 17365, 32946, - 33027, 17419, 33086, 23221, 157607, 157621, 144275, 144284, 33284, 36766, 17515, - 33425, 33419, 33437, 21171, 33457, 33459, 33469, 33510, 158524, 33565, 33635, 33709, - 33571, 33725, 33767, 33619, 33738, 33740, 33756, 158774, 159083, 158933, 17707, - 34033, 34035, 34070, 160714, 34148, 159532, 17757, 17761, 159665, 159954, 17771, - 34384, 34407, 34409, 34473, 34440, 34574, 34530, 34600, 34667, 34694, 34785, 34817, - 17913, 34912, 161383, 35031, 35038, 17973, 35066, 13499, 161966, 162150, 18110, - 18119, 35488, 162984, 36011, 36033, 36123, 36215, 163631, 133124, 36299, 36284, - 36336, 133342, 36564, 165330, 165357, 37012, 37105, 37137, 165678, 37147, 37432, - 37591, 37592, 37500, 37881, 37909, 166906, 38283, 18837, 38327, 167287, 18918, 38595, - 23986, 38691, 168261, 168474, 19054, 19062, 38880, 168970, 19122, 169110, 38953, - 169398, 39138, 19251, 39209, 39335, 39362, 39422, 19406, 170800, 40000, 40189, 19662, - 19693, 40295, 172238, 19704, 172293, 172558, 172689, 19798, 40702, 40709, 40719, - 40726, 173568, + 1231, 1218, 1220, 1222, 1224, 1226, 1228, 1230, 1233, 1235, 1237, 1239, 1241, 1243, + 1245, 1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1271, + 1273, 1275, 1277, 1279, 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299, + 1301, 1303, 1305, 1307, 1309, 1311, 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327, + 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, + 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, + 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, 1575, 1652, + 1608, 1652, 1735, 1652, 1610, 1652, 2325, 2364, 2326, 2364, 2327, 2364, 2332, 2364, + 2337, 2364, 2338, 2364, 2347, 2364, 2351, 2364, 2465, 2492, 2466, 2492, 2479, 2492, + 2610, 2620, 2616, 2620, 2582, 2620, 2583, 2620, 2588, 2620, 2603, 2620, 2849, 2876, + 2850, 2876, 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, 3851, 3906, 4023, 3916, + 4023, 3921, 4023, 3926, 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, 3956, 4018, + 3968, 4018, 3953, 3968, 4019, 3968, 4019, 3953, 3968, 3986, 4023, 3996, 4023, 4001, + 4023, 4006, 4023, 4011, 4023, 3984, 4021, 11520, 11521, 11522, 11523, 11524, 11525, + 11526, 11527, 11528, 11529, 11530, 11531, 11532, 11533, 11534, 11535, 11536, 11537, + 11538, 11539, 11540, 11541, 11542, 11543, 11544, 11545, 11546, 11547, 11548, 11549, + 11550, 11551, 11552, 11553, 11554, 11555, 11556, 11557, 11559, 11565, 4316, 5104, + 5105, 5106, 5107, 5108, 5109, 42571, 7306, 4304, 4305, 4306, 4307, 4308, 4309, 4310, + 4311, 4312, 4313, 4314, 4315, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, + 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, + 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4349, 4350, 4351, 592, 593, 7426, 604, + 7446, 7447, 7453, 7461, 594, 597, 607, 609, 613, 618, 7547, 669, 621, 7557, 671, + 625, 624, 627, 628, 632, 642, 427, 7452, 656, 657, 7681, 7683, 7685, 7687, 7689, + 7691, 7693, 7695, 7697, 7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717, + 7719, 7721, 7723, 7725, 7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745, + 7747, 7749, 7751, 7753, 7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773, + 7775, 7777, 7779, 7781, 7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801, + 7803, 7805, 7807, 7809, 7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829, + 97, 702, 223, 7841, 7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861, + 7863, 7865, 7867, 7869, 7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889, + 7891, 7893, 7895, 7897, 7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917, + 7919, 7921, 7923, 7925, 7927, 7929, 7931, 7933, 7935, 7936, 7937, 7938, 7939, 7940, + 7941, 7942, 7943, 7952, 7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972, + 7973, 7974, 7975, 7984, 7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002, + 8003, 8004, 8005, 8017, 8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038, + 8039, 7936, 953, 7937, 953, 7938, 953, 7939, 953, 7940, 953, 7941, 953, 7942, 953, + 7943, 953, 7968, 953, 7969, 953, 7970, 953, 7971, 953, 7972, 953, 7973, 953, 7974, + 953, 7975, 953, 8032, 953, 8033, 953, 8034, 953, 8035, 953, 8036, 953, 8037, 953, + 8038, 953, 8039, 953, 8048, 953, 945, 953, 940, 953, 8118, 953, 8112, 8113, 32, + 787, 32, 834, 32, 776, 834, 8052, 953, 951, 953, 942, 953, 8134, 953, 8050, 32, + 787, 768, 32, 787, 769, 32, 787, 834, 912, 8144, 8145, 8054, 32, 788, 768, 32, 788, + 769, 32, 788, 834, 944, 8160, 8161, 8058, 8165, 32, 776, 768, 96, 8060, 953, 969, + 953, 974, 953, 8182, 953, 8056, 8208, 32, 819, 8242, 8242, 8242, 8242, 8242, 8245, + 8245, 8245, 8245, 8245, 33, 33, 32, 773, 63, 63, 63, 33, 33, 63, 48, 53, 54, 55, + 56, 57, 43, 8722, 61, 40, 41, 97, 47, 99, 97, 47, 115, 176, 99, 99, 47, 111, 99, + 47, 117, 176, 102, 115, 109, 116, 101, 108, 116, 109, 8526, 1488, 1489, 1490, 1491, + 102, 97, 120, 8721, 49, 8260, 55, 49, 8260, 57, 49, 8260, 49, 48, 49, 8260, 51, + 50, 8260, 51, 49, 8260, 53, 50, 8260, 53, 51, 8260, 53, 52, 8260, 53, 49, 8260, + 54, 53, 8260, 54, 49, 8260, 56, 51, 8260, 56, 53, 8260, 56, 55, 8260, 56, 105, 105, + 105, 105, 105, 105, 118, 118, 105, 118, 105, 105, 118, 105, 105, 105, 105, 120, + 120, 105, 120, 105, 105, 8580, 48, 8260, 51, 8747, 8747, 8747, 8747, 8747, 8750, + 8750, 8750, 8750, 8750, 12296, 12297, 49, 50, 49, 51, 49, 52, 49, 53, 49, 54, 49, + 55, 49, 56, 49, 57, 50, 48, 40, 49, 41, 40, 50, 41, 40, 51, 41, 40, 52, 41, 40, + 53, 41, 40, 54, 41, 40, 55, 41, 40, 56, 41, 40, 57, 41, 40, 49, 48, 41, 40, 49, + 49, 41, 40, 49, 50, 41, 40, 49, 51, 41, 40, 49, 52, 41, 40, 49, 53, 41, 40, 49, + 54, 41, 40, 49, 55, 41, 40, 49, 56, 41, 40, 49, 57, 41, 40, 50, 48, 41, 40, 97, + 41, 40, 98, 41, 40, 99, 41, 40, 100, 41, 40, 101, 41, 40, 102, 41, 40, 103, 41, + 40, 104, 41, 40, 105, 41, 40, 106, 41, 40, 107, 41, 40, 108, 41, 40, 109, 41, 40, + 110, 41, 40, 111, 41, 40, 112, 41, 40, 113, 41, 40, 114, 41, 40, 115, 41, 40, 116, + 41, 40, 117, 41, 40, 118, 41, 40, 119, 41, 40, 120, 41, 40, 121, 41, 40, 122, 41, + 58, 58, 61, 61, 61, 10973, 824, 11312, 11313, 11314, 11315, 11316, 11317, 11318, + 11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, 11327, 11328, 11329, 11330, + 11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338, 11339, 11340, 11341, 11342, + 11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350, 11351, 11352, 11353, 11354, + 11355, 11356, 11357, 11358, 11359, 11361, 619, 7549, 637, 11368, 11370, 11372, 11379, + 11382, 575, 576, 11393, 11395, 11397, 11399, 11401, 11403, 11405, 11407, 11409, + 11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425, 11427, 11429, 11431, 11433, + 11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449, 11451, 11453, 11455, 11457, + 11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473, 11475, 11477, 11479, 11481, + 11483, 11485, 11487, 11489, 11491, 11500, 11502, 11507, 11617, 27597, 40863, 19968, + 20008, 20022, 20031, 20057, 20101, 20108, 20128, 20154, 20799, 20837, 20843, 20866, + 20886, 20907, 20960, 20981, 20992, 21147, 21241, 21269, 21274, 21304, 21313, 21340, + 21353, 21378, 21430, 21448, 21475, 22231, 22303, 22763, 22786, 22794, 22805, 22823, + 22899, 23376, 23424, 23544, 23567, 23586, 23608, 23662, 23665, 24027, 24037, 24049, + 24062, 24178, 24186, 24191, 24308, 24318, 24331, 24339, 24400, 24417, 24435, 24515, + 25096, 25142, 25163, 25903, 25908, 25991, 26007, 26020, 26041, 26080, 26085, 26352, + 26376, 26408, 27424, 27490, 27513, 27571, 27595, 27604, 27611, 27663, 27668, 27700, + 28779, 29226, 29238, 29243, 29247, 29255, 29273, 29275, 29356, 29572, 29577, 29916, + 29926, 29976, 29983, 29992, 30000, 30091, 30098, 30326, 30333, 30382, 30399, 30446, + 30683, 30690, 30707, 31034, 31160, 31166, 31348, 31435, 31481, 31859, 31992, 32566, + 32593, 32650, 32701, 32769, 32780, 32786, 32819, 32895, 32905, 33251, 33258, 33267, + 33276, 33292, 33307, 33311, 33390, 33394, 33400, 34381, 34411, 34880, 34892, 34915, + 35198, 35211, 35282, 35328, 35895, 35910, 35925, 35960, 35997, 36196, 36208, 36275, + 36523, 36554, 36763, 36784, 36789, 37009, 37193, 37318, 37324, 37329, 38263, 38272, + 38428, 38582, 38585, 38632, 38737, 38750, 38754, 38761, 38859, 38893, 38899, 38913, + 39080, 39131, 39135, 39318, 39321, 39340, 39592, 39640, 39647, 39717, 39727, 39730, + 39740, 39770, 40165, 40565, 40575, 40613, 40635, 40643, 40653, 40657, 40697, 40701, + 40718, 40723, 40736, 40763, 40778, 40786, 40845, 40860, 40864, 46, 12306, 21316, + 21317, 32, 12441, 32, 12442, 12424, 12426, 12467, 12488, 4352, 4353, 4522, 4354, + 4524, 4525, 4355, 4356, 4357, 4528, 4529, 4530, 4531, 4532, 4533, 4378, 4358, 4359, + 4360, 4385, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4449, 4450, + 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, + 4465, 4466, 4467, 4468, 4469, 4372, 4373, 4551, 4552, 4556, 4558, 4563, 4567, 4569, + 4380, 4573, 4575, 4381, 4382, 4384, 4386, 4387, 4391, 4393, 4395, 4396, 4397, 4398, + 4399, 4402, 4406, 4416, 4423, 4428, 4593, 4594, 4439, 4440, 4441, 4484, 4485, 4488, + 4497, 4498, 4500, 4510, 4513, 19977, 22235, 19978, 20013, 19979, 30002, 19993, 19969, + 22825, 22320, 40, 4352, 41, 40, 4354, 41, 40, 4355, 41, 40, 4357, 41, 40, 4358, + 41, 40, 4359, 41, 40, 4361, 41, 40, 4363, 41, 40, 4364, 41, 40, 4366, 41, 40, 4367, + 41, 40, 4368, 41, 40, 4369, 41, 40, 4370, 41, 40, 44032, 41, 40, 45208, 41, 40, + 45796, 41, 40, 46972, 41, 40, 47560, 41, 40, 48148, 41, 40, 49324, 41, 40, 50500, + 41, 40, 51088, 41, 40, 52264, 41, 40, 52852, 41, 40, 53440, 41, 40, 54028, 41, 40, + 54616, 41, 40, 51452, 41, 40, 50724, 51204, 41, 40, 50724, 54980, 41, 40, 19968, + 41, 40, 20108, 41, 40, 19977, 41, 40, 22235, 41, 40, 20116, 41, 40, 20845, 41, 40, + 19971, 41, 40, 20843, 41, 40, 20061, 41, 40, 21313, 41, 40, 26376, 41, 40, 28779, + 41, 40, 27700, 41, 40, 26408, 41, 40, 37329, 41, 40, 22303, 41, 40, 26085, 41, 40, + 26666, 41, 40, 26377, 41, 40, 31038, 41, 40, 21517, 41, 40, 29305, 41, 40, 36001, + 41, 40, 31069, 41, 40, 21172, 41, 40, 20195, 41, 40, 21628, 41, 40, 23398, 41, 40, + 30435, 41, 40, 20225, 41, 40, 36039, 41, 40, 21332, 41, 40, 31085, 41, 40, 20241, + 41, 40, 33258, 41, 40, 33267, 41, 21839, 24188, 31631, 112, 116, 101, 50, 50, 50, + 52, 50, 53, 50, 54, 50, 55, 50, 56, 50, 57, 51, 48, 51, 51, 51, 52, 51, 53, 52280, + 44256, 51452, 51032, 50864, 31192, 30007, 36969, 20778, 21360, 27880, 38917, 20889, + 27491, 24038, 21491, 21307, 23447, 22812, 51, 54, 51, 55, 51, 56, 51, 57, 52, 48, + 52, 52, 52, 53, 52, 54, 52, 55, 52, 56, 52, 57, 53, 48, 49, 26376, 50, 26376, 51, + 26376, 52, 26376, 53, 26376, 54, 26376, 55, 26376, 56, 26376, 57, 26376, 49, 48, + 26376, 49, 49, 26376, 49, 50, 26376, 104, 103, 101, 114, 103, 101, 118, 108, 116, + 100, 12450, 12452, 12454, 12456, 12458, 12459, 12461, 12463, 12465, 12469, 12471, + 12473, 12475, 12477, 12479, 12481, 12484, 12486, 12490, 12491, 12492, 12493, 12494, + 12495, 12498, 12501, 12504, 12507, 12510, 12511, 12512, 12513, 12514, 12516, 12518, + 12520, 12521, 12522, 12523, 12524, 12525, 12527, 12528, 12529, 12530, 20196, 21644, + 12450, 12497, 12540, 12488, 12450, 12523, 12501, 12449, 12450, 12531, 12506, 12450, + 12450, 12540, 12523, 12452, 12491, 12531, 12464, 12452, 12531, 12481, 12454, 12457, + 12531, 12456, 12473, 12463, 12540, 12489, 12456, 12540, 12459, 12540, 12458, 12531, + 12473, 12458, 12540, 12512, 12459, 12452, 12522, 12459, 12521, 12483, 12488, 12459, + 12525, 12522, 12540, 12460, 12525, 12531, 12460, 12531, 12510, 12462, 12460, 12462, + 12491, 12540, 12461, 12517, 12522, 12540, 12462, 12523, 12480, 12540, 12461, 12525, + 12461, 12525, 12464, 12521, 12512, 12461, 12525, 12513, 12540, 12488, 12523, 12461, + 12525, 12527, 12483, 12488, 12464, 12521, 12512, 12488, 12531, 12463, 12523, 12476, + 12452, 12525, 12463, 12525, 12540, 12493, 12465, 12540, 12473, 12467, 12523, 12490, + 12467, 12540, 12509, 12469, 12452, 12463, 12523, 12469, 12531, 12481, 12540, 12512, + 12471, 12522, 12531, 12464, 12475, 12531, 12481, 12475, 12531, 12488, 12480, 12540, + 12473, 12487, 12471, 12489, 12523, 12490, 12494, 12494, 12483, 12488, 12495, 12452, + 12484, 12497, 12540, 12475, 12531, 12488, 12497, 12540, 12484, 12496, 12540, 12524, + 12523, 12500, 12450, 12473, 12488, 12523, 12500, 12463, 12523, 12500, 12467, 12499, + 12523, 12501, 12449, 12521, 12483, 12489, 12501, 12451, 12540, 12488, 12502, 12483, + 12471, 12455, 12523, 12501, 12521, 12531, 12504, 12463, 12479, 12540, 12523, 12506, + 12477, 12506, 12491, 12498, 12504, 12523, 12484, 12506, 12531, 12473, 12506, 12540, + 12472, 12505, 12540, 12479, 12509, 12452, 12531, 12488, 12508, 12523, 12488, 12507, + 12531, 12509, 12531, 12489, 12507, 12540, 12523, 12507, 12540, 12531, 12510, 12452, + 12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, 12510, 12523, 12463, 12510, + 12531, 12471, 12519, 12531, 12511, 12463, 12525, 12531, 12511, 12522, 12511, 12522, + 12496, 12540, 12523, 12513, 12460, 12513, 12460, 12488, 12531, 12516, 12540, 12489, + 12516, 12540, 12523, 12518, 12450, 12531, 12522, 12483, 12488, 12523, 12522, 12521, + 12523, 12500, 12540, 12523, 12540, 12502, 12523, 12524, 12512, 12524, 12531, 12488, + 12466, 12531, 48, 28857, 49, 28857, 50, 28857, 51, 28857, 52, 28857, 53, 28857, + 54, 28857, 55, 28857, 56, 28857, 57, 28857, 49, 48, 28857, 49, 49, 28857, 49, 50, + 28857, 49, 51, 28857, 49, 52, 28857, 49, 53, 28857, 49, 54, 28857, 49, 55, 28857, + 49, 56, 28857, 49, 57, 28857, 50, 48, 28857, 50, 49, 28857, 50, 50, 28857, 50, 51, + 28857, 50, 52, 28857, 104, 112, 97, 100, 97, 97, 117, 98, 97, 114, 111, 118, 112, + 99, 100, 109, 100, 109, 50, 100, 109, 51, 105, 117, 24179, 25104, 26157, 21644, + 22823, 27491, 26126, 27835, 26666, 24335, 20250, 31038, 110, 97, 956, 97, 109, 97, + 107, 97, 107, 98, 109, 98, 103, 98, 99, 97, 108, 107, 99, 97, 108, 112, 102, 110, + 102, 956, 102, 956, 103, 109, 103, 107, 103, 104, 122, 107, 104, 122, 109, 104, + 122, 116, 104, 122, 956, 108, 109, 108, 100, 108, 102, 109, 110, 109, 956, 109, + 109, 109, 99, 109, 107, 109, 109, 109, 50, 99, 109, 50, 107, 109, 50, 109, 109, + 51, 99, 109, 51, 107, 109, 51, 109, 8725, 115, 109, 8725, 115, 50, 107, 112, 97, + 109, 112, 97, 103, 112, 97, 114, 97, 100, 114, 97, 100, 8725, 115, 114, 97, 100, + 8725, 115, 50, 112, 115, 110, 115, 956, 115, 109, 115, 112, 118, 110, 118, 956, + 118, 109, 118, 107, 118, 112, 119, 110, 119, 956, 119, 109, 119, 107, 119, 107, + 969, 109, 969, 98, 113, 99, 8725, 107, 103, 100, 98, 103, 121, 104, 97, 105, 110, + 107, 107, 107, 116, 108, 110, 108, 111, 103, 108, 120, 109, 105, 108, 109, 111, + 108, 112, 104, 112, 112, 109, 112, 114, 115, 118, 119, 98, 118, 8725, 109, 97, 8725, + 109, 49, 26085, 50, 26085, 51, 26085, 52, 26085, 53, 26085, 54, 26085, 55, 26085, + 56, 26085, 57, 26085, 49, 48, 26085, 49, 49, 26085, 49, 50, 26085, 49, 51, 26085, + 49, 52, 26085, 49, 53, 26085, 49, 54, 26085, 49, 55, 26085, 49, 56, 26085, 49, 57, + 26085, 50, 48, 26085, 50, 49, 26085, 50, 50, 26085, 50, 51, 26085, 50, 52, 26085, + 50, 53, 26085, 50, 54, 26085, 50, 55, 26085, 50, 56, 26085, 50, 57, 26085, 51, 48, + 26085, 51, 49, 26085, 103, 97, 108, 42561, 42563, 42565, 42567, 42569, 42573, 42575, + 42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, 42593, 42595, 42597, 42599, + 42601, 42603, 42605, 42625, 42627, 42629, 42631, 42633, 42635, 42637, 42639, 42641, + 42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, 42793, 42795, 42797, 42799, + 42803, 42805, 42807, 42809, 42811, 42813, 42815, 42817, 42819, 42821, 42823, 42825, + 42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, 42843, 42845, 42847, 42849, + 42851, 42853, 42855, 42857, 42859, 42861, 42863, 42874, 42876, 7545, 42879, 42881, + 42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, 42907, 42909, 42911, 42913, + 42915, 42917, 42919, 42921, 620, 670, 647, 43859, 42933, 42935, 42937, 42939, 42941, + 42943, 42945, 42947, 42900, 7566, 42952, 42954, 612, 42957, 42961, 42967, 42969, + 42971, 411, 42998, 43831, 43858, 653, 5024, 5025, 5026, 5027, 5028, 5029, 5030, + 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, + 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, + 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, + 5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, + 5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, + 5101, 5102, 5103, 35912, 26356, 36040, 28369, 20018, 21477, 22865, 21895, 22856, + 25078, 30313, 32645, 34367, 34746, 35064, 37007, 27138, 27931, 28889, 29662, 33853, + 37226, 39409, 20098, 21365, 27396, 29211, 34349, 40478, 23888, 28651, 34253, 35172, + 25289, 33240, 34847, 24266, 26391, 28010, 29436, 37070, 20358, 20919, 21214, 25796, + 27347, 29200, 30439, 34310, 34396, 36335, 38706, 39791, 40442, 30860, 31103, 32160, + 33737, 37636, 35542, 22751, 24324, 31840, 32894, 29282, 30922, 36034, 38647, 22744, + 23650, 27155, 28122, 28431, 32047, 32311, 38475, 21202, 32907, 20956, 20940, 31260, + 32190, 33777, 38517, 35712, 25295, 35582, 20025, 23527, 24594, 29575, 30064, 21271, + 30971, 20415, 24489, 19981, 27852, 25976, 32034, 21443, 22622, 30465, 33865, 35498, + 27578, 27784, 25342, 33509, 25504, 30053, 20142, 20841, 20937, 26753, 31975, 33391, + 35538, 37327, 21237, 21570, 24300, 26053, 28670, 31018, 38317, 39530, 40599, 40654, + 26310, 27511, 36706, 24180, 24976, 25088, 25754, 28451, 29001, 29833, 31178, 32244, + 32879, 36646, 34030, 36899, 37706, 21015, 21155, 21693, 28872, 35010, 24265, 24565, + 25467, 27566, 31806, 29557, 22265, 23994, 24604, 29618, 29801, 32666, 32838, 37428, + 38646, 38728, 38936, 20363, 31150, 37300, 38584, 24801, 20102, 20698, 23534, 23615, + 26009, 29134, 30274, 34044, 36988, 26248, 38446, 21129, 26491, 26611, 27969, 28316, + 29705, 30041, 30827, 32016, 39006, 25134, 38520, 20523, 23833, 28138, 36650, 24459, + 24900, 26647, 38534, 21033, 21519, 23653, 26131, 26446, 26792, 27877, 29702, 30178, + 32633, 35023, 35041, 38626, 21311, 28346, 21533, 29136, 29848, 34298, 38563, 40023, + 40607, 26519, 28107, 33256, 31520, 31890, 29376, 28825, 35672, 20160, 33590, 21050, + 20999, 24230, 25299, 31958, 23429, 27934, 26292, 36667, 38477, 24275, 20800, 21952, + 22618, 26228, 20958, 29482, 30410, 31036, 31070, 31077, 31119, 38742, 31934, 34322, + 35576, 36920, 37117, 39151, 39164, 39208, 40372, 37086, 38583, 20398, 20711, 20813, + 21193, 21220, 21329, 21917, 22022, 22120, 22592, 22696, 23652, 24724, 24936, 24974, + 25074, 25935, 26082, 26257, 26757, 28023, 28186, 28450, 29038, 29227, 29730, 30865, + 31049, 31048, 31056, 31062, 31117, 31118, 31296, 31361, 31680, 32265, 32321, 32626, + 32773, 33261, 33401, 33879, 35088, 35222, 35585, 35641, 36051, 36104, 36790, 38627, + 38911, 38971, 24693, 148206, 33304, 20006, 20917, 20840, 20352, 20805, 20864, 21191, + 21242, 21845, 21913, 21986, 22707, 22852, 22868, 23138, 23336, 24274, 24281, 24425, + 24493, 24792, 24910, 24840, 24928, 25140, 25540, 25628, 25682, 25942, 26395, 26454, + 28379, 28363, 28702, 30631, 29237, 29359, 29809, 29958, 30011, 30237, 30239, 30427, + 30452, 30538, 30528, 30924, 31409, 31867, 32091, 32574, 33618, 33775, 34681, 35137, + 35206, 35519, 35531, 35565, 35722, 36664, 36978, 37273, 37494, 38524, 38875, 38923, + 39698, 141386, 141380, 144341, 15261, 16408, 16441, 152137, 154832, 163539, 40771, + 40846, 102, 102, 102, 105, 102, 108, 102, 102, 108, 1396, 1398, 1396, 1381, 1396, + 1387, 1406, 1398, 1396, 1389, 1497, 1460, 1522, 1463, 1506, 1492, 1499, 1500, 1501, + 1512, 1514, 1513, 1473, 1513, 1474, 1513, 1468, 1473, 1513, 1468, 1474, 1488, 1463, + 1488, 1464, 1488, 1468, 1489, 1468, 1490, 1468, 1491, 1468, 1492, 1468, 1493, 1468, + 1494, 1468, 1496, 1468, 1497, 1468, 1498, 1468, 1499, 1468, 1500, 1468, 1502, 1468, + 1504, 1468, 1505, 1468, 1507, 1468, 1508, 1468, 1510, 1468, 1511, 1468, 1512, 1468, + 1514, 1468, 1493, 1465, 1489, 1471, 1499, 1471, 1508, 1471, 1488, 1500, 1649, 1659, + 1662, 1664, 1658, 1663, 1657, 1700, 1702, 1668, 1667, 1670, 1671, 1677, 1676, 1678, + 1672, 1688, 1681, 1705, 1711, 1715, 1713, 1722, 1723, 1728, 1729, 1726, 1746, 1747, + 1709, 1734, 1736, 1739, 1733, 1737, 1744, 1609, 1574, 1575, 1574, 1749, 1574, 1608, + 1574, 1735, 1574, 1734, 1574, 1736, 1574, 1744, 1574, 1609, 1740, 1574, 1580, 1574, + 1581, 1574, 1605, 1574, 1610, 1576, 1580, 1576, 1581, 1576, 1582, 1576, 1605, 1576, + 1609, 1576, 1610, 1578, 1580, 1578, 1581, 1578, 1582, 1578, 1605, 1578, 1609, 1578, + 1610, 1579, 1580, 1579, 1605, 1579, 1609, 1579, 1610, 1580, 1581, 1580, 1605, 1581, + 1605, 1582, 1580, 1582, 1581, 1582, 1605, 1587, 1580, 1587, 1581, 1587, 1582, 1587, + 1605, 1589, 1581, 1589, 1605, 1590, 1580, 1590, 1581, 1590, 1582, 1590, 1605, 1591, + 1581, 1591, 1605, 1592, 1605, 1593, 1580, 1593, 1605, 1594, 1580, 1594, 1605, 1601, + 1580, 1601, 1581, 1601, 1582, 1601, 1605, 1601, 1609, 1601, 1610, 1602, 1581, 1602, + 1605, 1602, 1609, 1602, 1610, 1603, 1575, 1603, 1580, 1603, 1581, 1603, 1582, 1603, + 1604, 1603, 1605, 1603, 1609, 1603, 1610, 1604, 1580, 1604, 1581, 1604, 1582, 1604, + 1605, 1604, 1609, 1604, 1610, 1605, 1580, 1605, 1605, 1605, 1609, 1605, 1610, 1606, + 1580, 1606, 1581, 1606, 1582, 1606, 1605, 1606, 1609, 1606, 1610, 1607, 1580, 1607, + 1605, 1607, 1609, 1607, 1610, 1610, 1581, 1610, 1582, 1610, 1609, 1584, 1648, 1585, + 1648, 1609, 1648, 32, 1612, 1617, 32, 1613, 1617, 32, 1614, 1617, 32, 1615, 1617, + 32, 1616, 1617, 32, 1617, 1648, 1574, 1585, 1574, 1586, 1574, 1606, 1576, 1585, + 1576, 1586, 1576, 1606, 1578, 1585, 1578, 1586, 1578, 1606, 1579, 1585, 1579, 1586, + 1579, 1606, 1605, 1575, 1606, 1585, 1606, 1586, 1606, 1606, 1610, 1585, 1610, 1586, + 1574, 1582, 1574, 1607, 1576, 1607, 1578, 1607, 1589, 1582, 1604, 1607, 1606, 1607, + 1607, 1648, 1579, 1607, 1587, 1607, 1588, 1605, 1588, 1607, 1600, 1614, 1617, 1600, + 1615, 1617, 1600, 1616, 1617, 1591, 1609, 1591, 1610, 1593, 1609, 1593, 1610, 1594, + 1609, 1594, 1610, 1587, 1609, 1587, 1610, 1588, 1609, 1588, 1610, 1581, 1609, 1580, + 1609, 1580, 1610, 1582, 1609, 1589, 1609, 1589, 1610, 1590, 1609, 1590, 1610, 1588, + 1580, 1588, 1581, 1588, 1582, 1588, 1585, 1587, 1585, 1589, 1585, 1590, 1585, 1575, + 1611, 1578, 1580, 1605, 1578, 1581, 1580, 1578, 1581, 1605, 1578, 1582, 1605, 1578, + 1605, 1580, 1578, 1605, 1581, 1578, 1605, 1582, 1581, 1605, 1610, 1581, 1605, 1609, + 1587, 1581, 1580, 1587, 1580, 1581, 1587, 1580, 1609, 1587, 1605, 1581, 1587, 1605, + 1580, 1587, 1605, 1605, 1589, 1581, 1581, 1589, 1605, 1605, 1588, 1581, 1605, 1588, + 1580, 1610, 1588, 1605, 1582, 1588, 1605, 1605, 1590, 1581, 1609, 1590, 1582, 1605, + 1591, 1605, 1581, 1591, 1605, 1605, 1591, 1605, 1610, 1593, 1580, 1605, 1593, 1605, + 1605, 1593, 1605, 1609, 1594, 1605, 1605, 1594, 1605, 1610, 1594, 1605, 1609, 1601, + 1582, 1605, 1602, 1605, 1581, 1602, 1605, 1605, 1604, 1581, 1605, 1604, 1581, 1610, + 1604, 1581, 1609, 1604, 1580, 1580, 1604, 1582, 1605, 1604, 1605, 1581, 1605, 1581, + 1580, 1605, 1581, 1610, 1605, 1580, 1581, 1605, 1582, 1605, 1605, 1580, 1582, 1607, + 1605, 1580, 1607, 1605, 1605, 1606, 1581, 1605, 1606, 1581, 1609, 1606, 1580, 1605, + 1606, 1580, 1609, 1606, 1605, 1610, 1606, 1605, 1609, 1610, 1605, 1605, 1576, 1582, + 1610, 1578, 1580, 1610, 1578, 1580, 1609, 1578, 1582, 1610, 1578, 1582, 1609, 1578, + 1605, 1610, 1578, 1605, 1609, 1580, 1605, 1610, 1580, 1581, 1609, 1580, 1605, 1609, + 1587, 1582, 1609, 1589, 1581, 1610, 1588, 1581, 1610, 1590, 1581, 1610, 1604, 1580, + 1610, 1604, 1605, 1610, 1610, 1580, 1610, 1610, 1605, 1610, 1605, 1605, 1610, 1602, + 1605, 1610, 1606, 1581, 1610, 1593, 1605, 1610, 1603, 1605, 1610, 1606, 1580, 1581, + 1605, 1582, 1610, 1604, 1580, 1605, 1603, 1605, 1605, 1580, 1581, 1610, 1581, 1580, + 1610, 1605, 1580, 1610, 1601, 1605, 1610, 1576, 1581, 1610, 1587, 1582, 1610, 1606, + 1580, 1610, 1589, 1604, 1746, 1602, 1604, 1746, 1575, 1604, 1604, 1607, 1575, 1603, + 1576, 1585, 1605, 1581, 1605, 1583, 1589, 1604, 1593, 1605, 1585, 1587, 1608, 1604, + 1593, 1604, 1610, 1607, 1608, 1587, 1604, 1605, 1589, 1604, 1609, 1589, 1604, 1609, + 32, 1575, 1604, 1604, 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605, + 1580, 1604, 32, 1580, 1604, 1575, 1604, 1607, 1585, 1740, 1575, 1604, 44, 12289, + 12310, 12311, 8212, 8211, 95, 123, 125, 12308, 12309, 12304, 12305, 12298, 12299, + 12300, 12301, 12302, 12303, 91, 93, 35, 38, 42, 45, 60, 62, 92, 36, 37, 64, 32, + 1611, 1600, 1611, 1600, 1617, 32, 1618, 1600, 1618, 1569, 1570, 1571, 1572, 1573, + 1577, 1604, 1570, 1604, 1571, 1604, 1573, 34, 39, 94, 124, 126, 10629, 10630, 12539, + 12453, 12515, 162, 163, 172, 166, 165, 8361, 9474, 8592, 8593, 8594, 8595, 9632, + 9675, 66600, 66601, 66602, 66603, 66604, 66605, 66606, 66607, 66608, 66609, 66610, + 66611, 66612, 66613, 66614, 66615, 66616, 66617, 66618, 66619, 66620, 66621, 66622, + 66623, 66624, 66625, 66626, 66627, 66628, 66629, 66630, 66631, 66632, 66633, 66634, + 66635, 66636, 66637, 66638, 66639, 66776, 66777, 66778, 66779, 66780, 66781, 66782, + 66783, 66784, 66785, 66786, 66787, 66788, 66789, 66790, 66791, 66792, 66793, 66794, + 66795, 66796, 66797, 66798, 66799, 66800, 66801, 66802, 66803, 66804, 66805, 66806, + 66807, 66808, 66809, 66810, 66811, 66967, 66968, 66969, 66970, 66971, 66972, 66973, + 66974, 66975, 66976, 66977, 66979, 66980, 66981, 66982, 66983, 66984, 66985, 66986, + 66987, 66988, 66989, 66990, 66991, 66992, 66993, 66995, 66996, 66997, 66998, 66999, + 67000, 67001, 67003, 67004, 720, 721, 665, 675, 43878, 677, 676, 7569, 600, 606, + 681, 610, 667, 668, 615, 644, 682, 683, 122628, 42894, 622, 122629, 654, 122630, + 630, 631, 634, 122632, 638, 680, 678, 43879, 679, 11377, 655, 673, 674, 664, 448, + 449, 450, 122634, 122654, 68800, 68801, 68802, 68803, 68804, 68805, 68806, 68807, + 68808, 68809, 68810, 68811, 68812, 68813, 68814, 68815, 68816, 68817, 68818, 68819, + 68820, 68821, 68822, 68823, 68824, 68825, 68826, 68827, 68828, 68829, 68830, 68831, + 68832, 68833, 68834, 68835, 68836, 68837, 68838, 68839, 68840, 68841, 68842, 68843, + 68844, 68845, 68846, 68847, 68848, 68849, 68850, 68976, 68977, 68978, 68979, 68980, + 68981, 68982, 68983, 68984, 68985, 68986, 68987, 68988, 68989, 68990, 68991, 68992, + 68993, 68994, 68995, 68996, 68997, 71872, 71873, 71874, 71875, 71876, 71877, 71878, + 71879, 71880, 71881, 71882, 71883, 71884, 71885, 71886, 71887, 71888, 71889, 71890, + 71891, 71892, 71893, 71894, 71895, 71896, 71897, 71898, 71899, 71900, 71901, 71902, + 71903, 93792, 93793, 93794, 93795, 93796, 93797, 93798, 93799, 93800, 93801, 93802, + 93803, 93804, 93805, 93806, 93807, 93808, 93809, 93810, 93811, 93812, 93813, 93814, + 93815, 93816, 93817, 93818, 93819, 93820, 93821, 93822, 93823, 119127, 119141, 119128, + 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128, 119141, 119152, + 119128, 119141, 119153, 119128, 119141, 119154, 119225, 119141, 119226, 119141, + 119225, 119141, 119150, 119226, 119141, 119150, 119225, 119141, 119151, 119226, + 119141, 119151, 305, 567, 8711, 8706, 125218, 125219, 125220, 125221, 125222, 125223, + 125224, 125225, 125226, 125227, 125228, 125229, 125230, 125231, 125232, 125233, + 125234, 125235, 125236, 125237, 125238, 125239, 125240, 125241, 125242, 125243, + 125244, 125245, 125246, 125247, 125248, 125249, 125250, 125251, 1646, 1697, 1647, + 48, 44, 49, 44, 50, 44, 51, 44, 52, 44, 53, 44, 54, 44, 55, 44, 56, 44, 57, 44, + 12308, 115, 12309, 119, 122, 104, 118, 115, 100, 115, 115, 112, 112, 118, 119, 99, + 109, 114, 100, 106, 12411, 12363, 12467, 12467, 23383, 21452, 22810, 35299, 20132, + 26144, 28961, 21069, 24460, 20877, 26032, 21021, 32066, 36009, 22768, 21561, 28436, + 25237, 25429, 36938, 25351, 25171, 31105, 31354, 21512, 28288, 30003, 21106, 21942, + 37197, 12308, 26412, 12309, 12308, 19977, 12309, 12308, 20108, 12309, 12308, 23433, + 12309, 12308, 28857, 12309, 12308, 25171, 12309, 12308, 30423, 12309, 12308, 21213, + 12309, 12308, 25943, 12309, 24471, 21487, 20029, 20024, 20033, 131362, 20320, 20411, + 20482, 20602, 20633, 20687, 13470, 132666, 20820, 20836, 20855, 132380, 13497, 20839, + 132427, 20887, 20900, 20172, 20908, 168415, 20995, 13535, 21051, 21062, 21111, 13589, + 21253, 21254, 21321, 21338, 21363, 21373, 21375, 133676, 28784, 21450, 21471, 133987, + 21483, 21489, 21510, 21662, 21560, 21576, 21608, 21666, 21750, 21776, 21843, 21859, + 21892, 21931, 21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, 22516, 22541, + 22411, 22578, 22577, 22700, 136420, 22770, 22775, 22790, 22818, 22882, 136872, 136938, + 23020, 23067, 23079, 23000, 23142, 14062, 14076, 23304, 23358, 137672, 23491, 23512, + 23539, 138008, 23551, 23558, 24403, 14209, 23648, 23744, 23693, 138724, 23875, 138726, + 23918, 23915, 23932, 24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434, 139651, + 14460, 24240, 24243, 24246, 172946, 140081, 33281, 24354, 14535, 144056, 156122, + 24418, 24427, 14563, 24474, 24525, 24535, 24569, 24705, 14650, 14620, 141012, 24775, + 24904, 24908, 24954, 25010, 24996, 25007, 25054, 25115, 25181, 25265, 25300, 25424, + 142092, 25405, 25340, 25448, 25475, 25572, 142321, 25634, 25541, 25513, 14894, 25705, + 25726, 25757, 25719, 14956, 25964, 143370, 26083, 26360, 26185, 15129, 15112, 15076, + 20882, 20885, 26368, 26268, 32941, 17369, 26401, 26462, 26451, 144323, 15177, 26618, + 26501, 26706, 144493, 26766, 26655, 26900, 26946, 27043, 27114, 27304, 145059, 27355, + 15384, 27425, 145575, 27476, 15438, 27506, 27551, 27579, 146061, 138507, 146170, + 27726, 146620, 27839, 27853, 27751, 27926, 27966, 28009, 28024, 28037, 146718, 27956, + 28207, 28270, 15667, 28359, 147153, 28153, 28526, 147294, 147342, 28614, 28729, + 28699, 15766, 28746, 28797, 28791, 28845, 132389, 28997, 148067, 29084, 148395, + 29224, 29264, 149000, 29312, 29333, 149301, 149524, 29562, 29579, 16044, 29605, + 16056, 29767, 29788, 29829, 29898, 16155, 29988, 150582, 30014, 150674, 139679, + 30224, 151457, 151480, 151620, 16380, 16392, 151795, 151794, 151833, 151859, 30494, + 30495, 30603, 16454, 16534, 152605, 30798, 16611, 153126, 153242, 153285, 31211, + 16687, 31306, 31311, 153980, 154279, 31470, 16898, 154539, 31686, 31689, 16935, + 154752, 31954, 17056, 31976, 31971, 32000, 155526, 32099, 17153, 32199, 32258, 32325, + 17204, 156200, 156231, 17241, 156377, 32634, 156478, 32661, 32762, 156890, 156963, + 32864, 157096, 32880, 144223, 17365, 32946, 33027, 17419, 33086, 23221, 157607, + 157621, 144275, 144284, 33284, 36766, 17515, 33425, 33419, 33437, 21171, 33457, + 33459, 33469, 33510, 158524, 33565, 33635, 33709, 33571, 33725, 33767, 33619, 33738, + 33740, 33756, 158774, 159083, 158933, 17707, 34033, 34035, 34070, 160714, 34148, + 159532, 17757, 17761, 159665, 159954, 17771, 34384, 34407, 34409, 34473, 34440, + 34574, 34530, 34600, 34667, 34694, 17879, 34785, 34817, 17913, 34912, 161383, 35031, + 35038, 17973, 35066, 13499, 161966, 162150, 18110, 18119, 35488, 162984, 36011, + 36033, 36123, 36215, 163631, 133124, 36299, 36284, 36336, 133342, 36564, 165330, + 165357, 37012, 37105, 37137, 165678, 37147, 37432, 37591, 37592, 37500, 37881, 37909, + 166906, 38283, 18837, 38327, 167287, 18918, 38595, 23986, 38691, 168261, 168474, + 19054, 19062, 38880, 168970, 19122, 169110, 38953, 169398, 39138, 19251, 39209, + 39335, 39362, 39422, 19406, 170800, 40000, 40189, 19662, 19693, 40295, 172238, 19704, + 172293, 172558, 172689, 19798, 40702, 40709, 40719, 40726, 173568, }; -const uint32_t table[8000][2] = +const uint32_t table[8150][2] = { {0, 1}, {65, 16777219}, {66, 16777475}, {67, 16777731}, {68, 16777987}, {69, 16778243}, {70, 16778499}, {71, 16778755}, @@ -884,73 +891,73 @@ const uint32_t table[8000][2] = {1204, 16884483}, {1205, 1}, {1206, 16884739}, {1207, 1}, {1208, 16884995}, {1209, 1}, {1210, 16885251}, {1211, 1}, {1212, 16885507}, {1213, 1}, {1214, 16885763}, {1215, 1}, - {1216, 2}, {1217, 16886019}, {1218, 1}, {1219, 16886275}, - {1220, 1}, {1221, 16886531}, {1222, 1}, {1223, 16886787}, - {1224, 1}, {1225, 16887043}, {1226, 1}, {1227, 16887299}, - {1228, 1}, {1229, 16887555}, {1230, 1}, {1232, 16887811}, - {1233, 1}, {1234, 16888067}, {1235, 1}, {1236, 16888323}, - {1237, 1}, {1238, 16888579}, {1239, 1}, {1240, 16888835}, - {1241, 1}, {1242, 16889091}, {1243, 1}, {1244, 16889347}, - {1245, 1}, {1246, 16889603}, {1247, 1}, {1248, 16889859}, - {1249, 1}, {1250, 16890115}, {1251, 1}, {1252, 16890371}, - {1253, 1}, {1254, 16890627}, {1255, 1}, {1256, 16890883}, - {1257, 1}, {1258, 16891139}, {1259, 1}, {1260, 16891395}, - {1261, 1}, {1262, 16891651}, {1263, 1}, {1264, 16891907}, - {1265, 1}, {1266, 16892163}, {1267, 1}, {1268, 16892419}, - {1269, 1}, {1270, 16892675}, {1271, 1}, {1272, 16892931}, - {1273, 1}, {1274, 16893187}, {1275, 1}, {1276, 16893443}, - {1277, 1}, {1278, 16893699}, {1279, 1}, {1280, 16893955}, - {1281, 1}, {1282, 16894211}, {1283, 1}, {1284, 16894467}, - {1285, 1}, {1286, 16894723}, {1287, 1}, {1288, 16894979}, - {1289, 1}, {1290, 16895235}, {1291, 1}, {1292, 16895491}, - {1293, 1}, {1294, 16895747}, {1295, 1}, {1296, 16896003}, - {1297, 1}, {1298, 16896259}, {1299, 1}, {1300, 16896515}, - {1301, 1}, {1302, 16896771}, {1303, 1}, {1304, 16897027}, - {1305, 1}, {1306, 16897283}, {1307, 1}, {1308, 16897539}, - {1309, 1}, {1310, 16897795}, {1311, 1}, {1312, 16898051}, - {1313, 1}, {1314, 16898307}, {1315, 1}, {1316, 16898563}, - {1317, 1}, {1318, 16898819}, {1319, 1}, {1320, 16899075}, - {1321, 1}, {1322, 16899331}, {1323, 1}, {1324, 16899587}, - {1325, 1}, {1326, 16899843}, {1327, 1}, {1328, 2}, - {1329, 16900099}, {1330, 16900355}, {1331, 16900611}, {1332, 16900867}, - {1333, 16901123}, {1334, 16901379}, {1335, 16901635}, {1336, 16901891}, - {1337, 16902147}, {1338, 16902403}, {1339, 16902659}, {1340, 16902915}, - {1341, 16903171}, {1342, 16903427}, {1343, 16903683}, {1344, 16903939}, - {1345, 16904195}, {1346, 16904451}, {1347, 16904707}, {1348, 16904963}, - {1349, 16905219}, {1350, 16905475}, {1351, 16905731}, {1352, 16905987}, - {1353, 16906243}, {1354, 16906499}, {1355, 16906755}, {1356, 16907011}, - {1357, 16907267}, {1358, 16907523}, {1359, 16907779}, {1360, 16908035}, - {1361, 16908291}, {1362, 16908547}, {1363, 16908803}, {1364, 16909059}, - {1365, 16909315}, {1366, 16909571}, {1367, 2}, {1369, 1}, - {1415, 33687043}, {1416, 1}, {1419, 2}, {1421, 1}, + {1216, 16886019}, {1217, 16886275}, {1218, 1}, {1219, 16886531}, + {1220, 1}, {1221, 16886787}, {1222, 1}, {1223, 16887043}, + {1224, 1}, {1225, 16887299}, {1226, 1}, {1227, 16887555}, + {1228, 1}, {1229, 16887811}, {1230, 1}, {1232, 16888067}, + {1233, 1}, {1234, 16888323}, {1235, 1}, {1236, 16888579}, + {1237, 1}, {1238, 16888835}, {1239, 1}, {1240, 16889091}, + {1241, 1}, {1242, 16889347}, {1243, 1}, {1244, 16889603}, + {1245, 1}, {1246, 16889859}, {1247, 1}, {1248, 16890115}, + {1249, 1}, {1250, 16890371}, {1251, 1}, {1252, 16890627}, + {1253, 1}, {1254, 16890883}, {1255, 1}, {1256, 16891139}, + {1257, 1}, {1258, 16891395}, {1259, 1}, {1260, 16891651}, + {1261, 1}, {1262, 16891907}, {1263, 1}, {1264, 16892163}, + {1265, 1}, {1266, 16892419}, {1267, 1}, {1268, 16892675}, + {1269, 1}, {1270, 16892931}, {1271, 1}, {1272, 16893187}, + {1273, 1}, {1274, 16893443}, {1275, 1}, {1276, 16893699}, + {1277, 1}, {1278, 16893955}, {1279, 1}, {1280, 16894211}, + {1281, 1}, {1282, 16894467}, {1283, 1}, {1284, 16894723}, + {1285, 1}, {1286, 16894979}, {1287, 1}, {1288, 16895235}, + {1289, 1}, {1290, 16895491}, {1291, 1}, {1292, 16895747}, + {1293, 1}, {1294, 16896003}, {1295, 1}, {1296, 16896259}, + {1297, 1}, {1298, 16896515}, {1299, 1}, {1300, 16896771}, + {1301, 1}, {1302, 16897027}, {1303, 1}, {1304, 16897283}, + {1305, 1}, {1306, 16897539}, {1307, 1}, {1308, 16897795}, + {1309, 1}, {1310, 16898051}, {1311, 1}, {1312, 16898307}, + {1313, 1}, {1314, 16898563}, {1315, 1}, {1316, 16898819}, + {1317, 1}, {1318, 16899075}, {1319, 1}, {1320, 16899331}, + {1321, 1}, {1322, 16899587}, {1323, 1}, {1324, 16899843}, + {1325, 1}, {1326, 16900099}, {1327, 1}, {1328, 2}, + {1329, 16900355}, {1330, 16900611}, {1331, 16900867}, {1332, 16901123}, + {1333, 16901379}, {1334, 16901635}, {1335, 16901891}, {1336, 16902147}, + {1337, 16902403}, {1338, 16902659}, {1339, 16902915}, {1340, 16903171}, + {1341, 16903427}, {1342, 16903683}, {1343, 16903939}, {1344, 16904195}, + {1345, 16904451}, {1346, 16904707}, {1347, 16904963}, {1348, 16905219}, + {1349, 16905475}, {1350, 16905731}, {1351, 16905987}, {1352, 16906243}, + {1353, 16906499}, {1354, 16906755}, {1355, 16907011}, {1356, 16907267}, + {1357, 16907523}, {1358, 16907779}, {1359, 16908035}, {1360, 16908291}, + {1361, 16908547}, {1362, 16908803}, {1363, 16909059}, {1364, 16909315}, + {1365, 16909571}, {1366, 16909827}, {1367, 2}, {1369, 1}, + {1415, 33687299}, {1416, 1}, {1419, 2}, {1421, 1}, {1424, 2}, {1425, 1}, {1480, 2}, {1488, 1}, {1515, 2}, {1519, 1}, {1525, 2}, {1542, 1}, - {1564, 2}, {1565, 1}, {1653, 33687555}, {1654, 33688067}, - {1655, 33688579}, {1656, 33689091}, {1657, 1}, {1757, 2}, + {1564, 2}, {1565, 1}, {1653, 33687811}, {1654, 33688323}, + {1655, 33688835}, {1656, 33689347}, {1657, 1}, {1757, 2}, {1758, 1}, {1806, 2}, {1808, 1}, {1867, 2}, {1869, 1}, {1970, 2}, {1984, 1}, {2043, 2}, {2045, 1}, {2094, 2}, {2096, 1}, {2111, 2}, {2112, 1}, {2140, 2}, {2142, 1}, {2143, 2}, {2144, 1}, {2155, 2}, {2160, 1}, {2191, 2}, - {2200, 1}, {2274, 2}, {2275, 1}, {2392, 33689603}, - {2393, 33690115}, {2394, 33690627}, {2395, 33691139}, {2396, 33691651}, - {2397, 33692163}, {2398, 33692675}, {2399, 33693187}, {2400, 1}, + {2199, 1}, {2274, 2}, {2275, 1}, {2392, 33689859}, + {2393, 33690371}, {2394, 33690883}, {2395, 33691395}, {2396, 33691907}, + {2397, 33692419}, {2398, 33692931}, {2399, 33693443}, {2400, 1}, {2436, 2}, {2437, 1}, {2445, 2}, {2447, 1}, {2449, 2}, {2451, 1}, {2473, 2}, {2474, 1}, {2481, 2}, {2482, 1}, {2483, 2}, {2486, 1}, {2490, 2}, {2492, 1}, {2501, 2}, {2503, 1}, {2505, 2}, {2507, 1}, {2511, 2}, {2519, 1}, - {2520, 2}, {2524, 33693699}, {2525, 33694211}, {2526, 2}, - {2527, 33694723}, {2528, 1}, {2532, 2}, {2534, 1}, + {2520, 2}, {2524, 33693955}, {2525, 33694467}, {2526, 2}, + {2527, 33694979}, {2528, 1}, {2532, 2}, {2534, 1}, {2559, 2}, {2561, 1}, {2564, 2}, {2565, 1}, {2571, 2}, {2575, 1}, {2577, 2}, {2579, 1}, {2601, 2}, {2602, 1}, {2609, 2}, {2610, 1}, - {2611, 33695235}, {2612, 2}, {2613, 1}, {2614, 33695747}, + {2611, 33695491}, {2612, 2}, {2613, 1}, {2614, 33696003}, {2615, 2}, {2616, 1}, {2618, 2}, {2620, 1}, {2621, 2}, {2622, 1}, {2627, 2}, {2631, 1}, {2633, 2}, {2635, 1}, {2638, 2}, {2641, 1}, - {2642, 2}, {2649, 33696259}, {2650, 33696771}, {2651, 33697283}, - {2652, 1}, {2653, 2}, {2654, 33697795}, {2655, 2}, + {2642, 2}, {2649, 33696515}, {2650, 33697027}, {2651, 33697539}, + {2652, 1}, {2653, 2}, {2654, 33698051}, {2655, 2}, {2662, 1}, {2679, 2}, {2689, 1}, {2692, 2}, {2693, 1}, {2702, 2}, {2703, 1}, {2706, 2}, {2707, 1}, {2729, 2}, {2730, 1}, {2737, 2}, @@ -964,7 +971,7 @@ const uint32_t table[8000][2] = {2866, 1}, {2868, 2}, {2869, 1}, {2874, 2}, {2876, 1}, {2885, 2}, {2887, 1}, {2889, 2}, {2891, 1}, {2894, 2}, {2901, 1}, {2904, 2}, - {2908, 33698307}, {2909, 33698819}, {2910, 2}, {2911, 1}, + {2908, 33698563}, {2909, 33699075}, {2910, 2}, {2911, 1}, {2916, 2}, {2918, 1}, {2936, 2}, {2946, 1}, {2948, 2}, {2949, 1}, {2955, 2}, {2958, 1}, {2961, 2}, {2962, 1}, {2966, 2}, {2969, 1}, @@ -996,1735 +1003,1772 @@ const uint32_t table[8000][2] = {3531, 2}, {3535, 1}, {3541, 2}, {3542, 1}, {3543, 2}, {3544, 1}, {3552, 2}, {3558, 1}, {3568, 2}, {3570, 1}, {3573, 2}, {3585, 1}, - {3635, 33699331}, {3636, 1}, {3643, 2}, {3647, 1}, + {3635, 33699587}, {3636, 1}, {3643, 2}, {3647, 1}, {3676, 2}, {3713, 1}, {3715, 2}, {3716, 1}, {3717, 2}, {3718, 1}, {3723, 2}, {3724, 1}, {3748, 2}, {3749, 1}, {3750, 2}, {3751, 1}, - {3763, 33699843}, {3764, 1}, {3774, 2}, {3776, 1}, + {3763, 33700099}, {3764, 1}, {3774, 2}, {3776, 1}, {3781, 2}, {3782, 1}, {3783, 2}, {3784, 1}, - {3791, 2}, {3792, 1}, {3802, 2}, {3804, 33700355}, - {3805, 33700867}, {3806, 1}, {3808, 2}, {3840, 1}, - {3852, 16924163}, {3853, 1}, {3907, 33701635}, {3908, 1}, - {3912, 2}, {3913, 1}, {3917, 33702147}, {3918, 1}, - {3922, 33702659}, {3923, 1}, {3927, 33703171}, {3928, 1}, - {3932, 33703683}, {3933, 1}, {3945, 33704195}, {3946, 1}, - {3949, 2}, {3953, 1}, {3955, 33704707}, {3956, 1}, - {3957, 33705219}, {3958, 33705731}, {3959, 50483459}, {3960, 33707011}, - {3961, 50484739}, {3962, 1}, {3969, 33706499}, {3970, 1}, - {3987, 33708291}, {3988, 1}, {3992, 2}, {3993, 1}, - {3997, 33708803}, {3998, 1}, {4002, 33709315}, {4003, 1}, - {4007, 33709827}, {4008, 1}, {4012, 33710339}, {4013, 1}, - {4025, 33710851}, {4026, 1}, {4029, 2}, {4030, 1}, + {3791, 2}, {3792, 1}, {3802, 2}, {3804, 33700611}, + {3805, 33701123}, {3806, 1}, {3808, 2}, {3840, 1}, + {3852, 16924419}, {3853, 1}, {3907, 33701891}, {3908, 1}, + {3912, 2}, {3913, 1}, {3917, 33702403}, {3918, 1}, + {3922, 33702915}, {3923, 1}, {3927, 33703427}, {3928, 1}, + {3932, 33703939}, {3933, 1}, {3945, 33704451}, {3946, 1}, + {3949, 2}, {3953, 1}, {3955, 33704963}, {3956, 1}, + {3957, 33705475}, {3958, 33705987}, {3959, 50483715}, {3960, 33707267}, + {3961, 50484995}, {3962, 1}, {3969, 33706755}, {3970, 1}, + {3987, 33708547}, {3988, 1}, {3992, 2}, {3993, 1}, + {3997, 33709059}, {3998, 1}, {4002, 33709571}, {4003, 1}, + {4007, 33710083}, {4008, 1}, {4012, 33710595}, {4013, 1}, + {4025, 33711107}, {4026, 1}, {4029, 2}, {4030, 1}, {4045, 2}, {4046, 1}, {4059, 2}, {4096, 1}, - {4256, 2}, {4295, 16934147}, {4296, 2}, {4301, 16934403}, - {4302, 2}, {4304, 1}, {4348, 16934659}, {4349, 1}, - {4447, 2}, {4449, 1}, {4681, 2}, {4682, 1}, - {4686, 2}, {4688, 1}, {4695, 2}, {4696, 1}, - {4697, 2}, {4698, 1}, {4702, 2}, {4704, 1}, - {4745, 2}, {4746, 1}, {4750, 2}, {4752, 1}, - {4785, 2}, {4786, 1}, {4790, 2}, {4792, 1}, - {4799, 2}, {4800, 1}, {4801, 2}, {4802, 1}, - {4806, 2}, {4808, 1}, {4823, 2}, {4824, 1}, - {4881, 2}, {4882, 1}, {4886, 2}, {4888, 1}, - {4955, 2}, {4957, 1}, {4989, 2}, {4992, 1}, - {5018, 2}, {5024, 1}, {5110, 2}, {5112, 16934915}, - {5113, 16935171}, {5114, 16935427}, {5115, 16935683}, {5116, 16935939}, - {5117, 16936195}, {5118, 2}, {5120, 1}, {5760, 2}, - {5761, 1}, {5789, 2}, {5792, 1}, {5881, 2}, - {5888, 1}, {5910, 2}, {5919, 1}, {5943, 2}, - {5952, 1}, {5972, 2}, {5984, 1}, {5997, 2}, - {5998, 1}, {6001, 2}, {6002, 1}, {6004, 2}, - {6016, 1}, {6068, 2}, {6070, 1}, {6110, 2}, - {6112, 1}, {6122, 2}, {6128, 1}, {6138, 2}, - {6144, 1}, {6150, 2}, {6151, 1}, {6155, 0}, - {6158, 2}, {6159, 0}, {6160, 1}, {6170, 2}, - {6176, 1}, {6265, 2}, {6272, 1}, {6315, 2}, - {6320, 1}, {6390, 2}, {6400, 1}, {6431, 2}, - {6432, 1}, {6444, 2}, {6448, 1}, {6460, 2}, - {6464, 1}, {6465, 2}, {6468, 1}, {6510, 2}, - {6512, 1}, {6517, 2}, {6528, 1}, {6572, 2}, - {6576, 1}, {6602, 2}, {6608, 1}, {6619, 2}, - {6622, 1}, {6684, 2}, {6686, 1}, {6751, 2}, - {6752, 1}, {6781, 2}, {6783, 1}, {6794, 2}, - {6800, 1}, {6810, 2}, {6816, 1}, {6830, 2}, - {6832, 1}, {6863, 2}, {6912, 1}, {6989, 2}, - {6992, 1}, {7039, 2}, {7040, 1}, {7156, 2}, + {4256, 16934403}, {4257, 16934659}, {4258, 16934915}, {4259, 16935171}, + {4260, 16935427}, {4261, 16935683}, {4262, 16935939}, {4263, 16936195}, + {4264, 16936451}, {4265, 16936707}, {4266, 16936963}, {4267, 16937219}, + {4268, 16937475}, {4269, 16937731}, {4270, 16937987}, {4271, 16938243}, + {4272, 16938499}, {4273, 16938755}, {4274, 16939011}, {4275, 16939267}, + {4276, 16939523}, {4277, 16939779}, {4278, 16940035}, {4279, 16940291}, + {4280, 16940547}, {4281, 16940803}, {4282, 16941059}, {4283, 16941315}, + {4284, 16941571}, {4285, 16941827}, {4286, 16942083}, {4287, 16942339}, + {4288, 16942595}, {4289, 16942851}, {4290, 16943107}, {4291, 16943363}, + {4292, 16943619}, {4293, 16943875}, {4294, 2}, {4295, 16944131}, + {4296, 2}, {4301, 16944387}, {4302, 2}, {4304, 1}, + {4348, 16944643}, {4349, 1}, {4447, 0}, {4449, 1}, + {4681, 2}, {4682, 1}, {4686, 2}, {4688, 1}, + {4695, 2}, {4696, 1}, {4697, 2}, {4698, 1}, + {4702, 2}, {4704, 1}, {4745, 2}, {4746, 1}, + {4750, 2}, {4752, 1}, {4785, 2}, {4786, 1}, + {4790, 2}, {4792, 1}, {4799, 2}, {4800, 1}, + {4801, 2}, {4802, 1}, {4806, 2}, {4808, 1}, + {4823, 2}, {4824, 1}, {4881, 2}, {4882, 1}, + {4886, 2}, {4888, 1}, {4955, 2}, {4957, 1}, + {4989, 2}, {4992, 1}, {5018, 2}, {5024, 1}, + {5110, 2}, {5112, 16944899}, {5113, 16945155}, {5114, 16945411}, + {5115, 16945667}, {5116, 16945923}, {5117, 16946179}, {5118, 2}, + {5120, 1}, {5760, 2}, {5761, 1}, {5789, 2}, + {5792, 1}, {5881, 2}, {5888, 1}, {5910, 2}, + {5919, 1}, {5943, 2}, {5952, 1}, {5972, 2}, + {5984, 1}, {5997, 2}, {5998, 1}, {6001, 2}, + {6002, 1}, {6004, 2}, {6016, 1}, {6068, 0}, + {6070, 1}, {6110, 2}, {6112, 1}, {6122, 2}, + {6128, 1}, {6138, 2}, {6144, 1}, {6155, 0}, + {6160, 1}, {6170, 2}, {6176, 1}, {6265, 2}, + {6272, 1}, {6315, 2}, {6320, 1}, {6390, 2}, + {6400, 1}, {6431, 2}, {6432, 1}, {6444, 2}, + {6448, 1}, {6460, 2}, {6464, 1}, {6465, 2}, + {6468, 1}, {6510, 2}, {6512, 1}, {6517, 2}, + {6528, 1}, {6572, 2}, {6576, 1}, {6602, 2}, + {6608, 1}, {6619, 2}, {6622, 1}, {6684, 2}, + {6686, 1}, {6751, 2}, {6752, 1}, {6781, 2}, + {6783, 1}, {6794, 2}, {6800, 1}, {6810, 2}, + {6816, 1}, {6830, 2}, {6832, 1}, {6863, 2}, + {6912, 1}, {6989, 2}, {6990, 1}, {7156, 2}, {7164, 1}, {7224, 2}, {7227, 1}, {7242, 2}, {7245, 1}, {7296, 16867075}, {7297, 16867587}, {7298, 16870147}, {7299, 16870915}, {7300, 16871171}, {7302, 16873219}, {7303, 16875011}, - {7304, 16936451}, {7305, 2}, {7312, 16936707}, {7313, 16936963}, - {7314, 16937219}, {7315, 16937475}, {7316, 16937731}, {7317, 16937987}, - {7318, 16938243}, {7319, 16938499}, {7320, 16938755}, {7321, 16939011}, - {7322, 16939267}, {7323, 16939523}, {7324, 16934659}, {7325, 16939779}, - {7326, 16940035}, {7327, 16940291}, {7328, 16940547}, {7329, 16940803}, - {7330, 16941059}, {7331, 16941315}, {7332, 16941571}, {7333, 16941827}, - {7334, 16942083}, {7335, 16942339}, {7336, 16942595}, {7337, 16942851}, - {7338, 16943107}, {7339, 16943363}, {7340, 16943619}, {7341, 16943875}, - {7342, 16944131}, {7343, 16944387}, {7344, 16944643}, {7345, 16944899}, - {7346, 16945155}, {7347, 16945411}, {7348, 16945667}, {7349, 16945923}, - {7350, 16946179}, {7351, 16946435}, {7352, 16946691}, {7353, 16946947}, - {7354, 16947203}, {7355, 2}, {7357, 16947459}, {7358, 16947715}, - {7359, 16947971}, {7360, 1}, {7368, 2}, {7376, 1}, - {7419, 2}, {7424, 1}, {7468, 16777219}, {7469, 16791043}, - {7470, 16777475}, {7471, 1}, {7472, 16777987}, {7473, 16778243}, - {7474, 16816131}, {7475, 16778755}, {7476, 16779011}, {7477, 16779267}, - {7478, 16779523}, {7479, 16779779}, {7480, 16780035}, {7481, 16780291}, - {7482, 16780547}, {7483, 1}, {7484, 16780803}, {7485, 16835843}, - {7486, 16781059}, {7487, 16781571}, {7488, 16782083}, {7489, 16782339}, - {7490, 16782851}, {7491, 16777219}, {7492, 16948227}, {7493, 16948483}, - {7494, 16948739}, {7495, 16777475}, {7496, 16777987}, {7497, 16778243}, - {7498, 16816387}, {7499, 16816643}, {7500, 16948995}, {7501, 16778755}, - {7502, 1}, {7503, 16779779}, {7504, 16780291}, {7505, 16807171}, - {7506, 16780803}, {7507, 16814851}, {7508, 16949251}, {7509, 16949507}, - {7510, 16781059}, {7511, 16782083}, {7512, 16782339}, {7513, 16949763}, - {7514, 16818435}, {7515, 16782595}, {7516, 16950019}, {7517, 16851971}, - {7518, 16852227}, {7519, 16852483}, {7520, 16856323}, {7521, 16856579}, - {7522, 16779267}, {7523, 16781571}, {7524, 16782339}, {7525, 16782595}, - {7526, 16851971}, {7527, 16852227}, {7528, 16855299}, {7529, 16856323}, - {7530, 16856579}, {7531, 1}, {7544, 16869891}, {7545, 1}, - {7579, 16950275}, {7580, 16777731}, {7581, 16950531}, {7582, 16793603}, - {7583, 16948995}, {7584, 16778499}, {7585, 16950787}, {7586, 16951043}, - {7587, 16951299}, {7588, 16817923}, {7589, 16817667}, {7590, 16951555}, - {7591, 16951811}, {7592, 16952067}, {7593, 16952323}, {7594, 16952579}, - {7595, 16952835}, {7596, 16953091}, {7597, 16953347}, {7598, 16818691}, - {7599, 16953603}, {7600, 16953859}, {7601, 16818947}, {7602, 16954115}, - {7603, 16954371}, {7604, 16820483}, {7605, 16954627}, {7606, 16839683}, - {7607, 16821507}, {7608, 16954883}, {7609, 16821763}, {7610, 16839939}, - {7611, 16783619}, {7612, 16955139}, {7613, 16955395}, {7614, 16822531}, - {7615, 16853507}, {7616, 1}, {7680, 16955651}, {7681, 1}, - {7682, 16955907}, {7683, 1}, {7684, 16956163}, {7685, 1}, - {7686, 16956419}, {7687, 1}, {7688, 16956675}, {7689, 1}, - {7690, 16956931}, {7691, 1}, {7692, 16957187}, {7693, 1}, - {7694, 16957443}, {7695, 1}, {7696, 16957699}, {7697, 1}, - {7698, 16957955}, {7699, 1}, {7700, 16958211}, {7701, 1}, - {7702, 16958467}, {7703, 1}, {7704, 16958723}, {7705, 1}, - {7706, 16958979}, {7707, 1}, {7708, 16959235}, {7709, 1}, - {7710, 16959491}, {7711, 1}, {7712, 16959747}, {7713, 1}, - {7714, 16960003}, {7715, 1}, {7716, 16960259}, {7717, 1}, - {7718, 16960515}, {7719, 1}, {7720, 16960771}, {7721, 1}, - {7722, 16961027}, {7723, 1}, {7724, 16961283}, {7725, 1}, - {7726, 16961539}, {7727, 1}, {7728, 16961795}, {7729, 1}, - {7730, 16962051}, {7731, 1}, {7732, 16962307}, {7733, 1}, - {7734, 16962563}, {7735, 1}, {7736, 16962819}, {7737, 1}, - {7738, 16963075}, {7739, 1}, {7740, 16963331}, {7741, 1}, - {7742, 16963587}, {7743, 1}, {7744, 16963843}, {7745, 1}, - {7746, 16964099}, {7747, 1}, {7748, 16964355}, {7749, 1}, - {7750, 16964611}, {7751, 1}, {7752, 16964867}, {7753, 1}, - {7754, 16965123}, {7755, 1}, {7756, 16965379}, {7757, 1}, - {7758, 16965635}, {7759, 1}, {7760, 16965891}, {7761, 1}, - {7762, 16966147}, {7763, 1}, {7764, 16966403}, {7765, 1}, - {7766, 16966659}, {7767, 1}, {7768, 16966915}, {7769, 1}, - {7770, 16967171}, {7771, 1}, {7772, 16967427}, {7773, 1}, - {7774, 16967683}, {7775, 1}, {7776, 16967939}, {7777, 1}, - {7778, 16968195}, {7779, 1}, {7780, 16968451}, {7781, 1}, - {7782, 16968707}, {7783, 1}, {7784, 16968963}, {7785, 1}, - {7786, 16969219}, {7787, 1}, {7788, 16969475}, {7789, 1}, - {7790, 16969731}, {7791, 1}, {7792, 16969987}, {7793, 1}, - {7794, 16970243}, {7795, 1}, {7796, 16970499}, {7797, 1}, - {7798, 16970755}, {7799, 1}, {7800, 16971011}, {7801, 1}, - {7802, 16971267}, {7803, 1}, {7804, 16971523}, {7805, 1}, - {7806, 16971779}, {7807, 1}, {7808, 16972035}, {7809, 1}, - {7810, 16972291}, {7811, 1}, {7812, 16972547}, {7813, 1}, - {7814, 16972803}, {7815, 1}, {7816, 16973059}, {7817, 1}, - {7818, 16973315}, {7819, 1}, {7820, 16973571}, {7821, 1}, - {7822, 16973827}, {7823, 1}, {7824, 16974083}, {7825, 1}, - {7826, 16974339}, {7827, 1}, {7828, 16974595}, {7829, 1}, - {7834, 33752067}, {7835, 16967939}, {7836, 1}, {7838, 33752579}, - {7839, 1}, {7840, 16975875}, {7841, 1}, {7842, 16976131}, - {7843, 1}, {7844, 16976387}, {7845, 1}, {7846, 16976643}, - {7847, 1}, {7848, 16976899}, {7849, 1}, {7850, 16977155}, - {7851, 1}, {7852, 16977411}, {7853, 1}, {7854, 16977667}, - {7855, 1}, {7856, 16977923}, {7857, 1}, {7858, 16978179}, - {7859, 1}, {7860, 16978435}, {7861, 1}, {7862, 16978691}, - {7863, 1}, {7864, 16978947}, {7865, 1}, {7866, 16979203}, - {7867, 1}, {7868, 16979459}, {7869, 1}, {7870, 16979715}, - {7871, 1}, {7872, 16979971}, {7873, 1}, {7874, 16980227}, - {7875, 1}, {7876, 16980483}, {7877, 1}, {7878, 16980739}, - {7879, 1}, {7880, 16980995}, {7881, 1}, {7882, 16981251}, - {7883, 1}, {7884, 16981507}, {7885, 1}, {7886, 16981763}, - {7887, 1}, {7888, 16982019}, {7889, 1}, {7890, 16982275}, - {7891, 1}, {7892, 16982531}, {7893, 1}, {7894, 16982787}, - {7895, 1}, {7896, 16983043}, {7897, 1}, {7898, 16983299}, - {7899, 1}, {7900, 16983555}, {7901, 1}, {7902, 16983811}, - {7903, 1}, {7904, 16984067}, {7905, 1}, {7906, 16984323}, - {7907, 1}, {7908, 16984579}, {7909, 1}, {7910, 16984835}, - {7911, 1}, {7912, 16985091}, {7913, 1}, {7914, 16985347}, - {7915, 1}, {7916, 16985603}, {7917, 1}, {7918, 16985859}, - {7919, 1}, {7920, 16986115}, {7921, 1}, {7922, 16986371}, - {7923, 1}, {7924, 16986627}, {7925, 1}, {7926, 16986883}, - {7927, 1}, {7928, 16987139}, {7929, 1}, {7930, 16987395}, - {7931, 1}, {7932, 16987651}, {7933, 1}, {7934, 16987907}, - {7935, 1}, {7944, 16988163}, {7945, 16988419}, {7946, 16988675}, - {7947, 16988931}, {7948, 16989187}, {7949, 16989443}, {7950, 16989699}, - {7951, 16989955}, {7952, 1}, {7958, 2}, {7960, 16990211}, - {7961, 16990467}, {7962, 16990723}, {7963, 16990979}, {7964, 16991235}, - {7965, 16991491}, {7966, 2}, {7968, 1}, {7976, 16991747}, - {7977, 16992003}, {7978, 16992259}, {7979, 16992515}, {7980, 16992771}, - {7981, 16993027}, {7982, 16993283}, {7983, 16993539}, {7984, 1}, - {7992, 16993795}, {7993, 16994051}, {7994, 16994307}, {7995, 16994563}, - {7996, 16994819}, {7997, 16995075}, {7998, 16995331}, {7999, 16995587}, - {8000, 1}, {8006, 2}, {8008, 16995843}, {8009, 16996099}, - {8010, 16996355}, {8011, 16996611}, {8012, 16996867}, {8013, 16997123}, - {8014, 2}, {8016, 1}, {8024, 2}, {8025, 16997379}, - {8026, 2}, {8027, 16997635}, {8028, 2}, {8029, 16997891}, - {8030, 2}, {8031, 16998147}, {8032, 1}, {8040, 16998403}, - {8041, 16998659}, {8042, 16998915}, {8043, 16999171}, {8044, 16999427}, - {8045, 16999683}, {8046, 16999939}, {8047, 17000195}, {8048, 1}, - {8049, 16849923}, {8050, 1}, {8051, 16850179}, {8052, 1}, - {8053, 16850435}, {8054, 1}, {8055, 16850691}, {8056, 1}, - {8057, 16850947}, {8058, 1}, {8059, 16851203}, {8060, 1}, - {8061, 16851459}, {8062, 2}, {8064, 33777667}, {8065, 33778179}, - {8066, 33778691}, {8067, 33779203}, {8068, 33779715}, {8069, 33780227}, - {8070, 33780739}, {8071, 33781251}, {8072, 33777667}, {8073, 33778179}, - {8074, 33778691}, {8075, 33779203}, {8076, 33779715}, {8077, 33780227}, - {8078, 33780739}, {8079, 33781251}, {8080, 33781763}, {8081, 33782275}, - {8082, 33782787}, {8083, 33783299}, {8084, 33783811}, {8085, 33784323}, - {8086, 33784835}, {8087, 33785347}, {8088, 33781763}, {8089, 33782275}, - {8090, 33782787}, {8091, 33783299}, {8092, 33783811}, {8093, 33784323}, - {8094, 33784835}, {8095, 33785347}, {8096, 33785859}, {8097, 33786371}, - {8098, 33786883}, {8099, 33787395}, {8100, 33787907}, {8101, 33788419}, - {8102, 33788931}, {8103, 33789443}, {8104, 33785859}, {8105, 33786371}, - {8106, 33786883}, {8107, 33787395}, {8108, 33787907}, {8109, 33788419}, - {8110, 33788931}, {8111, 33789443}, {8112, 1}, {8114, 33789955}, - {8115, 33790467}, {8116, 33790979}, {8117, 2}, {8118, 1}, - {8119, 33791491}, {8120, 17014787}, {8121, 17015043}, {8122, 17012739}, - {8123, 16849923}, {8124, 33790467}, {8125, 33792515}, {8126, 16846851}, - {8127, 33792515}, {8128, 33793027}, {8129, 50570755}, {8130, 33794307}, - {8131, 33794819}, {8132, 33795331}, {8133, 2}, {8134, 1}, - {8135, 33795843}, {8136, 17019139}, {8137, 16850179}, {8138, 17017091}, - {8139, 16850435}, {8140, 33794819}, {8141, 50573827}, {8142, 50574595}, - {8143, 50575363}, {8144, 1}, {8147, 17021699}, {8148, 2}, - {8150, 1}, {8152, 17021955}, {8153, 17022211}, {8154, 17022467}, - {8155, 16850691}, {8156, 2}, {8157, 50577155}, {8158, 50577923}, - {8159, 50578691}, {8160, 1}, {8163, 17025027}, {8164, 1}, - {8168, 17025283}, {8169, 17025539}, {8170, 17025795}, {8171, 16851203}, - {8172, 17026051}, {8173, 50580739}, {8174, 50403587}, {8175, 17027075}, - {8176, 2}, {8178, 33804547}, {8179, 33805059}, {8180, 33805571}, - {8181, 2}, {8182, 1}, {8183, 33806083}, {8184, 17029379}, - {8185, 16850947}, {8186, 17027331}, {8187, 16851459}, {8188, 33805059}, - {8189, 33562883}, {8190, 33799939}, {8191, 2}, {8192, 16783875}, - {8203, 0}, {8204, 1}, {8206, 2}, {8208, 1}, - {8209, 17029635}, {8210, 1}, {8215, 33807107}, {8216, 1}, - {8228, 2}, {8231, 1}, {8232, 2}, {8239, 16783875}, - {8240, 1}, {8243, 33807619}, {8244, 50585347}, {8245, 1}, - {8246, 33808899}, {8247, 50586627}, {8248, 1}, {8252, 33810179}, - {8253, 1}, {8254, 33810691}, {8255, 1}, {8263, 33811203}, - {8264, 33811715}, {8265, 33812227}, {8266, 1}, {8279, 67362051}, - {8280, 1}, {8287, 16783875}, {8288, 0}, {8289, 2}, - {8292, 0}, {8293, 2}, {8304, 17035523}, {8305, 16779267}, - {8306, 2}, {8308, 16787715}, {8309, 17035779}, {8310, 17036035}, - {8311, 17036291}, {8312, 17036547}, {8313, 17036803}, {8314, 17037059}, - {8315, 17037315}, {8316, 17037571}, {8317, 17037827}, {8318, 17038083}, - {8319, 16780547}, {8320, 17035523}, {8321, 16786947}, {8322, 16785155}, - {8323, 16785411}, {8324, 16787715}, {8325, 17035779}, {8326, 17036035}, - {8327, 17036291}, {8328, 17036547}, {8329, 17036803}, {8330, 17037059}, - {8331, 17037315}, {8332, 17037571}, {8333, 17037827}, {8334, 17038083}, - {8335, 2}, {8336, 16777219}, {8337, 16778243}, {8338, 16780803}, - {8339, 16783107}, {8340, 16816387}, {8341, 16779011}, {8342, 16779779}, - {8343, 16780035}, {8344, 16780291}, {8345, 16780547}, {8346, 16781059}, - {8347, 16781827}, {8348, 16782083}, {8349, 2}, {8352, 1}, - {8360, 33558787}, {8361, 1}, {8385, 2}, {8400, 1}, - {8433, 2}, {8448, 50592771}, {8449, 50593539}, {8450, 16777731}, - {8451, 33817091}, {8452, 1}, {8453, 50594819}, {8454, 50595587}, - {8455, 16816643}, {8456, 1}, {8457, 33819139}, {8458, 16778755}, - {8459, 16779011}, {8463, 16802051}, {8464, 16779267}, {8466, 16780035}, - {8468, 1}, {8469, 16780547}, {8470, 33557763}, {8471, 1}, - {8473, 16781059}, {8474, 16781315}, {8475, 16781571}, {8478, 1}, - {8480, 33819651}, {8481, 50597379}, {8482, 33820931}, {8483, 1}, - {8484, 16783619}, {8485, 1}, {8486, 16857091}, {8487, 1}, - {8488, 16783619}, {8489, 1}, {8490, 16779779}, {8491, 16790787}, - {8492, 16777475}, {8493, 16777731}, {8494, 1}, {8495, 16778243}, - {8497, 16778499}, {8498, 2}, {8499, 16780291}, {8500, 16780803}, - {8501, 17044227}, {8502, 17044483}, {8503, 17044739}, {8504, 17044995}, - {8505, 16779267}, {8506, 1}, {8507, 50599683}, {8508, 16855043}, - {8509, 16852227}, {8511, 16855043}, {8512, 17046019}, {8513, 1}, - {8517, 16777987}, {8519, 16778243}, {8520, 16779267}, {8521, 16779523}, - {8522, 1}, {8528, 50600707}, {8529, 50601475}, {8530, 67379459}, - {8531, 50603267}, {8532, 50604035}, {8533, 50604803}, {8534, 50605571}, - {8535, 50606339}, {8536, 50607107}, {8537, 50607875}, {8538, 50608643}, - {8539, 50609411}, {8540, 50610179}, {8541, 50610947}, {8542, 50611715}, - {8543, 33564419}, {8544, 16779267}, {8545, 33835267}, {8546, 50612995}, - {8547, 33836547}, {8548, 16782595}, {8549, 33837059}, {8550, 50614787}, - {8551, 67392771}, {8552, 33839363}, {8553, 16783107}, {8554, 33839875}, - {8555, 50617603}, {8556, 16780035}, {8557, 16777731}, {8558, 16777987}, - {8559, 16780291}, {8560, 16779267}, {8561, 33835267}, {8562, 50612483}, - {8563, 33836547}, {8564, 16782595}, {8565, 33837059}, {8566, 50614787}, - {8567, 67392771}, {8568, 33839363}, {8569, 16783107}, {8570, 33839875}, - {8571, 50617603}, {8572, 16780035}, {8573, 16777731}, {8574, 16777987}, - {8575, 16780291}, {8576, 1}, {8579, 2}, {8580, 1}, - {8585, 50618371}, {8586, 1}, {8588, 2}, {8592, 1}, - {8748, 33841923}, {8749, 50619651}, {8750, 1}, {8751, 33843203}, - {8752, 50620931}, {8753, 1}, {9001, 17067267}, {9002, 17067523}, - {9003, 1}, {9255, 2}, {9280, 1}, {9291, 2}, - {9312, 16786947}, {9313, 16785155}, {9314, 16785411}, {9315, 16787715}, - {9316, 17035779}, {9317, 17036035}, {9318, 17036291}, {9319, 17036547}, - {9320, 17036803}, {9321, 33825539}, {9322, 33564163}, {9323, 33844995}, - {9324, 33845507}, {9325, 33846019}, {9326, 33846531}, {9327, 33847043}, - {9328, 33847555}, {9329, 33848067}, {9330, 33848579}, {9331, 33849091}, - {9332, 50626819}, {9333, 50627587}, {9334, 50628355}, {9335, 50629123}, - {9336, 50629891}, {9337, 50630659}, {9338, 50631427}, {9339, 50632195}, - {9340, 50632963}, {9341, 67410947}, {9342, 67411971}, {9343, 67412995}, - {9344, 67414019}, {9345, 67415043}, {9346, 67416067}, {9347, 67417091}, - {9348, 67418115}, {9349, 67419139}, {9350, 67420163}, {9351, 67421187}, - {9352, 2}, {9372, 50644995}, {9373, 50645763}, {9374, 50646531}, - {9375, 50647299}, {9376, 50648067}, {9377, 50648835}, {9378, 50649603}, - {9379, 50650371}, {9380, 50651139}, {9381, 50651907}, {9382, 50652675}, - {9383, 50653443}, {9384, 50654211}, {9385, 50654979}, {9386, 50655747}, - {9387, 50656515}, {9388, 50657283}, {9389, 50658051}, {9390, 50658819}, - {9391, 50659587}, {9392, 50660355}, {9393, 50661123}, {9394, 50661891}, - {9395, 50662659}, {9396, 50663427}, {9397, 50664195}, {9398, 16777219}, - {9399, 16777475}, {9400, 16777731}, {9401, 16777987}, {9402, 16778243}, - {9403, 16778499}, {9404, 16778755}, {9405, 16779011}, {9406, 16779267}, - {9407, 16779523}, {9408, 16779779}, {9409, 16780035}, {9410, 16780291}, - {9411, 16780547}, {9412, 16780803}, {9413, 16781059}, {9414, 16781315}, - {9415, 16781571}, {9416, 16781827}, {9417, 16782083}, {9418, 16782339}, - {9419, 16782595}, {9420, 16782851}, {9421, 16783107}, {9422, 16783363}, - {9423, 16783619}, {9424, 16777219}, {9425, 16777475}, {9426, 16777731}, - {9427, 16777987}, {9428, 16778243}, {9429, 16778499}, {9430, 16778755}, - {9431, 16779011}, {9432, 16779267}, {9433, 16779523}, {9434, 16779779}, - {9435, 16780035}, {9436, 16780291}, {9437, 16780547}, {9438, 16780803}, - {9439, 16781059}, {9440, 16781315}, {9441, 16781571}, {9442, 16781827}, - {9443, 16782083}, {9444, 16782339}, {9445, 16782595}, {9446, 16782851}, - {9447, 16783107}, {9448, 16783363}, {9449, 16783619}, {9450, 17035523}, - {9451, 1}, {10764, 67396355}, {10765, 1}, {10868, 50664963}, - {10869, 33888515}, {10870, 50665475}, {10871, 1}, {10972, 33889027}, - {10973, 1}, {11124, 2}, {11126, 1}, {11158, 2}, - {11159, 1}, {11264, 17112323}, {11265, 17112579}, {11266, 17112835}, - {11267, 17113091}, {11268, 17113347}, {11269, 17113603}, {11270, 17113859}, - {11271, 17114115}, {11272, 17114371}, {11273, 17114627}, {11274, 17114883}, - {11275, 17115139}, {11276, 17115395}, {11277, 17115651}, {11278, 17115907}, - {11279, 17116163}, {11280, 17116419}, {11281, 17116675}, {11282, 17116931}, - {11283, 17117187}, {11284, 17117443}, {11285, 17117699}, {11286, 17117955}, - {11287, 17118211}, {11288, 17118467}, {11289, 17118723}, {11290, 17118979}, - {11291, 17119235}, {11292, 17119491}, {11293, 17119747}, {11294, 17120003}, - {11295, 17120259}, {11296, 17120515}, {11297, 17120771}, {11298, 17121027}, - {11299, 17121283}, {11300, 17121539}, {11301, 17121795}, {11302, 17122051}, - {11303, 17122307}, {11304, 17122563}, {11305, 17122819}, {11306, 17123075}, - {11307, 17123331}, {11308, 17123587}, {11309, 17123843}, {11310, 17124099}, - {11311, 17124355}, {11312, 1}, {11360, 17124611}, {11361, 1}, - {11362, 17124867}, {11363, 17125123}, {11364, 17125379}, {11365, 1}, - {11367, 17125635}, {11368, 1}, {11369, 17125891}, {11370, 1}, - {11371, 17126147}, {11372, 1}, {11373, 16948483}, {11374, 16953091}, - {11375, 16948227}, {11376, 16950275}, {11377, 1}, {11378, 17126403}, - {11379, 1}, {11381, 17126659}, {11382, 1}, {11388, 16779523}, - {11389, 16782595}, {11390, 17126915}, {11391, 17127171}, {11392, 17127427}, - {11393, 1}, {11394, 17127683}, {11395, 1}, {11396, 17127939}, - {11397, 1}, {11398, 17128195}, {11399, 1}, {11400, 17128451}, - {11401, 1}, {11402, 17128707}, {11403, 1}, {11404, 17128963}, - {11405, 1}, {11406, 17129219}, {11407, 1}, {11408, 17129475}, - {11409, 1}, {11410, 17129731}, {11411, 1}, {11412, 17129987}, - {11413, 1}, {11414, 17130243}, {11415, 1}, {11416, 17130499}, - {11417, 1}, {11418, 17130755}, {11419, 1}, {11420, 17131011}, - {11421, 1}, {11422, 17131267}, {11423, 1}, {11424, 17131523}, - {11425, 1}, {11426, 17131779}, {11427, 1}, {11428, 17132035}, - {11429, 1}, {11430, 17132291}, {11431, 1}, {11432, 17132547}, - {11433, 1}, {11434, 17132803}, {11435, 1}, {11436, 17133059}, - {11437, 1}, {11438, 17133315}, {11439, 1}, {11440, 17133571}, - {11441, 1}, {11442, 17133827}, {11443, 1}, {11444, 17134083}, - {11445, 1}, {11446, 17134339}, {11447, 1}, {11448, 17134595}, - {11449, 1}, {11450, 17134851}, {11451, 1}, {11452, 17135107}, - {11453, 1}, {11454, 17135363}, {11455, 1}, {11456, 17135619}, - {11457, 1}, {11458, 17135875}, {11459, 1}, {11460, 17136131}, - {11461, 1}, {11462, 17136387}, {11463, 1}, {11464, 17136643}, - {11465, 1}, {11466, 17136899}, {11467, 1}, {11468, 17137155}, - {11469, 1}, {11470, 17137411}, {11471, 1}, {11472, 17137667}, - {11473, 1}, {11474, 17137923}, {11475, 1}, {11476, 17138179}, - {11477, 1}, {11478, 17138435}, {11479, 1}, {11480, 17138691}, - {11481, 1}, {11482, 17138947}, {11483, 1}, {11484, 17139203}, - {11485, 1}, {11486, 17139459}, {11487, 1}, {11488, 17139715}, - {11489, 1}, {11490, 17139971}, {11491, 1}, {11499, 17140227}, - {11500, 1}, {11501, 17140483}, {11502, 1}, {11506, 17140739}, - {11507, 1}, {11508, 2}, {11513, 1}, {11558, 2}, - {11559, 1}, {11560, 2}, {11565, 1}, {11566, 2}, - {11568, 1}, {11624, 2}, {11631, 17140995}, {11632, 1}, - {11633, 2}, {11647, 1}, {11671, 2}, {11680, 1}, - {11687, 2}, {11688, 1}, {11695, 2}, {11696, 1}, - {11703, 2}, {11704, 1}, {11711, 2}, {11712, 1}, - {11719, 2}, {11720, 1}, {11727, 2}, {11728, 1}, - {11735, 2}, {11736, 1}, {11743, 2}, {11744, 1}, - {11870, 2}, {11904, 1}, {11930, 2}, {11931, 1}, - {11935, 17141251}, {11936, 1}, {12019, 17141507}, {12020, 2}, - {12032, 17141763}, {12033, 17142019}, {12034, 17142275}, {12035, 17142531}, - {12036, 17142787}, {12037, 17143043}, {12038, 17143299}, {12039, 17143555}, - {12040, 17143811}, {12041, 17144067}, {12042, 17144323}, {12043, 17144579}, - {12044, 17144835}, {12045, 17145091}, {12046, 17145347}, {12047, 17145603}, - {12048, 17145859}, {12049, 17146115}, {12050, 17146371}, {12051, 17146627}, - {12052, 17146883}, {12053, 17147139}, {12054, 17147395}, {12055, 17147651}, - {12056, 17147907}, {12057, 17148163}, {12058, 17148419}, {12059, 17148675}, - {12060, 17148931}, {12061, 17149187}, {12062, 17149443}, {12063, 17149699}, - {12064, 17149955}, {12065, 17150211}, {12066, 17150467}, {12067, 17150723}, - {12068, 17150979}, {12069, 17151235}, {12070, 17151491}, {12071, 17151747}, - {12072, 17152003}, {12073, 17152259}, {12074, 17152515}, {12075, 17152771}, - {12076, 17153027}, {12077, 17153283}, {12078, 17153539}, {12079, 17153795}, - {12080, 17154051}, {12081, 17154307}, {12082, 17154563}, {12083, 17154819}, - {12084, 17155075}, {12085, 17155331}, {12086, 17155587}, {12087, 17155843}, - {12088, 17156099}, {12089, 17156355}, {12090, 17156611}, {12091, 17156867}, - {12092, 17157123}, {12093, 17157379}, {12094, 17157635}, {12095, 17157891}, - {12096, 17158147}, {12097, 17158403}, {12098, 17158659}, {12099, 17158915}, - {12100, 17159171}, {12101, 17159427}, {12102, 17159683}, {12103, 17159939}, - {12104, 17160195}, {12105, 17160451}, {12106, 17160707}, {12107, 17160963}, - {12108, 17161219}, {12109, 17161475}, {12110, 17161731}, {12111, 17161987}, - {12112, 17162243}, {12113, 17162499}, {12114, 17162755}, {12115, 17163011}, - {12116, 17163267}, {12117, 17163523}, {12118, 17163779}, {12119, 17164035}, - {12120, 17164291}, {12121, 17164547}, {12122, 17164803}, {12123, 17165059}, - {12124, 17165315}, {12125, 17165571}, {12126, 17165827}, {12127, 17166083}, - {12128, 17166339}, {12129, 17166595}, {12130, 17166851}, {12131, 17167107}, - {12132, 17167363}, {12133, 17167619}, {12134, 17167875}, {12135, 17168131}, - {12136, 17168387}, {12137, 17168643}, {12138, 17168899}, {12139, 17169155}, - {12140, 17169411}, {12141, 17169667}, {12142, 17169923}, {12143, 17170179}, - {12144, 17170435}, {12145, 17170691}, {12146, 17170947}, {12147, 17171203}, - {12148, 17171459}, {12149, 17171715}, {12150, 17171971}, {12151, 17172227}, - {12152, 17172483}, {12153, 17172739}, {12154, 17172995}, {12155, 17173251}, - {12156, 17173507}, {12157, 17173763}, {12158, 17174019}, {12159, 17174275}, - {12160, 17174531}, {12161, 17174787}, {12162, 17175043}, {12163, 17175299}, - {12164, 17175555}, {12165, 17175811}, {12166, 17176067}, {12167, 17176323}, - {12168, 17176579}, {12169, 17176835}, {12170, 17177091}, {12171, 17177347}, - {12172, 17177603}, {12173, 17177859}, {12174, 17178115}, {12175, 17178371}, - {12176, 17178627}, {12177, 17178883}, {12178, 17179139}, {12179, 17179395}, - {12180, 17179651}, {12181, 17179907}, {12182, 17180163}, {12183, 17180419}, - {12184, 17180675}, {12185, 17180931}, {12186, 17181187}, {12187, 17181443}, - {12188, 17181699}, {12189, 17181955}, {12190, 17182211}, {12191, 17182467}, - {12192, 17182723}, {12193, 17182979}, {12194, 17183235}, {12195, 17183491}, - {12196, 17183747}, {12197, 17184003}, {12198, 17184259}, {12199, 17184515}, - {12200, 17184771}, {12201, 17185027}, {12202, 17185283}, {12203, 17185539}, - {12204, 17185795}, {12205, 17186051}, {12206, 17186307}, {12207, 17186563}, - {12208, 17186819}, {12209, 17187075}, {12210, 17187331}, {12211, 17187587}, - {12212, 17187843}, {12213, 17188099}, {12214, 17188355}, {12215, 17188611}, - {12216, 17188867}, {12217, 17189123}, {12218, 17189379}, {12219, 17189635}, - {12220, 17189891}, {12221, 17190147}, {12222, 17190403}, {12223, 17190659}, - {12224, 17190915}, {12225, 17191171}, {12226, 17191427}, {12227, 17191683}, - {12228, 17191939}, {12229, 17192195}, {12230, 17192451}, {12231, 17192707}, - {12232, 17192963}, {12233, 17193219}, {12234, 17193475}, {12235, 17193731}, - {12236, 17193987}, {12237, 17194243}, {12238, 17194499}, {12239, 17194755}, - {12240, 17195011}, {12241, 17195267}, {12242, 17195523}, {12243, 17195779}, - {12244, 17196035}, {12245, 17196291}, {12246, 2}, {12288, 16783875}, - {12289, 1}, {12290, 17196547}, {12291, 1}, {12342, 17196803}, - {12343, 1}, {12344, 17147651}, {12345, 17197059}, {12346, 17197315}, - {12347, 1}, {12352, 2}, {12353, 1}, {12439, 2}, - {12441, 1}, {12443, 33974787}, {12444, 33975299}, {12445, 1}, - {12447, 33975811}, {12448, 1}, {12543, 33976323}, {12544, 2}, - {12549, 1}, {12592, 2}, {12593, 17199619}, {12594, 17199875}, - {12595, 17200131}, {12596, 17200387}, {12597, 17200643}, {12598, 17200899}, - {12599, 17201155}, {12600, 17201411}, {12601, 17201667}, {12602, 17201923}, - {12603, 17202179}, {12604, 17202435}, {12605, 17202691}, {12606, 17202947}, - {12607, 17203203}, {12608, 17203459}, {12609, 17203715}, {12610, 17203971}, - {12611, 17204227}, {12612, 17204483}, {12613, 17204739}, {12614, 17204995}, - {12615, 17205251}, {12616, 17205507}, {12617, 17205763}, {12618, 17206019}, - {12619, 17206275}, {12620, 17206531}, {12621, 17206787}, {12622, 17207043}, - {12623, 17207299}, {12624, 17207555}, {12625, 17207811}, {12626, 17208067}, - {12627, 17208323}, {12628, 17208579}, {12629, 17208835}, {12630, 17209091}, - {12631, 17209347}, {12632, 17209603}, {12633, 17209859}, {12634, 17210115}, - {12635, 17210371}, {12636, 17210627}, {12637, 17210883}, {12638, 17211139}, - {12639, 17211395}, {12640, 17211651}, {12641, 17211907}, {12642, 17212163}, - {12643, 17212419}, {12644, 2}, {12645, 17212675}, {12646, 17212931}, - {12647, 17213187}, {12648, 17213443}, {12649, 17213699}, {12650, 17213955}, - {12651, 17214211}, {12652, 17214467}, {12653, 17214723}, {12654, 17214979}, - {12655, 17215235}, {12656, 17215491}, {12657, 17215747}, {12658, 17216003}, - {12659, 17216259}, {12660, 17216515}, {12661, 17216771}, {12662, 17217027}, - {12663, 17217283}, {12664, 17217539}, {12665, 17217795}, {12666, 17218051}, - {12667, 17218307}, {12668, 17218563}, {12669, 17218819}, {12670, 17219075}, - {12671, 17219331}, {12672, 17219587}, {12673, 17219843}, {12674, 17220099}, - {12675, 17220355}, {12676, 17220611}, {12677, 17220867}, {12678, 17221123}, - {12679, 17221379}, {12680, 17221635}, {12681, 17221891}, {12682, 17222147}, - {12683, 17222403}, {12684, 17222659}, {12685, 17222915}, {12686, 17223171}, - {12687, 2}, {12688, 1}, {12690, 17141763}, {12691, 17143299}, - {12692, 17223427}, {12693, 17223683}, {12694, 17223939}, {12695, 17224195}, - {12696, 17224451}, {12697, 17224707}, {12698, 17142787}, {12699, 17224963}, - {12700, 17225219}, {12701, 17225475}, {12702, 17225731}, {12703, 17143811}, - {12704, 1}, {12772, 2}, {12784, 1}, {12800, 50780419}, - {12801, 50781187}, {12802, 50781955}, {12803, 50782723}, {12804, 50783491}, - {12805, 50784259}, {12806, 50785027}, {12807, 50785795}, {12808, 50786563}, - {12809, 50787331}, {12810, 50788099}, {12811, 50788867}, {12812, 50789635}, - {12813, 50790403}, {12814, 50791171}, {12815, 50791939}, {12816, 50792707}, - {12817, 50793475}, {12818, 50794243}, {12819, 50795011}, {12820, 50795779}, - {12821, 50796547}, {12822, 50797315}, {12823, 50798083}, {12824, 50798851}, - {12825, 50799619}, {12826, 50800387}, {12827, 50801155}, {12828, 50801923}, - {12829, 67579907}, {12830, 67580931}, {12831, 2}, {12832, 50804739}, - {12833, 50805507}, {12834, 50806275}, {12835, 50807043}, {12836, 50807811}, - {12837, 50808579}, {12838, 50809347}, {12839, 50810115}, {12840, 50810883}, - {12841, 50811651}, {12842, 50812419}, {12843, 50813187}, {12844, 50813955}, - {12845, 50814723}, {12846, 50815491}, {12847, 50816259}, {12848, 50817027}, - {12849, 50817795}, {12850, 50818563}, {12851, 50819331}, {12852, 50820099}, - {12853, 50820867}, {12854, 50821635}, {12855, 50822403}, {12856, 50823171}, - {12857, 50823939}, {12858, 50824707}, {12859, 50825475}, {12860, 50826243}, - {12861, 50827011}, {12862, 50827779}, {12863, 50828547}, {12864, 50829315}, - {12865, 50830083}, {12866, 50830851}, {12867, 50831619}, {12868, 17277955}, - {12869, 17278211}, {12870, 17158659}, {12871, 17278467}, {12872, 1}, - {12880, 50833155}, {12881, 33845251}, {12882, 34056707}, {12883, 33562371}, - {12884, 34057219}, {12885, 34057731}, {12886, 34058243}, {12887, 34058755}, - {12888, 34059267}, {12889, 34059779}, {12890, 34060291}, {12891, 33827331}, - {12892, 33826563}, {12893, 34060803}, {12894, 34061315}, {12895, 34061827}, - {12896, 17199619}, {12897, 17200387}, {12898, 17201155}, {12899, 17201667}, - {12900, 17203715}, {12901, 17203971}, {12902, 17204739}, {12903, 17205251}, - {12904, 17205507}, {12905, 17206019}, {12906, 17206275}, {12907, 17206531}, - {12908, 17206787}, {12909, 17207043}, {12910, 17236995}, {12911, 17237763}, - {12912, 17238531}, {12913, 17239299}, {12914, 17240067}, {12915, 17240835}, - {12916, 17241603}, {12917, 17242371}, {12918, 17243139}, {12919, 17243907}, - {12920, 17244675}, {12921, 17245443}, {12922, 17246211}, {12923, 17246979}, - {12924, 34062339}, {12925, 34062851}, {12926, 17286147}, {12927, 1}, - {12928, 17141763}, {12929, 17143299}, {12930, 17223427}, {12931, 17223683}, - {12932, 17253635}, {12933, 17254403}, {12934, 17255171}, {12935, 17144579}, - {12936, 17256707}, {12937, 17147651}, {12938, 17160451}, {12939, 17163523}, - {12940, 17163267}, {12941, 17160707}, {12942, 17184259}, {12943, 17149699}, - {12944, 17159939}, {12945, 17263619}, {12946, 17264387}, {12947, 17265155}, - {12948, 17265923}, {12949, 17266691}, {12950, 17267459}, {12951, 17268227}, - {12952, 17268995}, {12953, 17286403}, {12954, 17286659}, {12955, 17151235}, - {12956, 17286915}, {12957, 17287171}, {12958, 17287427}, {12959, 17287683}, - {12960, 17287939}, {12961, 17275907}, {12962, 17288195}, {12963, 17288451}, - {12964, 17223939}, {12965, 17224195}, {12966, 17224451}, {12967, 17288707}, - {12968, 17288963}, {12969, 17289219}, {12970, 17289475}, {12971, 17271299}, - {12972, 17272067}, {12973, 17272835}, {12974, 17273603}, {12975, 17274371}, - {12976, 17289731}, {12977, 34067203}, {12978, 34067715}, {12979, 34068227}, - {12980, 34068739}, {12981, 34069251}, {12982, 33564931}, {12983, 34057475}, - {12984, 34061571}, {12985, 34069763}, {12986, 34070275}, {12987, 34070787}, - {12988, 34071299}, {12989, 34071811}, {12990, 34072323}, {12991, 34072835}, - {12992, 34073347}, {12993, 34073859}, {12994, 34074371}, {12995, 34074883}, - {12996, 34075395}, {12997, 34075907}, {12998, 34076419}, {12999, 34076931}, - {13000, 34077443}, {13001, 50855171}, {13002, 50855939}, {13003, 50856707}, - {13004, 34080259}, {13005, 50857987}, {13006, 34081539}, {13007, 50859267}, - {13008, 17305603}, {13009, 17305859}, {13010, 17306115}, {13011, 17306371}, - {13012, 17306627}, {13013, 17306883}, {13014, 17307139}, {13015, 17307395}, - {13016, 17307651}, {13017, 17199107}, {13018, 17307907}, {13019, 17308163}, - {13020, 17308419}, {13021, 17308675}, {13022, 17308931}, {13023, 17309187}, - {13024, 17309443}, {13025, 17309699}, {13026, 17309955}, {13027, 17199363}, - {13028, 17310211}, {13029, 17310467}, {13030, 17310723}, {13031, 17310979}, - {13032, 17311235}, {13033, 17311491}, {13034, 17311747}, {13035, 17312003}, - {13036, 17312259}, {13037, 17312515}, {13038, 17312771}, {13039, 17313027}, - {13040, 17313283}, {13041, 17313539}, {13042, 17313795}, {13043, 17314051}, - {13044, 17314307}, {13045, 17314563}, {13046, 17314819}, {13047, 17315075}, - {13048, 17315331}, {13049, 17315587}, {13050, 17315843}, {13051, 17316099}, - {13052, 17316355}, {13053, 17316611}, {13054, 17316867}, {13055, 34094339}, - {13056, 67649283}, {13057, 67650307}, {13058, 67651331}, {13059, 50875139}, - {13060, 67653123}, {13061, 50876931}, {13062, 50877699}, {13063, 84432899}, - {13064, 67656963}, {13065, 50880771}, {13066, 50881539}, {13067, 50882307}, - {13068, 67660291}, {13069, 67661315}, {13070, 50885123}, {13071, 50885891}, - {13072, 34109443}, {13073, 50887171}, {13074, 67665155}, {13075, 67666179}, - {13076, 34112771}, {13077, 84444931}, {13078, 101223427}, {13079, 84447747}, - {13080, 50891011}, {13081, 84449027}, {13082, 84450307}, {13083, 67674371}, - {13084, 50898179}, {13085, 50898947}, {13086, 50899715}, {13087, 67677699}, - {13088, 84455939}, {13089, 67680003}, {13090, 50903811}, {13091, 50904579}, - {13092, 50905347}, {13093, 34128899}, {13094, 34129411}, {13095, 34118147}, - {13096, 34129923}, {13097, 50907651}, {13098, 50908419}, {13099, 84463619}, - {13100, 50910467}, {13101, 67688451}, {13102, 84466691}, {13103, 50913539}, - {13104, 34137091}, {13105, 34137603}, {13106, 84469763}, {13107, 67693827}, - {13108, 84472067}, {13109, 50918915}, {13110, 84474115}, {13111, 34143747}, - {13112, 50921475}, {13113, 50922243}, {13114, 50923011}, {13115, 50923779}, - {13116, 50924547}, {13117, 67702531}, {13118, 50926339}, {13119, 34149891}, - {13120, 50927619}, {13121, 50928387}, {13122, 50929155}, {13123, 67707139}, - {13124, 50930947}, {13125, 50931715}, {13126, 50932483}, {13127, 84487683}, - {13128, 67711747}, {13129, 34158339}, {13130, 84490499}, {13131, 34160131}, - {13132, 67715075}, {13133, 67669507}, {13134, 50938883}, {13135, 50939651}, - {13136, 50940419}, {13137, 67718403}, {13138, 34164995}, {13139, 50942723}, - {13140, 67720707}, {13141, 34167299}, {13142, 84499459}, {13143, 50893827}, - {13144, 34169091}, {13145, 34169603}, {13146, 34170115}, {13147, 34170627}, - {13148, 34171139}, {13149, 34171651}, {13150, 34172163}, {13151, 34172675}, - {13152, 34173187}, {13153, 34173699}, {13154, 50951427}, {13155, 50952195}, - {13156, 50952963}, {13157, 50953731}, {13158, 50954499}, {13159, 50955267}, - {13160, 50956035}, {13161, 50956803}, {13162, 50957571}, {13163, 50958339}, - {13164, 50959107}, {13165, 50959875}, {13166, 50960643}, {13167, 50961411}, - {13168, 50962179}, {13169, 50962947}, {13170, 34186499}, {13171, 34187011}, - {13172, 50964739}, {13173, 34188291}, {13174, 34188803}, {13175, 34189315}, - {13176, 50967043}, {13177, 50967811}, {13178, 34191363}, {13179, 34191875}, - {13180, 34192387}, {13181, 34192899}, {13182, 34193411}, {13183, 67748355}, - {13184, 34185987}, {13185, 34194947}, {13186, 34195459}, {13187, 34195971}, - {13188, 34196483}, {13189, 34196995}, {13190, 34197507}, {13191, 34198019}, - {13192, 50975747}, {13193, 67753731}, {13194, 34200323}, {13195, 34200835}, - {13196, 34201347}, {13197, 34201859}, {13198, 34202371}, {13199, 34202883}, - {13200, 34203395}, {13201, 50981123}, {13202, 50981891}, {13203, 50980355}, - {13204, 50982659}, {13205, 34206211}, {13206, 34206723}, {13207, 34207235}, - {13208, 33556995}, {13209, 34207747}, {13210, 34208259}, {13211, 34208771}, - {13212, 34209283}, {13213, 34209795}, {13214, 34210307}, {13215, 50988035}, - {13216, 50988803}, {13217, 34190083}, {13218, 50989571}, {13219, 50990339}, - {13220, 50991107}, {13221, 34190851}, {13222, 50991875}, {13223, 50992643}, - {13224, 67770627}, {13225, 34185987}, {13226, 50994435}, {13227, 50995203}, - {13228, 50995971}, {13229, 50996739}, {13230, 84551939}, {13231, 101330435}, - {13232, 34223107}, {13233, 34223619}, {13234, 34224131}, {13235, 34224643}, - {13236, 34225155}, {13237, 34225667}, {13238, 34226179}, {13239, 34226691}, - {13240, 34227203}, {13241, 34226691}, {13242, 34227715}, {13243, 34228227}, - {13244, 34228739}, {13245, 34229251}, {13246, 34229763}, {13247, 34229251}, - {13248, 34230275}, {13249, 34230787}, {13250, 2}, {13251, 34231299}, - {13252, 33817347}, {13253, 33554947}, {13254, 67786243}, {13255, 2}, - {13256, 34232835}, {13257, 34233347}, {13258, 34233859}, {13259, 34185731}, - {13260, 34234371}, {13261, 34234883}, {13262, 34210307}, {13263, 34235395}, - {13264, 33557251}, {13265, 34235907}, {13266, 51013635}, {13267, 34237187}, - {13268, 34197507}, {13269, 51014915}, {13270, 51015683}, {13271, 34239235}, - {13272, 2}, {13273, 51016963}, {13274, 34240515}, {13275, 34221315}, - {13276, 34241027}, {13277, 34241539}, {13278, 51019267}, {13279, 51020035}, - {13280, 34243587}, {13281, 34244099}, {13282, 34244611}, {13283, 34245123}, - {13284, 34245635}, {13285, 34246147}, {13286, 34246659}, {13287, 34247171}, - {13288, 34247683}, {13289, 51025411}, {13290, 51026179}, {13291, 51026947}, - {13292, 51027715}, {13293, 51028483}, {13294, 51029251}, {13295, 51030019}, - {13296, 51030787}, {13297, 51031555}, {13298, 51032323}, {13299, 51033091}, - {13300, 51033859}, {13301, 51034627}, {13302, 51035395}, {13303, 51036163}, - {13304, 51036931}, {13305, 51037699}, {13306, 51038467}, {13307, 51039235}, - {13308, 51040003}, {13309, 51040771}, {13310, 51041539}, {13311, 51042307}, - {13312, 1}, {42125, 2}, {42128, 1}, {42183, 2}, - {42192, 1}, {42540, 2}, {42560, 17488643}, {42561, 1}, - {42562, 17488899}, {42563, 1}, {42564, 17489155}, {42565, 1}, - {42566, 17489411}, {42567, 1}, {42568, 17489667}, {42569, 1}, - {42570, 16936451}, {42571, 1}, {42572, 17489923}, {42573, 1}, - {42574, 17490179}, {42575, 1}, {42576, 17490435}, {42577, 1}, - {42578, 17490691}, {42579, 1}, {42580, 17490947}, {42581, 1}, - {42582, 17491203}, {42583, 1}, {42584, 17491459}, {42585, 1}, - {42586, 17491715}, {42587, 1}, {42588, 17491971}, {42589, 1}, - {42590, 17492227}, {42591, 1}, {42592, 17492483}, {42593, 1}, - {42594, 17492739}, {42595, 1}, {42596, 17492995}, {42597, 1}, - {42598, 17493251}, {42599, 1}, {42600, 17493507}, {42601, 1}, - {42602, 17493763}, {42603, 1}, {42604, 17494019}, {42605, 1}, - {42624, 17494275}, {42625, 1}, {42626, 17494531}, {42627, 1}, - {42628, 17494787}, {42629, 1}, {42630, 17495043}, {42631, 1}, - {42632, 17495299}, {42633, 1}, {42634, 17495555}, {42635, 1}, - {42636, 17495811}, {42637, 1}, {42638, 17496067}, {42639, 1}, - {42640, 17496323}, {42641, 1}, {42642, 17496579}, {42643, 1}, - {42644, 17496835}, {42645, 1}, {42646, 17497091}, {42647, 1}, - {42648, 17497347}, {42649, 1}, {42650, 17497603}, {42651, 1}, - {42652, 16873219}, {42653, 16873731}, {42654, 1}, {42744, 2}, - {42752, 1}, {42786, 17497859}, {42787, 1}, {42788, 17498115}, - {42789, 1}, {42790, 17498371}, {42791, 1}, {42792, 17498627}, - {42793, 1}, {42794, 17498883}, {42795, 1}, {42796, 17499139}, - {42797, 1}, {42798, 17499395}, {42799, 1}, {42802, 17499651}, - {42803, 1}, {42804, 17499907}, {42805, 1}, {42806, 17500163}, - {42807, 1}, {42808, 17500419}, {42809, 1}, {42810, 17500675}, - {42811, 1}, {42812, 17500931}, {42813, 1}, {42814, 17501187}, - {42815, 1}, {42816, 17501443}, {42817, 1}, {42818, 17501699}, - {42819, 1}, {42820, 17501955}, {42821, 1}, {42822, 17502211}, - {42823, 1}, {42824, 17502467}, {42825, 1}, {42826, 17502723}, - {42827, 1}, {42828, 17502979}, {42829, 1}, {42830, 17503235}, - {42831, 1}, {42832, 17503491}, {42833, 1}, {42834, 17503747}, - {42835, 1}, {42836, 17504003}, {42837, 1}, {42838, 17504259}, - {42839, 1}, {42840, 17504515}, {42841, 1}, {42842, 17504771}, - {42843, 1}, {42844, 17505027}, {42845, 1}, {42846, 17505283}, - {42847, 1}, {42848, 17505539}, {42849, 1}, {42850, 17505795}, - {42851, 1}, {42852, 17506051}, {42853, 1}, {42854, 17506307}, - {42855, 1}, {42856, 17506563}, {42857, 1}, {42858, 17506819}, - {42859, 1}, {42860, 17507075}, {42861, 1}, {42862, 17507331}, - {42863, 1}, {42864, 17507331}, {42865, 1}, {42873, 17507587}, - {42874, 1}, {42875, 17507843}, {42876, 1}, {42877, 17508099}, - {42878, 17508355}, {42879, 1}, {42880, 17508611}, {42881, 1}, - {42882, 17508867}, {42883, 1}, {42884, 17509123}, {42885, 1}, - {42886, 17509379}, {42887, 1}, {42891, 17509635}, {42892, 1}, - {42893, 16951299}, {42894, 1}, {42896, 17509891}, {42897, 1}, - {42898, 17510147}, {42899, 1}, {42902, 17510403}, {42903, 1}, - {42904, 17510659}, {42905, 1}, {42906, 17510915}, {42907, 1}, - {42908, 17511171}, {42909, 1}, {42910, 17511427}, {42911, 1}, - {42912, 17511683}, {42913, 1}, {42914, 17511939}, {42915, 1}, - {42916, 17512195}, {42917, 1}, {42918, 17512451}, {42919, 1}, - {42920, 17512707}, {42921, 1}, {42922, 16841475}, {42923, 16948995}, - {42924, 16951043}, {42925, 17512963}, {42926, 16951555}, {42927, 1}, - {42928, 17513219}, {42929, 17513475}, {42930, 16952067}, {42931, 17513731}, - {42932, 17513987}, {42933, 1}, {42934, 17514243}, {42935, 1}, - {42936, 17514499}, {42937, 1}, {42938, 17514755}, {42939, 1}, - {42940, 17515011}, {42941, 1}, {42942, 17515267}, {42943, 1}, - {42944, 17515523}, {42945, 1}, {42946, 17515779}, {42947, 1}, - {42948, 17516035}, {42949, 16954371}, {42950, 17516291}, {42951, 17516547}, - {42952, 1}, {42953, 17516803}, {42954, 1}, {42955, 2}, - {42960, 17517059}, {42961, 1}, {42962, 2}, {42963, 1}, - {42964, 2}, {42965, 1}, {42966, 17517315}, {42967, 1}, - {42968, 17517571}, {42969, 1}, {42970, 2}, {42994, 16777731}, - {42995, 16778499}, {42996, 16781315}, {42997, 17517827}, {42998, 1}, - {43000, 16802051}, {43001, 16808195}, {43002, 1}, {43053, 2}, - {43056, 1}, {43066, 2}, {43072, 1}, {43128, 2}, - {43136, 1}, {43206, 2}, {43214, 1}, {43226, 2}, - {43232, 1}, {43348, 2}, {43359, 1}, {43389, 2}, - {43392, 1}, {43470, 2}, {43471, 1}, {43482, 2}, - {43486, 1}, {43519, 2}, {43520, 1}, {43575, 2}, - {43584, 1}, {43598, 2}, {43600, 1}, {43610, 2}, - {43612, 1}, {43715, 2}, {43739, 1}, {43767, 2}, - {43777, 1}, {43783, 2}, {43785, 1}, {43791, 2}, - {43793, 1}, {43799, 2}, {43808, 1}, {43815, 2}, - {43816, 1}, {43823, 2}, {43824, 1}, {43868, 17498371}, - {43869, 17518083}, {43870, 17124867}, {43871, 17518339}, {43872, 1}, - {43881, 17518595}, {43882, 1}, {43884, 2}, {43888, 17518851}, - {43889, 17519107}, {43890, 17519363}, {43891, 17519619}, {43892, 17519875}, - {43893, 17520131}, {43894, 17520387}, {43895, 17520643}, {43896, 17520899}, - {43897, 17521155}, {43898, 17521411}, {43899, 17521667}, {43900, 17521923}, - {43901, 17522179}, {43902, 17522435}, {43903, 17522691}, {43904, 17522947}, - {43905, 17523203}, {43906, 17523459}, {43907, 17523715}, {43908, 17523971}, - {43909, 17524227}, {43910, 17524483}, {43911, 17524739}, {43912, 17524995}, - {43913, 17525251}, {43914, 17525507}, {43915, 17525763}, {43916, 17526019}, - {43917, 17526275}, {43918, 17526531}, {43919, 17526787}, {43920, 17527043}, - {43921, 17527299}, {43922, 17527555}, {43923, 17527811}, {43924, 17528067}, - {43925, 17528323}, {43926, 17528579}, {43927, 17528835}, {43928, 17529091}, - {43929, 17529347}, {43930, 17529603}, {43931, 17529859}, {43932, 17530115}, - {43933, 17530371}, {43934, 17530627}, {43935, 17530883}, {43936, 17531139}, - {43937, 17531395}, {43938, 17531651}, {43939, 17531907}, {43940, 17532163}, - {43941, 17532419}, {43942, 17532675}, {43943, 17532931}, {43944, 17533187}, - {43945, 17533443}, {43946, 17533699}, {43947, 17533955}, {43948, 17534211}, - {43949, 17534467}, {43950, 17534723}, {43951, 17534979}, {43952, 17535235}, - {43953, 17535491}, {43954, 17535747}, {43955, 17536003}, {43956, 17536259}, - {43957, 17536515}, {43958, 17536771}, {43959, 17537027}, {43960, 17537283}, - {43961, 17537539}, {43962, 17537795}, {43963, 17538051}, {43964, 17538307}, - {43965, 17538563}, {43966, 17538819}, {43967, 17539075}, {43968, 1}, - {44014, 2}, {44016, 1}, {44026, 2}, {44032, 1}, - {55204, 2}, {55216, 1}, {55239, 2}, {55243, 1}, - {55292, 2}, {63744, 17539331}, {63745, 17539587}, {63746, 17182211}, - {63747, 17539843}, {63748, 17540099}, {63749, 17540355}, {63750, 17540611}, - {63751, 17196035}, {63753, 17540867}, {63754, 17184259}, {63755, 17541123}, - {63756, 17541379}, {63757, 17541635}, {63758, 17541891}, {63759, 17542147}, - {63760, 17542403}, {63761, 17542659}, {63762, 17542915}, {63763, 17543171}, - {63764, 17543427}, {63765, 17543683}, {63766, 17543939}, {63767, 17544195}, - {63768, 17544451}, {63769, 17544707}, {63770, 17544963}, {63771, 17545219}, - {63772, 17545475}, {63773, 17545731}, {63774, 17545987}, {63775, 17546243}, - {63776, 17546499}, {63777, 17546755}, {63778, 17547011}, {63779, 17547267}, - {63780, 17547523}, {63781, 17547779}, {63782, 17548035}, {63783, 17548291}, - {63784, 17548547}, {63785, 17548803}, {63786, 17549059}, {63787, 17549315}, - {63788, 17549571}, {63789, 17549827}, {63790, 17550083}, {63791, 17550339}, - {63792, 17550595}, {63793, 17550851}, {63794, 17551107}, {63795, 17551363}, - {63796, 17173507}, {63797, 17551619}, {63798, 17551875}, {63799, 17552131}, - {63800, 17552387}, {63801, 17552643}, {63802, 17552899}, {63803, 17553155}, - {63804, 17553411}, {63805, 17553667}, {63806, 17553923}, {63807, 17554179}, - {63808, 17192195}, {63809, 17554435}, {63810, 17554691}, {63811, 17554947}, - {63812, 17555203}, {63813, 17555459}, {63814, 17555715}, {63815, 17555971}, - {63816, 17556227}, {63817, 17556483}, {63818, 17556739}, {63819, 17556995}, - {63820, 17557251}, {63821, 17557507}, {63822, 17557763}, {63823, 17558019}, - {63824, 17558275}, {63825, 17558531}, {63826, 17558787}, {63827, 17559043}, - {63828, 17559299}, {63829, 17559555}, {63830, 17559811}, {63831, 17560067}, - {63832, 17560323}, {63833, 17560579}, {63834, 17560835}, {63835, 17561091}, - {63836, 17543427}, {63837, 17561347}, {63838, 17561603}, {63839, 17561859}, - {63840, 17562115}, {63841, 17562371}, {63842, 17562627}, {63843, 17562883}, - {63844, 17563139}, {63845, 17563395}, {63846, 17563651}, {63847, 17563907}, - {63848, 17564163}, {63849, 17564419}, {63850, 17564675}, {63851, 17564931}, - {63852, 17565187}, {63853, 17565443}, {63854, 17565699}, {63855, 17565955}, - {63856, 17566211}, {63857, 17182723}, {63858, 17566467}, {63859, 17566723}, - {63860, 17566979}, {63861, 17567235}, {63862, 17567491}, {63863, 17567747}, - {63864, 17568003}, {63865, 17568259}, {63866, 17568515}, {63867, 17568771}, - {63868, 17569027}, {63869, 17569283}, {63870, 17569539}, {63871, 17569795}, - {63872, 17570051}, {63873, 17151235}, {63874, 17570307}, {63875, 17570563}, - {63876, 17570819}, {63877, 17571075}, {63878, 17571331}, {63879, 17571587}, - {63880, 17571843}, {63881, 17572099}, {63882, 17146371}, {63883, 17572355}, - {63884, 17572611}, {63885, 17572867}, {63886, 17573123}, {63887, 17573379}, - {63888, 17573635}, {63889, 17573891}, {63890, 17574147}, {63891, 17574403}, - {63892, 17574659}, {63893, 17574915}, {63894, 17575171}, {63895, 17575427}, - {63896, 17575683}, {63897, 17575939}, {63898, 17576195}, {63899, 17576451}, - {63900, 17576707}, {63901, 17576963}, {63902, 17577219}, {63903, 17577475}, - {63904, 17577731}, {63905, 17565955}, {63906, 17577987}, {63907, 17578243}, - {63908, 17578499}, {63909, 17578755}, {63910, 17579011}, {63911, 17579267}, - {63912, 17317123}, {63913, 17579523}, {63914, 17561859}, {63915, 17579779}, - {63916, 17580035}, {63917, 17580291}, {63918, 17580547}, {63919, 17580803}, - {63920, 17581059}, {63921, 17581315}, {63922, 17581571}, {63923, 17581827}, - {63924, 17582083}, {63925, 17582339}, {63926, 17582595}, {63927, 17582851}, - {63928, 17583107}, {63929, 17583363}, {63930, 17583619}, {63931, 17583875}, - {63932, 17584131}, {63933, 17584387}, {63934, 17584643}, {63935, 17543427}, - {63936, 17584899}, {63937, 17585155}, {63938, 17585411}, {63939, 17585667}, - {63940, 17195779}, {63941, 17585923}, {63942, 17586179}, {63943, 17586435}, - {63944, 17586691}, {63945, 17586947}, {63946, 17587203}, {63947, 17587459}, - {63948, 17587715}, {63949, 17587971}, {63950, 17588227}, {63951, 17588483}, - {63952, 17588739}, {63953, 17254403}, {63954, 17588995}, {63955, 17589251}, - {63956, 17589507}, {63957, 17589763}, {63958, 17590019}, {63959, 17590275}, - {63960, 17590531}, {63961, 17590787}, {63962, 17591043}, {63963, 17562371}, - {63964, 17591299}, {63965, 17591555}, {63966, 17591811}, {63967, 17592067}, - {63968, 17592323}, {63969, 17592579}, {63970, 17592835}, {63971, 17593091}, - {63972, 17593347}, {63973, 17593603}, {63974, 17593859}, {63975, 17594115}, - {63976, 17594371}, {63977, 17184003}, {63978, 17594627}, {63979, 17594883}, - {63980, 17595139}, {63981, 17595395}, {63982, 17595651}, {63983, 17595907}, - {63984, 17596163}, {63985, 17596419}, {63986, 17596675}, {63987, 17596931}, - {63988, 17597187}, {63989, 17597443}, {63990, 17597699}, {63991, 17171459}, - {63992, 17597955}, {63993, 17598211}, {63994, 17598467}, {63995, 17598723}, - {63996, 17598979}, {63997, 17599235}, {63998, 17599491}, {63999, 17599747}, - {64000, 17600003}, {64001, 17600259}, {64002, 17600515}, {64003, 17600771}, - {64004, 17601027}, {64005, 17601283}, {64006, 17601539}, {64007, 17601795}, - {64008, 17178371}, {64009, 17602051}, {64010, 17179139}, {64011, 17602307}, - {64012, 17602563}, {64013, 17602819}, {64014, 1}, {64016, 17603075}, - {64017, 1}, {64018, 17603331}, {64019, 1}, {64021, 17603587}, - {64022, 17603843}, {64023, 17604099}, {64024, 17604355}, {64025, 17604611}, - {64026, 17604867}, {64027, 17605123}, {64028, 17605379}, {64029, 17605635}, - {64030, 17173251}, {64031, 1}, {64032, 17605891}, {64033, 1}, - {64034, 17606147}, {64035, 1}, {64037, 17606403}, {64038, 17606659}, - {64039, 1}, {64042, 17606915}, {64043, 17607171}, {64044, 17607427}, - {64045, 17607683}, {64046, 17607939}, {64047, 17608195}, {64048, 17608451}, - {64049, 17608707}, {64050, 17608963}, {64051, 17609219}, {64052, 17609475}, - {64053, 17609731}, {64054, 17609987}, {64055, 17610243}, {64056, 17610499}, - {64057, 17610755}, {64058, 17611011}, {64059, 17611267}, {64060, 17153027}, - {64061, 17611523}, {64062, 17611779}, {64063, 17612035}, {64064, 17612291}, - {64065, 17612547}, {64066, 17612803}, {64067, 17613059}, {64068, 17613315}, - {64069, 17613571}, {64070, 17613827}, {64071, 17614083}, {64072, 17614339}, - {64073, 17614595}, {64074, 17614851}, {64075, 17615107}, {64076, 17265155}, - {64077, 17615363}, {64078, 17615619}, {64079, 17615875}, {64080, 17616131}, - {64081, 17268227}, {64082, 17616387}, {64083, 17616643}, {64084, 17616899}, - {64085, 17617155}, {64086, 17617411}, {64087, 17575171}, {64088, 17617667}, - {64089, 17617923}, {64090, 17618179}, {64091, 17618435}, {64092, 17618691}, - {64093, 17618947}, {64095, 17619203}, {64096, 17619459}, {64097, 17619715}, - {64098, 17619971}, {64099, 17620227}, {64100, 17620483}, {64101, 17620739}, - {64102, 17620995}, {64103, 17606403}, {64104, 17621251}, {64105, 17621507}, - {64106, 17621763}, {64107, 17622019}, {64108, 17622275}, {64109, 17622531}, - {64110, 2}, {64112, 17622787}, {64113, 17623043}, {64114, 17623299}, - {64115, 17623555}, {64116, 17623811}, {64117, 17624067}, {64118, 17624323}, - {64119, 17624579}, {64120, 17609987}, {64121, 17624835}, {64122, 17625091}, - {64123, 17625347}, {64124, 17603075}, {64125, 17625603}, {64126, 17625859}, - {64127, 17626115}, {64128, 17626371}, {64129, 17626627}, {64130, 17626883}, - {64131, 17627139}, {64132, 17627395}, {64133, 17627651}, {64134, 17627907}, - {64135, 17628163}, {64136, 17628419}, {64137, 17612035}, {64138, 17628675}, - {64139, 17612291}, {64140, 17628931}, {64141, 17629187}, {64142, 17629443}, - {64143, 17629699}, {64144, 17629955}, {64145, 17603331}, {64146, 17548803}, - {64147, 17630211}, {64148, 17630467}, {64149, 17161475}, {64150, 17566211}, - {64151, 17587203}, {64152, 17630723}, {64153, 17630979}, {64154, 17614083}, - {64155, 17631235}, {64156, 17614339}, {64157, 17631491}, {64158, 17631747}, - {64159, 17632003}, {64160, 17603843}, {64161, 17632259}, {64162, 17632515}, - {64163, 17632771}, {64164, 17633027}, {64165, 17633283}, {64166, 17604099}, - {64167, 17633539}, {64168, 17633795}, {64169, 17634051}, {64170, 17634307}, - {64171, 17634563}, {64172, 17634819}, {64173, 17617411}, {64174, 17635075}, - {64175, 17635331}, {64176, 17575171}, {64177, 17635587}, {64178, 17618435}, - {64179, 17635843}, {64180, 17636099}, {64181, 17636355}, {64182, 17636611}, - {64183, 17636867}, {64184, 17619715}, {64185, 17637123}, {64186, 17606147}, - {64187, 17637379}, {64188, 17619971}, {64189, 17561347}, {64190, 17637635}, - {64191, 17620227}, {64192, 17637891}, {64193, 17620739}, {64194, 17638147}, - {64195, 17638403}, {64196, 17638659}, {64197, 17638915}, {64198, 17639171}, - {64199, 17621251}, {64200, 17605379}, {64201, 17639427}, {64202, 17621507}, - {64203, 17639683}, {64204, 17621763}, {64205, 17639939}, {64206, 17196035}, - {64207, 17640195}, {64208, 17640451}, {64209, 17640707}, {64210, 17640963}, - {64211, 17641219}, {64212, 17641475}, {64213, 17641731}, {64214, 17641987}, - {64215, 17642243}, {64216, 17642499}, {64217, 17642755}, {64218, 2}, - {64256, 34420227}, {64257, 34420739}, {64258, 34421251}, {64259, 51197699}, - {64260, 51198979}, {64261, 33559043}, {64263, 2}, {64275, 34422531}, - {64276, 34423043}, {64277, 34423555}, {64278, 34424067}, {64279, 34424579}, - {64280, 2}, {64285, 34425091}, {64286, 1}, {64287, 34425603}, - {64288, 17648899}, {64289, 17044227}, {64290, 17044995}, {64291, 17649155}, - {64292, 17649411}, {64293, 17649667}, {64294, 17649923}, {64295, 17650179}, - {64296, 17650435}, {64297, 17037059}, {64298, 34427907}, {64299, 34428419}, - {64300, 51206147}, {64301, 51206915}, {64302, 34430467}, {64303, 34430979}, - {64304, 34431491}, {64305, 34432003}, {64306, 34432515}, {64307, 34433027}, - {64308, 34433539}, {64309, 34434051}, {64310, 34434563}, {64311, 2}, - {64312, 34435075}, {64313, 34435587}, {64314, 34436099}, {64315, 34436611}, - {64316, 34437123}, {64317, 2}, {64318, 34437635}, {64319, 2}, - {64320, 34438147}, {64321, 34438659}, {64322, 2}, {64323, 34439171}, - {64324, 34439683}, {64325, 2}, {64326, 34440195}, {64327, 34440707}, - {64328, 34441219}, {64329, 34428931}, {64330, 34441731}, {64331, 34442243}, - {64332, 34442755}, {64333, 34443267}, {64334, 34443779}, {64335, 34444291}, - {64336, 17667587}, {64338, 17667843}, {64342, 17668099}, {64346, 17668355}, - {64350, 17668611}, {64354, 17668867}, {64358, 17669123}, {64362, 17669379}, - {64366, 17669635}, {64370, 17669891}, {64374, 17670147}, {64378, 17670403}, - {64382, 17670659}, {64386, 17670915}, {64388, 17671171}, {64390, 17671427}, - {64392, 17671683}, {64394, 17671939}, {64396, 17672195}, {64398, 17672451}, - {64402, 17672707}, {64406, 17672963}, {64410, 17673219}, {64414, 17673475}, - {64416, 17673731}, {64420, 17673987}, {64422, 17674243}, {64426, 17674499}, - {64430, 17674755}, {64432, 17675011}, {64434, 1}, {64451, 2}, - {64467, 17675267}, {64471, 16911363}, {64473, 17675523}, {64475, 17675779}, - {64477, 33688579}, {64478, 17676035}, {64480, 17676291}, {64482, 17676547}, - {64484, 17676803}, {64488, 17677059}, {64490, 34454531}, {64492, 34455043}, - {64494, 34455555}, {64496, 34456067}, {64498, 34456579}, {64500, 34457091}, - {64502, 34457603}, {64505, 34458115}, {64508, 17681411}, {64512, 34458883}, - {64513, 34459395}, {64514, 34459907}, {64515, 34458115}, {64516, 34460419}, - {64517, 34460931}, {64518, 34461443}, {64519, 34461955}, {64520, 34462467}, - {64521, 34462979}, {64522, 34463491}, {64523, 34464003}, {64524, 34464515}, - {64525, 34465027}, {64526, 34465539}, {64527, 34466051}, {64528, 34466563}, - {64529, 34467075}, {64530, 34467587}, {64531, 34468099}, {64532, 34468611}, - {64533, 34469123}, {64534, 34469635}, {64535, 34469379}, {64536, 34470147}, - {64537, 34470659}, {64538, 34471171}, {64539, 34471683}, {64540, 34472195}, - {64541, 34472707}, {64542, 34473219}, {64543, 34473731}, {64544, 34474243}, - {64545, 34474755}, {64546, 34475267}, {64547, 34475779}, {64548, 34476291}, - {64549, 34476803}, {64550, 34477315}, {64551, 34477827}, {64552, 34478339}, - {64553, 34478851}, {64554, 34479363}, {64555, 34479875}, {64556, 34480387}, - {64557, 34480899}, {64558, 34481411}, {64559, 34481923}, {64560, 34482435}, - {64561, 34482947}, {64562, 34483459}, {64563, 34483971}, {64564, 34484483}, - {64565, 34484995}, {64566, 34485507}, {64567, 34486019}, {64568, 34486531}, - {64569, 34487043}, {64570, 34487555}, {64571, 34488067}, {64572, 34488579}, - {64573, 34489091}, {64574, 34489603}, {64575, 34490115}, {64576, 34490627}, - {64577, 34491139}, {64578, 34491651}, {64579, 34492163}, {64580, 34492675}, - {64581, 34493187}, {64582, 34469891}, {64583, 34470403}, {64584, 34493699}, - {64585, 34494211}, {64586, 34494723}, {64587, 34495235}, {64588, 34495747}, - {64589, 34496259}, {64590, 34496771}, {64591, 34497283}, {64592, 34497795}, - {64593, 34498307}, {64594, 34498819}, {64595, 34499331}, {64596, 34499843}, - {64597, 34468867}, {64598, 34500355}, {64599, 34500867}, {64600, 34492931}, - {64601, 34501379}, {64602, 34500099}, {64603, 34501891}, {64604, 34502403}, - {64605, 34502915}, {64606, 51280643}, {64607, 51281411}, {64608, 51282179}, - {64609, 51282947}, {64610, 51283715}, {64611, 51284483}, {64612, 34508035}, - {64613, 34508547}, {64614, 34459907}, {64615, 34509059}, {64616, 34458115}, - {64617, 34460419}, {64618, 34509571}, {64619, 34510083}, {64620, 34462467}, - {64621, 34510595}, {64622, 34462979}, {64623, 34463491}, {64624, 34511107}, - {64625, 34511619}, {64626, 34465539}, {64627, 34512131}, {64628, 34466051}, - {64629, 34466563}, {64630, 34512643}, {64631, 34513155}, {64632, 34467587}, - {64633, 34513667}, {64634, 34468099}, {64635, 34468611}, {64636, 34482947}, - {64637, 34483459}, {64638, 34484995}, {64639, 34485507}, {64640, 34486019}, - {64641, 34488067}, {64642, 34488579}, {64643, 34489091}, {64644, 34489603}, - {64645, 34491651}, {64646, 34492163}, {64647, 34492675}, {64648, 34514179}, - {64649, 34493699}, {64650, 34514691}, {64651, 34515203}, {64652, 34496771}, - {64653, 34515715}, {64654, 34497283}, {64655, 34497795}, {64656, 34502915}, - {64657, 34516227}, {64658, 34516739}, {64659, 34492931}, {64660, 34494979}, - {64661, 34501379}, {64662, 34500099}, {64663, 34458883}, {64664, 34459395}, - {64665, 34517251}, {64666, 34459907}, {64667, 34517763}, {64668, 34460931}, - {64669, 34461443}, {64670, 34461955}, {64671, 34462467}, {64672, 34518275}, - {64673, 34464003}, {64674, 34464515}, {64675, 34465027}, {64676, 34465539}, - {64677, 34518787}, {64678, 34467587}, {64679, 34469123}, {64680, 34469635}, - {64681, 34469379}, {64682, 34470147}, {64683, 34470659}, {64684, 34471683}, - {64685, 34472195}, {64686, 34472707}, {64687, 34473219}, {64688, 34473731}, - {64689, 34474243}, {64690, 34519299}, {64691, 34474755}, {64692, 34475267}, - {64693, 34475779}, {64694, 34476291}, {64695, 34476803}, {64696, 34477315}, - {64697, 34478339}, {64698, 34478851}, {64699, 34479363}, {64700, 34479875}, - {64701, 34480387}, {64702, 34480899}, {64703, 34481411}, {64704, 34481923}, - {64705, 34482435}, {64706, 34483971}, {64707, 34484483}, {64708, 34486531}, - {64709, 34487043}, {64710, 34487555}, {64711, 34488067}, {64712, 34488579}, - {64713, 34490115}, {64714, 34490627}, {64715, 34491139}, {64716, 34491651}, - {64717, 34519811}, {64718, 34493187}, {64719, 34469891}, {64720, 34470403}, - {64721, 34493699}, {64722, 34495235}, {64723, 34495747}, {64724, 34496259}, - {64725, 34496771}, {64726, 34520323}, {64727, 34498307}, {64728, 34498819}, - {64729, 34520835}, {64730, 34468867}, {64731, 34500355}, {64732, 34500867}, - {64733, 34492931}, {64734, 34498051}, {64735, 34459907}, {64736, 34517763}, - {64737, 34462467}, {64738, 34518275}, {64739, 34465539}, {64740, 34518787}, - {64741, 34467587}, {64742, 34521347}, {64743, 34473731}, {64744, 34521859}, - {64745, 34522371}, {64746, 34522883}, {64747, 34488067}, {64748, 34488579}, - {64749, 34491651}, {64750, 34496771}, {64751, 34520323}, {64752, 34492931}, - {64753, 34498051}, {64754, 51300611}, {64755, 51301379}, {64756, 51302147}, - {64757, 34525699}, {64758, 34526211}, {64759, 34526723}, {64760, 34527235}, - {64761, 34527747}, {64762, 34528259}, {64763, 34528771}, {64764, 34529283}, - {64765, 34529795}, {64766, 34530307}, {64767, 34530819}, {64768, 34500611}, - {64769, 34531331}, {64770, 34531843}, {64771, 34532355}, {64772, 34501123}, - {64773, 34532867}, {64774, 34533379}, {64775, 34533891}, {64776, 34534403}, - {64777, 34534915}, {64778, 34535427}, {64779, 34535939}, {64780, 34522371}, - {64781, 34536451}, {64782, 34536963}, {64783, 34537475}, {64784, 34537987}, - {64785, 34525699}, {64786, 34526211}, {64787, 34526723}, {64788, 34527235}, - {64789, 34527747}, {64790, 34528259}, {64791, 34528771}, {64792, 34529283}, - {64793, 34529795}, {64794, 34530307}, {64795, 34530819}, {64796, 34500611}, - {64797, 34531331}, {64798, 34531843}, {64799, 34532355}, {64800, 34501123}, - {64801, 34532867}, {64802, 34533379}, {64803, 34533891}, {64804, 34534403}, - {64805, 34534915}, {64806, 34535427}, {64807, 34535939}, {64808, 34522371}, - {64809, 34536451}, {64810, 34536963}, {64811, 34537475}, {64812, 34537987}, - {64813, 34534915}, {64814, 34535427}, {64815, 34535939}, {64816, 34522371}, - {64817, 34521859}, {64818, 34522883}, {64819, 34477827}, {64820, 34472195}, - {64821, 34472707}, {64822, 34473219}, {64823, 34534915}, {64824, 34535427}, - {64825, 34535939}, {64826, 34477827}, {64827, 34478339}, {64828, 34538499}, - {64830, 1}, {64848, 51316227}, {64849, 51316995}, {64851, 51317763}, - {64852, 51318531}, {64853, 51319299}, {64854, 51320067}, {64855, 51320835}, - {64856, 51246851}, {64858, 51321603}, {64859, 51322371}, {64860, 51323139}, - {64861, 51323907}, {64862, 51324675}, {64863, 51325443}, {64865, 51326211}, - {64866, 51326979}, {64868, 51327747}, {64870, 51328515}, {64871, 51329283}, - {64873, 51330051}, {64874, 51330819}, {64876, 51331587}, {64878, 51332355}, - {64879, 51333123}, {64881, 51333891}, {64883, 51334659}, {64884, 51335427}, - {64885, 51336195}, {64886, 51336963}, {64888, 51337731}, {64889, 51338499}, - {64890, 51339267}, {64891, 51340035}, {64892, 51340803}, {64894, 51341571}, - {64895, 51342339}, {64896, 51343107}, {64897, 51343875}, {64898, 51344643}, - {64899, 51345411}, {64901, 51346179}, {64903, 51346947}, {64905, 51347715}, - {64906, 51247107}, {64907, 51348483}, {64908, 51349251}, {64909, 51270403}, - {64910, 51247619}, {64911, 51350019}, {64912, 2}, {64914, 51350787}, - {64915, 51351555}, {64916, 51352323}, {64917, 51353091}, {64918, 51353859}, - {64919, 51354627}, {64921, 51355395}, {64922, 51356163}, {64923, 51356931}, - {64924, 51357699}, {64926, 51358467}, {64927, 51359235}, {64928, 51360003}, - {64929, 51360771}, {64930, 51361539}, {64931, 51362307}, {64932, 51363075}, - {64933, 51363843}, {64934, 51364611}, {64935, 51365379}, {64936, 51366147}, - {64937, 51366915}, {64938, 51367683}, {64939, 51368451}, {64940, 51369219}, - {64941, 51369987}, {64942, 51277571}, {64943, 51370755}, {64944, 51371523}, - {64945, 51372291}, {64946, 51373059}, {64947, 51373827}, {64948, 51341571}, - {64949, 51343107}, {64950, 51374595}, {64951, 51375363}, {64952, 51376131}, - {64953, 51376899}, {64954, 51377667}, {64955, 51378435}, {64956, 51377667}, - {64957, 51376131}, {64958, 51379203}, {64959, 51379971}, {64960, 51380739}, - {64961, 51381507}, {64962, 51382275}, {64963, 51378435}, {64964, 51336195}, - {64965, 51328515}, {64966, 51383043}, {64967, 51383811}, {64968, 2}, - {64975, 1}, {64976, 2}, {65008, 51384579}, {65009, 51385347}, - {65010, 68163331}, {65011, 68164355}, {65012, 68165379}, {65013, 68166403}, - {65014, 68167427}, {65015, 68168451}, {65016, 68169475}, {65017, 51393283}, - {65018, 303052291}, {65019, 135284739}, {65020, 68177923}, {65021, 1}, - {65024, 0}, {65040, 17847299}, {65041, 17847555}, {65042, 2}, - {65043, 17110531}, {65044, 16848643}, {65045, 17032963}, {65046, 17033987}, - {65047, 17847811}, {65048, 17848067}, {65049, 2}, {65056, 1}, - {65072, 2}, {65073, 17848323}, {65074, 17848579}, {65075, 17848835}, - {65077, 17037827}, {65078, 17038083}, {65079, 17849091}, {65080, 17849347}, - {65081, 17849603}, {65082, 17849859}, {65083, 17850115}, {65084, 17850371}, - {65085, 17850627}, {65086, 17850883}, {65087, 17067267}, {65088, 17067523}, - {65089, 17851139}, {65090, 17851395}, {65091, 17851651}, {65092, 17851907}, - {65093, 1}, {65095, 17852163}, {65096, 17852419}, {65097, 33810691}, - {65101, 17848835}, {65104, 17847299}, {65105, 17847555}, {65106, 2}, - {65108, 16848643}, {65109, 17110531}, {65110, 17033987}, {65111, 17032963}, - {65112, 17848323}, {65113, 17037827}, {65114, 17038083}, {65115, 17849091}, - {65116, 17849347}, {65117, 17849603}, {65118, 17849859}, {65119, 17852675}, - {65120, 17852931}, {65121, 17853187}, {65122, 17037059}, {65123, 17853443}, - {65124, 17853699}, {65125, 17853955}, {65126, 17037571}, {65127, 2}, - {65128, 17854211}, {65129, 17854467}, {65130, 17854723}, {65131, 17854979}, - {65132, 2}, {65136, 34632451}, {65137, 34632963}, {65138, 34503427}, - {65139, 1}, {65140, 34504195}, {65141, 2}, {65142, 34504963}, - {65143, 34523395}, {65144, 34505731}, {65145, 34524163}, {65146, 34506499}, - {65147, 34524931}, {65148, 34507267}, {65149, 34633475}, {65150, 34633987}, - {65151, 34634499}, {65152, 17857795}, {65153, 17858051}, {65155, 17858307}, - {65157, 17858563}, {65159, 17858819}, {65161, 17677315}, {65165, 16910339}, - {65167, 17683715}, {65171, 17859075}, {65173, 17686787}, {65177, 17689859}, - {65181, 17681923}, {65185, 17682435}, {65189, 17684995}, {65193, 17834499}, - {65195, 17724675}, {65197, 17725187}, {65199, 17731587}, {65201, 17694979}, - {65205, 17745155}, {65209, 17697027}, {65213, 17698051}, {65217, 17700099}, - {65221, 17701123}, {65225, 17701635}, {65229, 17702659}, {65233, 17703683}, - {65237, 17706755}, {65241, 17708803}, {65245, 17711107}, {65249, 17682947}, - {65253, 17718019}, {65257, 17721091}, {65261, 16910851}, {65263, 17677059}, - {65265, 16911875}, {65269, 34636547}, {65271, 34637059}, {65273, 34637571}, - {65275, 34622467}, {65277, 2}, {65279, 0}, {65280, 2}, - {65281, 17032963}, {65282, 17860867}, {65283, 17852675}, {65284, 17854467}, - {65285, 17854723}, {65286, 17852931}, {65287, 17861123}, {65288, 17037827}, - {65289, 17038083}, {65290, 17853187}, {65291, 17037059}, {65292, 17847299}, - {65293, 17853443}, {65294, 17196547}, {65295, 17038595}, {65296, 17035523}, - {65297, 16786947}, {65298, 16785155}, {65299, 16785411}, {65300, 16787715}, - {65301, 17035779}, {65302, 17036035}, {65303, 17036291}, {65304, 17036547}, - {65305, 17036803}, {65306, 17110531}, {65307, 16848643}, {65308, 17853699}, - {65309, 17037571}, {65310, 17853955}, {65311, 17033987}, {65312, 17854979}, - {65313, 16777219}, {65314, 16777475}, {65315, 16777731}, {65316, 16777987}, - {65317, 16778243}, {65318, 16778499}, {65319, 16778755}, {65320, 16779011}, - {65321, 16779267}, {65322, 16779523}, {65323, 16779779}, {65324, 16780035}, - {65325, 16780291}, {65326, 16780547}, {65327, 16780803}, {65328, 16781059}, - {65329, 16781315}, {65330, 16781571}, {65331, 16781827}, {65332, 16782083}, - {65333, 16782339}, {65334, 16782595}, {65335, 16782851}, {65336, 16783107}, - {65337, 16783363}, {65338, 16783619}, {65339, 17852163}, {65340, 17854211}, - {65341, 17852419}, {65342, 17861379}, {65343, 17848835}, {65344, 17027075}, - {65345, 16777219}, {65346, 16777475}, {65347, 16777731}, {65348, 16777987}, - {65349, 16778243}, {65350, 16778499}, {65351, 16778755}, {65352, 16779011}, - {65353, 16779267}, {65354, 16779523}, {65355, 16779779}, {65356, 16780035}, - {65357, 16780291}, {65358, 16780547}, {65359, 16780803}, {65360, 16781059}, - {65361, 16781315}, {65362, 16781571}, {65363, 16781827}, {65364, 16782083}, - {65365, 16782339}, {65366, 16782595}, {65367, 16782851}, {65368, 16783107}, - {65369, 16783363}, {65370, 16783619}, {65371, 17849091}, {65372, 17861635}, - {65373, 17849347}, {65374, 17861891}, {65375, 17862147}, {65376, 17862403}, - {65377, 17196547}, {65378, 17851139}, {65379, 17851395}, {65380, 17847555}, - {65381, 17862659}, {65382, 17316867}, {65383, 17319427}, {65384, 17362435}, - {65385, 17862915}, {65386, 17363971}, {65387, 17323523}, {65388, 17863171}, - {65389, 17333763}, {65390, 17379587}, {65391, 17329155}, {65392, 17318147}, - {65393, 17305603}, {65394, 17305859}, {65395, 17306115}, {65396, 17306371}, - {65397, 17306627}, {65398, 17306883}, {65399, 17307139}, {65400, 17307395}, - {65401, 17307651}, {65402, 17199107}, {65403, 17307907}, {65404, 17308163}, - {65405, 17308419}, {65406, 17308675}, {65407, 17308931}, {65408, 17309187}, - {65409, 17309443}, {65410, 17309699}, {65411, 17309955}, {65412, 17199363}, - {65413, 17310211}, {65414, 17310467}, {65415, 17310723}, {65416, 17310979}, - {65417, 17311235}, {65418, 17311491}, {65419, 17311747}, {65420, 17312003}, - {65421, 17312259}, {65422, 17312515}, {65423, 17312771}, {65424, 17313027}, - {65425, 17313283}, {65426, 17313539}, {65427, 17313795}, {65428, 17314051}, - {65429, 17314307}, {65430, 17314563}, {65431, 17314819}, {65432, 17315075}, - {65433, 17315331}, {65434, 17315587}, {65435, 17315843}, {65436, 17316099}, - {65437, 17319939}, {65438, 17197827}, {65439, 17198339}, {65440, 2}, - {65441, 17199619}, {65442, 17199875}, {65443, 17200131}, {65444, 17200387}, - {65445, 17200643}, {65446, 17200899}, {65447, 17201155}, {65448, 17201411}, - {65449, 17201667}, {65450, 17201923}, {65451, 17202179}, {65452, 17202435}, - {65453, 17202691}, {65454, 17202947}, {65455, 17203203}, {65456, 17203459}, - {65457, 17203715}, {65458, 17203971}, {65459, 17204227}, {65460, 17204483}, - {65461, 17204739}, {65462, 17204995}, {65463, 17205251}, {65464, 17205507}, - {65465, 17205763}, {65466, 17206019}, {65467, 17206275}, {65468, 17206531}, - {65469, 17206787}, {65470, 17207043}, {65471, 2}, {65474, 17207299}, - {65475, 17207555}, {65476, 17207811}, {65477, 17208067}, {65478, 17208323}, - {65479, 17208579}, {65480, 2}, {65482, 17208835}, {65483, 17209091}, - {65484, 17209347}, {65485, 17209603}, {65486, 17209859}, {65487, 17210115}, - {65488, 2}, {65490, 17210371}, {65491, 17210627}, {65492, 17210883}, - {65493, 17211139}, {65494, 17211395}, {65495, 17211651}, {65496, 2}, - {65498, 17211907}, {65499, 17212163}, {65500, 17212419}, {65501, 2}, - {65504, 17863427}, {65505, 17863683}, {65506, 17863939}, {65507, 33561859}, - {65508, 17864195}, {65509, 17864451}, {65510, 17864707}, {65511, 2}, - {65512, 17864963}, {65513, 17865219}, {65514, 17865475}, {65515, 17865731}, - {65516, 17865987}, {65517, 17866243}, {65518, 17866499}, {65519, 2}, - {65536, 1}, {65548, 2}, {65549, 1}, {65575, 2}, - {65576, 1}, {65595, 2}, {65596, 1}, {65598, 2}, - {65599, 1}, {65614, 2}, {65616, 1}, {65630, 2}, - {65664, 1}, {65787, 2}, {65792, 1}, {65795, 2}, - {65799, 1}, {65844, 2}, {65847, 1}, {65935, 2}, - {65936, 1}, {65949, 2}, {65952, 1}, {65953, 2}, - {66000, 1}, {66046, 2}, {66176, 1}, {66205, 2}, - {66208, 1}, {66257, 2}, {66272, 1}, {66300, 2}, - {66304, 1}, {66340, 2}, {66349, 1}, {66379, 2}, - {66384, 1}, {66427, 2}, {66432, 1}, {66462, 2}, - {66463, 1}, {66500, 2}, {66504, 1}, {66518, 2}, - {66560, 17866755}, {66561, 17867011}, {66562, 17867267}, {66563, 17867523}, - {66564, 17867779}, {66565, 17868035}, {66566, 17868291}, {66567, 17868547}, - {66568, 17868803}, {66569, 17869059}, {66570, 17869315}, {66571, 17869571}, - {66572, 17869827}, {66573, 17870083}, {66574, 17870339}, {66575, 17870595}, - {66576, 17870851}, {66577, 17871107}, {66578, 17871363}, {66579, 17871619}, - {66580, 17871875}, {66581, 17872131}, {66582, 17872387}, {66583, 17872643}, - {66584, 17872899}, {66585, 17873155}, {66586, 17873411}, {66587, 17873667}, - {66588, 17873923}, {66589, 17874179}, {66590, 17874435}, {66591, 17874691}, - {66592, 17874947}, {66593, 17875203}, {66594, 17875459}, {66595, 17875715}, - {66596, 17875971}, {66597, 17876227}, {66598, 17876483}, {66599, 17876739}, - {66600, 1}, {66718, 2}, {66720, 1}, {66730, 2}, - {66736, 17876995}, {66737, 17877251}, {66738, 17877507}, {66739, 17877763}, - {66740, 17878019}, {66741, 17878275}, {66742, 17878531}, {66743, 17878787}, - {66744, 17879043}, {66745, 17879299}, {66746, 17879555}, {66747, 17879811}, - {66748, 17880067}, {66749, 17880323}, {66750, 17880579}, {66751, 17880835}, - {66752, 17881091}, {66753, 17881347}, {66754, 17881603}, {66755, 17881859}, - {66756, 17882115}, {66757, 17882371}, {66758, 17882627}, {66759, 17882883}, - {66760, 17883139}, {66761, 17883395}, {66762, 17883651}, {66763, 17883907}, - {66764, 17884163}, {66765, 17884419}, {66766, 17884675}, {66767, 17884931}, - {66768, 17885187}, {66769, 17885443}, {66770, 17885699}, {66771, 17885955}, - {66772, 2}, {66776, 1}, {66812, 2}, {66816, 1}, - {66856, 2}, {66864, 1}, {66916, 2}, {66927, 1}, - {66928, 17886211}, {66929, 17886467}, {66930, 17886723}, {66931, 17886979}, - {66932, 17887235}, {66933, 17887491}, {66934, 17887747}, {66935, 17888003}, - {66936, 17888259}, {66937, 17888515}, {66938, 17888771}, {66939, 2}, - {66940, 17889027}, {66941, 17889283}, {66942, 17889539}, {66943, 17889795}, - {66944, 17890051}, {66945, 17890307}, {66946, 17890563}, {66947, 17890819}, - {66948, 17891075}, {66949, 17891331}, {66950, 17891587}, {66951, 17891843}, - {66952, 17892099}, {66953, 17892355}, {66954, 17892611}, {66955, 2}, - {66956, 17892867}, {66957, 17893123}, {66958, 17893379}, {66959, 17893635}, - {66960, 17893891}, {66961, 17894147}, {66962, 17894403}, {66963, 2}, - {66964, 17894659}, {66965, 17894915}, {66966, 2}, {66967, 1}, - {66978, 2}, {66979, 1}, {66994, 2}, {66995, 1}, - {67002, 2}, {67003, 1}, {67005, 2}, {67072, 1}, - {67383, 2}, {67392, 1}, {67414, 2}, {67424, 1}, - {67432, 2}, {67456, 1}, {67457, 17895171}, {67458, 17895427}, - {67459, 16791043}, {67460, 17895683}, {67461, 16814083}, {67462, 2}, - {67463, 17895939}, {67464, 17896195}, {67465, 17896451}, {67466, 17896707}, - {67467, 16815363}, {67468, 16815619}, {67469, 17896963}, {67470, 17897219}, - {67471, 17897475}, {67472, 17897731}, {67473, 17897987}, {67474, 17898243}, - {67475, 16817155}, {67476, 17898499}, {67477, 16802051}, {67478, 17898755}, - {67479, 17899011}, {67480, 17899267}, {67481, 17899523}, {67482, 17899779}, - {67483, 17512963}, {67484, 17900035}, {67485, 17900291}, {67486, 17900547}, - {67487, 17900803}, {67488, 17901059}, {67489, 17901315}, {67490, 16795395}, - {67491, 17901571}, {67492, 17901827}, {67493, 16781315}, {67494, 17902083}, - {67495, 17902339}, {67496, 17125379}, {67497, 17902595}, {67498, 16819971}, - {67499, 17902851}, {67500, 17903107}, {67501, 17903363}, {67502, 17903619}, - {67503, 16820995}, {67504, 17903875}, {67505, 2}, {67506, 17904131}, - {67507, 17904387}, {67508, 17904643}, {67509, 17904899}, {67510, 17905155}, - {67511, 17905411}, {67512, 17905667}, {67513, 17905923}, {67514, 17906179}, - {67515, 2}, {67584, 1}, {67590, 2}, {67592, 1}, - {67593, 2}, {67594, 1}, {67638, 2}, {67639, 1}, - {67641, 2}, {67644, 1}, {67645, 2}, {67647, 1}, - {67670, 2}, {67671, 1}, {67743, 2}, {67751, 1}, - {67760, 2}, {67808, 1}, {67827, 2}, {67828, 1}, - {67830, 2}, {67835, 1}, {67868, 2}, {67871, 1}, - {67898, 2}, {67903, 1}, {67904, 2}, {67968, 1}, - {68024, 2}, {68028, 1}, {68048, 2}, {68050, 1}, - {68100, 2}, {68101, 1}, {68103, 2}, {68108, 1}, - {68116, 2}, {68117, 1}, {68120, 2}, {68121, 1}, - {68150, 2}, {68152, 1}, {68155, 2}, {68159, 1}, - {68169, 2}, {68176, 1}, {68185, 2}, {68192, 1}, - {68256, 2}, {68288, 1}, {68327, 2}, {68331, 1}, - {68343, 2}, {68352, 1}, {68406, 2}, {68409, 1}, - {68438, 2}, {68440, 1}, {68467, 2}, {68472, 1}, - {68498, 2}, {68505, 1}, {68509, 2}, {68521, 1}, - {68528, 2}, {68608, 1}, {68681, 2}, {68736, 17906435}, - {68737, 17906691}, {68738, 17906947}, {68739, 17907203}, {68740, 17907459}, - {68741, 17907715}, {68742, 17907971}, {68743, 17908227}, {68744, 17908483}, - {68745, 17908739}, {68746, 17908995}, {68747, 17909251}, {68748, 17909507}, - {68749, 17909763}, {68750, 17910019}, {68751, 17910275}, {68752, 17910531}, - {68753, 17910787}, {68754, 17911043}, {68755, 17911299}, {68756, 17911555}, - {68757, 17911811}, {68758, 17912067}, {68759, 17912323}, {68760, 17912579}, - {68761, 17912835}, {68762, 17913091}, {68763, 17913347}, {68764, 17913603}, - {68765, 17913859}, {68766, 17914115}, {68767, 17914371}, {68768, 17914627}, - {68769, 17914883}, {68770, 17915139}, {68771, 17915395}, {68772, 17915651}, - {68773, 17915907}, {68774, 17916163}, {68775, 17916419}, {68776, 17916675}, - {68777, 17916931}, {68778, 17917187}, {68779, 17917443}, {68780, 17917699}, - {68781, 17917955}, {68782, 17918211}, {68783, 17918467}, {68784, 17918723}, - {68785, 17918979}, {68786, 17919235}, {68787, 2}, {68800, 1}, - {68851, 2}, {68858, 1}, {68904, 2}, {68912, 1}, - {68922, 2}, {69216, 1}, {69247, 2}, {69248, 1}, - {69290, 2}, {69291, 1}, {69294, 2}, {69296, 1}, - {69298, 2}, {69373, 1}, {69416, 2}, {69424, 1}, - {69466, 2}, {69488, 1}, {69514, 2}, {69552, 1}, - {69580, 2}, {69600, 1}, {69623, 2}, {69632, 1}, - {69710, 2}, {69714, 1}, {69750, 2}, {69759, 1}, - {69821, 2}, {69822, 1}, {69827, 2}, {69840, 1}, - {69865, 2}, {69872, 1}, {69882, 2}, {69888, 1}, - {69941, 2}, {69942, 1}, {69960, 2}, {69968, 1}, - {70007, 2}, {70016, 1}, {70112, 2}, {70113, 1}, - {70133, 2}, {70144, 1}, {70162, 2}, {70163, 1}, - {70210, 2}, {70272, 1}, {70279, 2}, {70280, 1}, - {70281, 2}, {70282, 1}, {70286, 2}, {70287, 1}, - {70302, 2}, {70303, 1}, {70314, 2}, {70320, 1}, - {70379, 2}, {70384, 1}, {70394, 2}, {70400, 1}, - {70404, 2}, {70405, 1}, {70413, 2}, {70415, 1}, - {70417, 2}, {70419, 1}, {70441, 2}, {70442, 1}, - {70449, 2}, {70450, 1}, {70452, 2}, {70453, 1}, - {70458, 2}, {70459, 1}, {70469, 2}, {70471, 1}, - {70473, 2}, {70475, 1}, {70478, 2}, {70480, 1}, - {70481, 2}, {70487, 1}, {70488, 2}, {70493, 1}, - {70500, 2}, {70502, 1}, {70509, 2}, {70512, 1}, - {70517, 2}, {70656, 1}, {70748, 2}, {70749, 1}, - {70754, 2}, {70784, 1}, {70856, 2}, {70864, 1}, - {70874, 2}, {71040, 1}, {71094, 2}, {71096, 1}, - {71134, 2}, {71168, 1}, {71237, 2}, {71248, 1}, - {71258, 2}, {71264, 1}, {71277, 2}, {71296, 1}, - {71354, 2}, {71360, 1}, {71370, 2}, {71424, 1}, - {71451, 2}, {71453, 1}, {71468, 2}, {71472, 1}, - {71495, 2}, {71680, 1}, {71740, 2}, {71840, 17919491}, - {71841, 17919747}, {71842, 17920003}, {71843, 17920259}, {71844, 17920515}, - {71845, 17920771}, {71846, 17921027}, {71847, 17921283}, {71848, 17921539}, - {71849, 17921795}, {71850, 17922051}, {71851, 17922307}, {71852, 17922563}, - {71853, 17922819}, {71854, 17923075}, {71855, 17923331}, {71856, 17923587}, - {71857, 17923843}, {71858, 17924099}, {71859, 17924355}, {71860, 17924611}, - {71861, 17924867}, {71862, 17925123}, {71863, 17925379}, {71864, 17925635}, - {71865, 17925891}, {71866, 17926147}, {71867, 17926403}, {71868, 17926659}, - {71869, 17926915}, {71870, 17927171}, {71871, 17927427}, {71872, 1}, - {71923, 2}, {71935, 1}, {71943, 2}, {71945, 1}, - {71946, 2}, {71948, 1}, {71956, 2}, {71957, 1}, - {71959, 2}, {71960, 1}, {71990, 2}, {71991, 1}, - {71993, 2}, {71995, 1}, {72007, 2}, {72016, 1}, - {72026, 2}, {72096, 1}, {72104, 2}, {72106, 1}, - {72152, 2}, {72154, 1}, {72165, 2}, {72192, 1}, - {72264, 2}, {72272, 1}, {72355, 2}, {72368, 1}, - {72441, 2}, {72448, 1}, {72458, 2}, {72704, 1}, - {72713, 2}, {72714, 1}, {72759, 2}, {72760, 1}, - {72774, 2}, {72784, 1}, {72813, 2}, {72816, 1}, - {72848, 2}, {72850, 1}, {72872, 2}, {72873, 1}, - {72887, 2}, {72960, 1}, {72967, 2}, {72968, 1}, - {72970, 2}, {72971, 1}, {73015, 2}, {73018, 1}, - {73019, 2}, {73020, 1}, {73022, 2}, {73023, 1}, - {73032, 2}, {73040, 1}, {73050, 2}, {73056, 1}, - {73062, 2}, {73063, 1}, {73065, 2}, {73066, 1}, - {73103, 2}, {73104, 1}, {73106, 2}, {73107, 1}, - {73113, 2}, {73120, 1}, {73130, 2}, {73440, 1}, - {73465, 2}, {73472, 1}, {73489, 2}, {73490, 1}, - {73531, 2}, {73534, 1}, {73562, 2}, {73648, 1}, - {73649, 2}, {73664, 1}, {73714, 2}, {73727, 1}, - {74650, 2}, {74752, 1}, {74863, 2}, {74864, 1}, - {74869, 2}, {74880, 1}, {75076, 2}, {77712, 1}, - {77811, 2}, {77824, 1}, {78896, 2}, {78912, 1}, - {78934, 2}, {82944, 1}, {83527, 2}, {92160, 1}, - {92729, 2}, {92736, 1}, {92767, 2}, {92768, 1}, - {92778, 2}, {92782, 1}, {92863, 2}, {92864, 1}, - {92874, 2}, {92880, 1}, {92910, 2}, {92912, 1}, - {92918, 2}, {92928, 1}, {92998, 2}, {93008, 1}, - {93018, 2}, {93019, 1}, {93026, 2}, {93027, 1}, - {93048, 2}, {93053, 1}, {93072, 2}, {93760, 17927683}, - {93761, 17927939}, {93762, 17928195}, {93763, 17928451}, {93764, 17928707}, - {93765, 17928963}, {93766, 17929219}, {93767, 17929475}, {93768, 17929731}, - {93769, 17929987}, {93770, 17930243}, {93771, 17930499}, {93772, 17930755}, - {93773, 17931011}, {93774, 17931267}, {93775, 17931523}, {93776, 17931779}, - {93777, 17932035}, {93778, 17932291}, {93779, 17932547}, {93780, 17932803}, - {93781, 17933059}, {93782, 17933315}, {93783, 17933571}, {93784, 17933827}, - {93785, 17934083}, {93786, 17934339}, {93787, 17934595}, {93788, 17934851}, - {93789, 17935107}, {93790, 17935363}, {93791, 17935619}, {93792, 1}, - {93851, 2}, {93952, 1}, {94027, 2}, {94031, 1}, - {94088, 2}, {94095, 1}, {94112, 2}, {94176, 1}, - {94181, 2}, {94192, 1}, {94194, 2}, {94208, 1}, - {100344, 2}, {100352, 1}, {101590, 2}, {101632, 1}, - {101641, 2}, {110576, 1}, {110580, 2}, {110581, 1}, - {110588, 2}, {110589, 1}, {110591, 2}, {110592, 1}, - {110883, 2}, {110898, 1}, {110899, 2}, {110928, 1}, - {110931, 2}, {110933, 1}, {110934, 2}, {110948, 1}, - {110952, 2}, {110960, 1}, {111356, 2}, {113664, 1}, - {113771, 2}, {113776, 1}, {113789, 2}, {113792, 1}, - {113801, 2}, {113808, 1}, {113818, 2}, {113820, 1}, - {113824, 0}, {113828, 2}, {118528, 1}, {118574, 2}, - {118576, 1}, {118599, 2}, {118608, 1}, {118724, 2}, - {118784, 1}, {119030, 2}, {119040, 1}, {119079, 2}, - {119081, 1}, {119134, 34713091}, {119135, 34713603}, {119136, 51491331}, - {119137, 51492099}, {119138, 51492867}, {119139, 51493635}, {119140, 51494403}, - {119141, 1}, {119155, 2}, {119163, 1}, {119227, 34717955}, - {119228, 34718467}, {119229, 51496195}, {119230, 51496963}, {119231, 51497731}, - {119232, 51498499}, {119233, 1}, {119275, 2}, {119296, 1}, - {119366, 2}, {119488, 1}, {119508, 2}, {119520, 1}, - {119540, 2}, {119552, 1}, {119639, 2}, {119648, 1}, - {119673, 2}, {119808, 16777219}, {119809, 16777475}, {119810, 16777731}, - {119811, 16777987}, {119812, 16778243}, {119813, 16778499}, {119814, 16778755}, - {119815, 16779011}, {119816, 16779267}, {119817, 16779523}, {119818, 16779779}, - {119819, 16780035}, {119820, 16780291}, {119821, 16780547}, {119822, 16780803}, - {119823, 16781059}, {119824, 16781315}, {119825, 16781571}, {119826, 16781827}, - {119827, 16782083}, {119828, 16782339}, {119829, 16782595}, {119830, 16782851}, - {119831, 16783107}, {119832, 16783363}, {119833, 16783619}, {119834, 16777219}, - {119835, 16777475}, {119836, 16777731}, {119837, 16777987}, {119838, 16778243}, - {119839, 16778499}, {119840, 16778755}, {119841, 16779011}, {119842, 16779267}, - {119843, 16779523}, {119844, 16779779}, {119845, 16780035}, {119846, 16780291}, - {119847, 16780547}, {119848, 16780803}, {119849, 16781059}, {119850, 16781315}, - {119851, 16781571}, {119852, 16781827}, {119853, 16782083}, {119854, 16782339}, - {119855, 16782595}, {119856, 16782851}, {119857, 16783107}, {119858, 16783363}, - {119859, 16783619}, {119860, 16777219}, {119861, 16777475}, {119862, 16777731}, - {119863, 16777987}, {119864, 16778243}, {119865, 16778499}, {119866, 16778755}, - {119867, 16779011}, {119868, 16779267}, {119869, 16779523}, {119870, 16779779}, - {119871, 16780035}, {119872, 16780291}, {119873, 16780547}, {119874, 16780803}, - {119875, 16781059}, {119876, 16781315}, {119877, 16781571}, {119878, 16781827}, - {119879, 16782083}, {119880, 16782339}, {119881, 16782595}, {119882, 16782851}, - {119883, 16783107}, {119884, 16783363}, {119885, 16783619}, {119886, 16777219}, - {119887, 16777475}, {119888, 16777731}, {119889, 16777987}, {119890, 16778243}, - {119891, 16778499}, {119892, 16778755}, {119893, 2}, {119894, 16779267}, - {119895, 16779523}, {119896, 16779779}, {119897, 16780035}, {119898, 16780291}, - {119899, 16780547}, {119900, 16780803}, {119901, 16781059}, {119902, 16781315}, - {119903, 16781571}, {119904, 16781827}, {119905, 16782083}, {119906, 16782339}, - {119907, 16782595}, {119908, 16782851}, {119909, 16783107}, {119910, 16783363}, - {119911, 16783619}, {119912, 16777219}, {119913, 16777475}, {119914, 16777731}, - {119915, 16777987}, {119916, 16778243}, {119917, 16778499}, {119918, 16778755}, - {119919, 16779011}, {119920, 16779267}, {119921, 16779523}, {119922, 16779779}, - {119923, 16780035}, {119924, 16780291}, {119925, 16780547}, {119926, 16780803}, - {119927, 16781059}, {119928, 16781315}, {119929, 16781571}, {119930, 16781827}, - {119931, 16782083}, {119932, 16782339}, {119933, 16782595}, {119934, 16782851}, - {119935, 16783107}, {119936, 16783363}, {119937, 16783619}, {119938, 16777219}, - {119939, 16777475}, {119940, 16777731}, {119941, 16777987}, {119942, 16778243}, - {119943, 16778499}, {119944, 16778755}, {119945, 16779011}, {119946, 16779267}, - {119947, 16779523}, {119948, 16779779}, {119949, 16780035}, {119950, 16780291}, - {119951, 16780547}, {119952, 16780803}, {119953, 16781059}, {119954, 16781315}, - {119955, 16781571}, {119956, 16781827}, {119957, 16782083}, {119958, 16782339}, - {119959, 16782595}, {119960, 16782851}, {119961, 16783107}, {119962, 16783363}, - {119963, 16783619}, {119964, 16777219}, {119965, 2}, {119966, 16777731}, - {119967, 16777987}, {119968, 2}, {119970, 16778755}, {119971, 2}, - {119973, 16779523}, {119974, 16779779}, {119975, 2}, {119977, 16780547}, - {119978, 16780803}, {119979, 16781059}, {119980, 16781315}, {119981, 2}, - {119982, 16781827}, {119983, 16782083}, {119984, 16782339}, {119985, 16782595}, - {119986, 16782851}, {119987, 16783107}, {119988, 16783363}, {119989, 16783619}, - {119990, 16777219}, {119991, 16777475}, {119992, 16777731}, {119993, 16777987}, - {119994, 2}, {119995, 16778499}, {119996, 2}, {119997, 16779011}, - {119998, 16779267}, {119999, 16779523}, {120000, 16779779}, {120001, 16780035}, - {120002, 16780291}, {120003, 16780547}, {120004, 2}, {120005, 16781059}, - {120006, 16781315}, {120007, 16781571}, {120008, 16781827}, {120009, 16782083}, - {120010, 16782339}, {120011, 16782595}, {120012, 16782851}, {120013, 16783107}, - {120014, 16783363}, {120015, 16783619}, {120016, 16777219}, {120017, 16777475}, - {120018, 16777731}, {120019, 16777987}, {120020, 16778243}, {120021, 16778499}, - {120022, 16778755}, {120023, 16779011}, {120024, 16779267}, {120025, 16779523}, - {120026, 16779779}, {120027, 16780035}, {120028, 16780291}, {120029, 16780547}, - {120030, 16780803}, {120031, 16781059}, {120032, 16781315}, {120033, 16781571}, - {120034, 16781827}, {120035, 16782083}, {120036, 16782339}, {120037, 16782595}, - {120038, 16782851}, {120039, 16783107}, {120040, 16783363}, {120041, 16783619}, - {120042, 16777219}, {120043, 16777475}, {120044, 16777731}, {120045, 16777987}, - {120046, 16778243}, {120047, 16778499}, {120048, 16778755}, {120049, 16779011}, - {120050, 16779267}, {120051, 16779523}, {120052, 16779779}, {120053, 16780035}, - {120054, 16780291}, {120055, 16780547}, {120056, 16780803}, {120057, 16781059}, - {120058, 16781315}, {120059, 16781571}, {120060, 16781827}, {120061, 16782083}, - {120062, 16782339}, {120063, 16782595}, {120064, 16782851}, {120065, 16783107}, - {120066, 16783363}, {120067, 16783619}, {120068, 16777219}, {120069, 16777475}, - {120070, 2}, {120071, 16777987}, {120072, 16778243}, {120073, 16778499}, - {120074, 16778755}, {120075, 2}, {120077, 16779523}, {120078, 16779779}, - {120079, 16780035}, {120080, 16780291}, {120081, 16780547}, {120082, 16780803}, - {120083, 16781059}, {120084, 16781315}, {120085, 2}, {120086, 16781827}, - {120087, 16782083}, {120088, 16782339}, {120089, 16782595}, {120090, 16782851}, - {120091, 16783107}, {120092, 16783363}, {120093, 2}, {120094, 16777219}, - {120095, 16777475}, {120096, 16777731}, {120097, 16777987}, {120098, 16778243}, - {120099, 16778499}, {120100, 16778755}, {120101, 16779011}, {120102, 16779267}, - {120103, 16779523}, {120104, 16779779}, {120105, 16780035}, {120106, 16780291}, - {120107, 16780547}, {120108, 16780803}, {120109, 16781059}, {120110, 16781315}, - {120111, 16781571}, {120112, 16781827}, {120113, 16782083}, {120114, 16782339}, - {120115, 16782595}, {120116, 16782851}, {120117, 16783107}, {120118, 16783363}, - {120119, 16783619}, {120120, 16777219}, {120121, 16777475}, {120122, 2}, - {120123, 16777987}, {120124, 16778243}, {120125, 16778499}, {120126, 16778755}, - {120127, 2}, {120128, 16779267}, {120129, 16779523}, {120130, 16779779}, - {120131, 16780035}, {120132, 16780291}, {120133, 2}, {120134, 16780803}, - {120135, 2}, {120138, 16781827}, {120139, 16782083}, {120140, 16782339}, - {120141, 16782595}, {120142, 16782851}, {120143, 16783107}, {120144, 16783363}, - {120145, 2}, {120146, 16777219}, {120147, 16777475}, {120148, 16777731}, - {120149, 16777987}, {120150, 16778243}, {120151, 16778499}, {120152, 16778755}, - {120153, 16779011}, {120154, 16779267}, {120155, 16779523}, {120156, 16779779}, - {120157, 16780035}, {120158, 16780291}, {120159, 16780547}, {120160, 16780803}, - {120161, 16781059}, {120162, 16781315}, {120163, 16781571}, {120164, 16781827}, - {120165, 16782083}, {120166, 16782339}, {120167, 16782595}, {120168, 16782851}, - {120169, 16783107}, {120170, 16783363}, {120171, 16783619}, {120172, 16777219}, - {120173, 16777475}, {120174, 16777731}, {120175, 16777987}, {120176, 16778243}, - {120177, 16778499}, {120178, 16778755}, {120179, 16779011}, {120180, 16779267}, - {120181, 16779523}, {120182, 16779779}, {120183, 16780035}, {120184, 16780291}, - {120185, 16780547}, {120186, 16780803}, {120187, 16781059}, {120188, 16781315}, - {120189, 16781571}, {120190, 16781827}, {120191, 16782083}, {120192, 16782339}, - {120193, 16782595}, {120194, 16782851}, {120195, 16783107}, {120196, 16783363}, - {120197, 16783619}, {120198, 16777219}, {120199, 16777475}, {120200, 16777731}, - {120201, 16777987}, {120202, 16778243}, {120203, 16778499}, {120204, 16778755}, - {120205, 16779011}, {120206, 16779267}, {120207, 16779523}, {120208, 16779779}, - {120209, 16780035}, {120210, 16780291}, {120211, 16780547}, {120212, 16780803}, - {120213, 16781059}, {120214, 16781315}, {120215, 16781571}, {120216, 16781827}, - {120217, 16782083}, {120218, 16782339}, {120219, 16782595}, {120220, 16782851}, - {120221, 16783107}, {120222, 16783363}, {120223, 16783619}, {120224, 16777219}, - {120225, 16777475}, {120226, 16777731}, {120227, 16777987}, {120228, 16778243}, - {120229, 16778499}, {120230, 16778755}, {120231, 16779011}, {120232, 16779267}, - {120233, 16779523}, {120234, 16779779}, {120235, 16780035}, {120236, 16780291}, - {120237, 16780547}, {120238, 16780803}, {120239, 16781059}, {120240, 16781315}, - {120241, 16781571}, {120242, 16781827}, {120243, 16782083}, {120244, 16782339}, - {120245, 16782595}, {120246, 16782851}, {120247, 16783107}, {120248, 16783363}, - {120249, 16783619}, {120250, 16777219}, {120251, 16777475}, {120252, 16777731}, - {120253, 16777987}, {120254, 16778243}, {120255, 16778499}, {120256, 16778755}, - {120257, 16779011}, {120258, 16779267}, {120259, 16779523}, {120260, 16779779}, - {120261, 16780035}, {120262, 16780291}, {120263, 16780547}, {120264, 16780803}, - {120265, 16781059}, {120266, 16781315}, {120267, 16781571}, {120268, 16781827}, - {120269, 16782083}, {120270, 16782339}, {120271, 16782595}, {120272, 16782851}, - {120273, 16783107}, {120274, 16783363}, {120275, 16783619}, {120276, 16777219}, - {120277, 16777475}, {120278, 16777731}, {120279, 16777987}, {120280, 16778243}, - {120281, 16778499}, {120282, 16778755}, {120283, 16779011}, {120284, 16779267}, - {120285, 16779523}, {120286, 16779779}, {120287, 16780035}, {120288, 16780291}, - {120289, 16780547}, {120290, 16780803}, {120291, 16781059}, {120292, 16781315}, - {120293, 16781571}, {120294, 16781827}, {120295, 16782083}, {120296, 16782339}, - {120297, 16782595}, {120298, 16782851}, {120299, 16783107}, {120300, 16783363}, - {120301, 16783619}, {120302, 16777219}, {120303, 16777475}, {120304, 16777731}, - {120305, 16777987}, {120306, 16778243}, {120307, 16778499}, {120308, 16778755}, - {120309, 16779011}, {120310, 16779267}, {120311, 16779523}, {120312, 16779779}, - {120313, 16780035}, {120314, 16780291}, {120315, 16780547}, {120316, 16780803}, - {120317, 16781059}, {120318, 16781315}, {120319, 16781571}, {120320, 16781827}, - {120321, 16782083}, {120322, 16782339}, {120323, 16782595}, {120324, 16782851}, - {120325, 16783107}, {120326, 16783363}, {120327, 16783619}, {120328, 16777219}, - {120329, 16777475}, {120330, 16777731}, {120331, 16777987}, {120332, 16778243}, - {120333, 16778499}, {120334, 16778755}, {120335, 16779011}, {120336, 16779267}, - {120337, 16779523}, {120338, 16779779}, {120339, 16780035}, {120340, 16780291}, - {120341, 16780547}, {120342, 16780803}, {120343, 16781059}, {120344, 16781315}, - {120345, 16781571}, {120346, 16781827}, {120347, 16782083}, {120348, 16782339}, - {120349, 16782595}, {120350, 16782851}, {120351, 16783107}, {120352, 16783363}, - {120353, 16783619}, {120354, 16777219}, {120355, 16777475}, {120356, 16777731}, - {120357, 16777987}, {120358, 16778243}, {120359, 16778499}, {120360, 16778755}, - {120361, 16779011}, {120362, 16779267}, {120363, 16779523}, {120364, 16779779}, - {120365, 16780035}, {120366, 16780291}, {120367, 16780547}, {120368, 16780803}, - {120369, 16781059}, {120370, 16781315}, {120371, 16781571}, {120372, 16781827}, - {120373, 16782083}, {120374, 16782339}, {120375, 16782595}, {120376, 16782851}, - {120377, 16783107}, {120378, 16783363}, {120379, 16783619}, {120380, 16777219}, - {120381, 16777475}, {120382, 16777731}, {120383, 16777987}, {120384, 16778243}, - {120385, 16778499}, {120386, 16778755}, {120387, 16779011}, {120388, 16779267}, - {120389, 16779523}, {120390, 16779779}, {120391, 16780035}, {120392, 16780291}, - {120393, 16780547}, {120394, 16780803}, {120395, 16781059}, {120396, 16781315}, - {120397, 16781571}, {120398, 16781827}, {120399, 16782083}, {120400, 16782339}, - {120401, 16782595}, {120402, 16782851}, {120403, 16783107}, {120404, 16783363}, - {120405, 16783619}, {120406, 16777219}, {120407, 16777475}, {120408, 16777731}, - {120409, 16777987}, {120410, 16778243}, {120411, 16778499}, {120412, 16778755}, - {120413, 16779011}, {120414, 16779267}, {120415, 16779523}, {120416, 16779779}, - {120417, 16780035}, {120418, 16780291}, {120419, 16780547}, {120420, 16780803}, - {120421, 16781059}, {120422, 16781315}, {120423, 16781571}, {120424, 16781827}, - {120425, 16782083}, {120426, 16782339}, {120427, 16782595}, {120428, 16782851}, - {120429, 16783107}, {120430, 16783363}, {120431, 16783619}, {120432, 16777219}, - {120433, 16777475}, {120434, 16777731}, {120435, 16777987}, {120436, 16778243}, - {120437, 16778499}, {120438, 16778755}, {120439, 16779011}, {120440, 16779267}, - {120441, 16779523}, {120442, 16779779}, {120443, 16780035}, {120444, 16780291}, - {120445, 16780547}, {120446, 16780803}, {120447, 16781059}, {120448, 16781315}, - {120449, 16781571}, {120450, 16781827}, {120451, 16782083}, {120452, 16782339}, - {120453, 16782595}, {120454, 16782851}, {120455, 16783107}, {120456, 16783363}, - {120457, 16783619}, {120458, 16777219}, {120459, 16777475}, {120460, 16777731}, - {120461, 16777987}, {120462, 16778243}, {120463, 16778499}, {120464, 16778755}, - {120465, 16779011}, {120466, 16779267}, {120467, 16779523}, {120468, 16779779}, - {120469, 16780035}, {120470, 16780291}, {120471, 16780547}, {120472, 16780803}, - {120473, 16781059}, {120474, 16781315}, {120475, 16781571}, {120476, 16781827}, - {120477, 16782083}, {120478, 16782339}, {120479, 16782595}, {120480, 16782851}, - {120481, 16783107}, {120482, 16783363}, {120483, 16783619}, {120484, 17944835}, - {120485, 17945091}, {120486, 2}, {120488, 16851715}, {120489, 16851971}, - {120490, 16852227}, {120491, 16852483}, {120492, 16852739}, {120493, 16852995}, - {120494, 16853251}, {120495, 16853507}, {120496, 16846851}, {120497, 16853763}, - {120498, 16854019}, {120499, 16786179}, {120500, 16854275}, {120501, 16854531}, - {120502, 16854787}, {120503, 16855043}, {120504, 16855299}, {120505, 16853507}, - {120506, 16855555}, {120507, 16855811}, {120508, 16856067}, {120509, 16856323}, - {120510, 16856579}, {120511, 16856835}, {120512, 16857091}, {120513, 17945347}, - {120514, 16851715}, {120515, 16851971}, {120516, 16852227}, {120517, 16852483}, - {120518, 16852739}, {120519, 16852995}, {120520, 16853251}, {120521, 16853507}, - {120522, 16846851}, {120523, 16853763}, {120524, 16854019}, {120525, 16786179}, - {120526, 16854275}, {120527, 16854531}, {120528, 16854787}, {120529, 16855043}, - {120530, 16855299}, {120531, 16855555}, {120533, 16855811}, {120534, 16856067}, - {120535, 16856323}, {120536, 16856579}, {120537, 16856835}, {120538, 16857091}, - {120539, 17945603}, {120540, 16852739}, {120541, 16853507}, {120542, 16853763}, - {120543, 16856323}, {120544, 16855299}, {120545, 16855043}, {120546, 16851715}, - {120547, 16851971}, {120548, 16852227}, {120549, 16852483}, {120550, 16852739}, - {120551, 16852995}, {120552, 16853251}, {120553, 16853507}, {120554, 16846851}, - {120555, 16853763}, {120556, 16854019}, {120557, 16786179}, {120558, 16854275}, - {120559, 16854531}, {120560, 16854787}, {120561, 16855043}, {120562, 16855299}, - {120563, 16853507}, {120564, 16855555}, {120565, 16855811}, {120566, 16856067}, - {120567, 16856323}, {120568, 16856579}, {120569, 16856835}, {120570, 16857091}, - {120571, 17945347}, {120572, 16851715}, {120573, 16851971}, {120574, 16852227}, - {120575, 16852483}, {120576, 16852739}, {120577, 16852995}, {120578, 16853251}, - {120579, 16853507}, {120580, 16846851}, {120581, 16853763}, {120582, 16854019}, - {120583, 16786179}, {120584, 16854275}, {120585, 16854531}, {120586, 16854787}, - {120587, 16855043}, {120588, 16855299}, {120589, 16855555}, {120591, 16855811}, - {120592, 16856067}, {120593, 16856323}, {120594, 16856579}, {120595, 16856835}, - {120596, 16857091}, {120597, 17945603}, {120598, 16852739}, {120599, 16853507}, - {120600, 16853763}, {120601, 16856323}, {120602, 16855299}, {120603, 16855043}, - {120604, 16851715}, {120605, 16851971}, {120606, 16852227}, {120607, 16852483}, - {120608, 16852739}, {120609, 16852995}, {120610, 16853251}, {120611, 16853507}, - {120612, 16846851}, {120613, 16853763}, {120614, 16854019}, {120615, 16786179}, - {120616, 16854275}, {120617, 16854531}, {120618, 16854787}, {120619, 16855043}, - {120620, 16855299}, {120621, 16853507}, {120622, 16855555}, {120623, 16855811}, - {120624, 16856067}, {120625, 16856323}, {120626, 16856579}, {120627, 16856835}, - {120628, 16857091}, {120629, 17945347}, {120630, 16851715}, {120631, 16851971}, - {120632, 16852227}, {120633, 16852483}, {120634, 16852739}, {120635, 16852995}, - {120636, 16853251}, {120637, 16853507}, {120638, 16846851}, {120639, 16853763}, - {120640, 16854019}, {120641, 16786179}, {120642, 16854275}, {120643, 16854531}, - {120644, 16854787}, {120645, 16855043}, {120646, 16855299}, {120647, 16855555}, - {120649, 16855811}, {120650, 16856067}, {120651, 16856323}, {120652, 16856579}, - {120653, 16856835}, {120654, 16857091}, {120655, 17945603}, {120656, 16852739}, - {120657, 16853507}, {120658, 16853763}, {120659, 16856323}, {120660, 16855299}, - {120661, 16855043}, {120662, 16851715}, {120663, 16851971}, {120664, 16852227}, - {120665, 16852483}, {120666, 16852739}, {120667, 16852995}, {120668, 16853251}, - {120669, 16853507}, {120670, 16846851}, {120671, 16853763}, {120672, 16854019}, - {120673, 16786179}, {120674, 16854275}, {120675, 16854531}, {120676, 16854787}, - {120677, 16855043}, {120678, 16855299}, {120679, 16853507}, {120680, 16855555}, - {120681, 16855811}, {120682, 16856067}, {120683, 16856323}, {120684, 16856579}, - {120685, 16856835}, {120686, 16857091}, {120687, 17945347}, {120688, 16851715}, - {120689, 16851971}, {120690, 16852227}, {120691, 16852483}, {120692, 16852739}, - {120693, 16852995}, {120694, 16853251}, {120695, 16853507}, {120696, 16846851}, - {120697, 16853763}, {120698, 16854019}, {120699, 16786179}, {120700, 16854275}, - {120701, 16854531}, {120702, 16854787}, {120703, 16855043}, {120704, 16855299}, - {120705, 16855555}, {120707, 16855811}, {120708, 16856067}, {120709, 16856323}, - {120710, 16856579}, {120711, 16856835}, {120712, 16857091}, {120713, 17945603}, - {120714, 16852739}, {120715, 16853507}, {120716, 16853763}, {120717, 16856323}, - {120718, 16855299}, {120719, 16855043}, {120720, 16851715}, {120721, 16851971}, - {120722, 16852227}, {120723, 16852483}, {120724, 16852739}, {120725, 16852995}, - {120726, 16853251}, {120727, 16853507}, {120728, 16846851}, {120729, 16853763}, - {120730, 16854019}, {120731, 16786179}, {120732, 16854275}, {120733, 16854531}, - {120734, 16854787}, {120735, 16855043}, {120736, 16855299}, {120737, 16853507}, - {120738, 16855555}, {120739, 16855811}, {120740, 16856067}, {120741, 16856323}, - {120742, 16856579}, {120743, 16856835}, {120744, 16857091}, {120745, 17945347}, - {120746, 16851715}, {120747, 16851971}, {120748, 16852227}, {120749, 16852483}, - {120750, 16852739}, {120751, 16852995}, {120752, 16853251}, {120753, 16853507}, - {120754, 16846851}, {120755, 16853763}, {120756, 16854019}, {120757, 16786179}, - {120758, 16854275}, {120759, 16854531}, {120760, 16854787}, {120761, 16855043}, - {120762, 16855299}, {120763, 16855555}, {120765, 16855811}, {120766, 16856067}, - {120767, 16856323}, {120768, 16856579}, {120769, 16856835}, {120770, 16857091}, - {120771, 17945603}, {120772, 16852739}, {120773, 16853507}, {120774, 16853763}, - {120775, 16856323}, {120776, 16855299}, {120777, 16855043}, {120778, 16858627}, - {120780, 2}, {120782, 17035523}, {120783, 16786947}, {120784, 16785155}, - {120785, 16785411}, {120786, 16787715}, {120787, 17035779}, {120788, 17036035}, - {120789, 17036291}, {120790, 17036547}, {120791, 17036803}, {120792, 17035523}, - {120793, 16786947}, {120794, 16785155}, {120795, 16785411}, {120796, 16787715}, - {120797, 17035779}, {120798, 17036035}, {120799, 17036291}, {120800, 17036547}, - {120801, 17036803}, {120802, 17035523}, {120803, 16786947}, {120804, 16785155}, - {120805, 16785411}, {120806, 16787715}, {120807, 17035779}, {120808, 17036035}, - {120809, 17036291}, {120810, 17036547}, {120811, 17036803}, {120812, 17035523}, - {120813, 16786947}, {120814, 16785155}, {120815, 16785411}, {120816, 16787715}, - {120817, 17035779}, {120818, 17036035}, {120819, 17036291}, {120820, 17036547}, - {120821, 17036803}, {120822, 17035523}, {120823, 16786947}, {120824, 16785155}, - {120825, 16785411}, {120826, 16787715}, {120827, 17035779}, {120828, 17036035}, - {120829, 17036291}, {120830, 17036547}, {120831, 17036803}, {120832, 1}, - {121484, 2}, {121499, 1}, {121504, 2}, {121505, 1}, - {121520, 2}, {122624, 1}, {122655, 2}, {122661, 1}, - {122667, 2}, {122880, 1}, {122887, 2}, {122888, 1}, - {122905, 2}, {122907, 1}, {122914, 2}, {122915, 1}, - {122917, 2}, {122918, 1}, {122923, 2}, {122928, 16866563}, - {122929, 16866819}, {122930, 16867075}, {122931, 16867331}, {122932, 16867587}, - {122933, 16867843}, {122934, 16868099}, {122935, 16868355}, {122936, 16868611}, - {122937, 16869123}, {122938, 16869379}, {122939, 16869635}, {122940, 16870147}, - {122941, 16870403}, {122942, 16870659}, {122943, 16870915}, {122944, 16871171}, - {122945, 16871427}, {122946, 16871683}, {122947, 16871939}, {122948, 16872195}, - {122949, 16872451}, {122950, 16872707}, {122951, 16873475}, {122952, 16873987}, - {122953, 16874243}, {122954, 17495299}, {122955, 16888835}, {122956, 16864003}, - {122957, 16864515}, {122958, 16890883}, {122959, 16883715}, {122960, 17945859}, - {122961, 16866563}, {122962, 16866819}, {122963, 16867075}, {122964, 16867331}, - {122965, 16867587}, {122966, 16867843}, {122967, 16868099}, {122968, 16868355}, - {122969, 16868611}, {122970, 16869123}, {122971, 16869379}, {122972, 16870147}, - {122973, 16870403}, {122974, 16870915}, {122975, 16871427}, {122976, 16871683}, - {122977, 16871939}, {122978, 16872195}, {122979, 16872451}, {122980, 16872707}, - {122981, 16873219}, {122982, 16873475}, {122983, 16879875}, {122984, 16864003}, - {122985, 16863747}, {122986, 16866307}, {122987, 16883203}, {122988, 17490435}, - {122989, 16883971}, {122990, 2}, {123023, 1}, {123024, 2}, - {123136, 1}, {123181, 2}, {123184, 1}, {123198, 2}, - {123200, 1}, {123210, 2}, {123214, 1}, {123216, 2}, - {123536, 1}, {123567, 2}, {123584, 1}, {123642, 2}, - {123647, 1}, {123648, 2}, {124112, 1}, {124154, 2}, - {124896, 1}, {124903, 2}, {124904, 1}, {124908, 2}, - {124909, 1}, {124911, 2}, {124912, 1}, {124927, 2}, - {124928, 1}, {125125, 2}, {125127, 1}, {125143, 2}, - {125184, 17946115}, {125185, 17946371}, {125186, 17946627}, {125187, 17946883}, - {125188, 17947139}, {125189, 17947395}, {125190, 17947651}, {125191, 17947907}, - {125192, 17948163}, {125193, 17948419}, {125194, 17948675}, {125195, 17948931}, - {125196, 17949187}, {125197, 17949443}, {125198, 17949699}, {125199, 17949955}, - {125200, 17950211}, {125201, 17950467}, {125202, 17950723}, {125203, 17950979}, - {125204, 17951235}, {125205, 17951491}, {125206, 17951747}, {125207, 17952003}, - {125208, 17952259}, {125209, 17952515}, {125210, 17952771}, {125211, 17953027}, - {125212, 17953283}, {125213, 17953539}, {125214, 17953795}, {125215, 17954051}, - {125216, 17954307}, {125217, 17954563}, {125218, 1}, {125260, 2}, - {125264, 1}, {125274, 2}, {125278, 1}, {125280, 2}, - {126065, 1}, {126133, 2}, {126209, 1}, {126270, 2}, - {126464, 16910339}, {126465, 17683715}, {126466, 17681923}, {126467, 17834499}, - {126468, 2}, {126469, 16910851}, {126470, 17731587}, {126471, 17682435}, - {126472, 17700099}, {126473, 16911875}, {126474, 17708803}, {126475, 17711107}, - {126476, 17682947}, {126477, 17718019}, {126478, 17694979}, {126479, 17701635}, - {126480, 17703683}, {126481, 17697027}, {126482, 17706755}, {126483, 17725187}, - {126484, 17745155}, {126485, 17686787}, {126486, 17689859}, {126487, 17684995}, - {126488, 17724675}, {126489, 17698051}, {126490, 17701123}, {126491, 17702659}, - {126492, 17954819}, {126493, 17673475}, {126494, 17955075}, {126495, 17955331}, - {126496, 2}, {126497, 17683715}, {126498, 17681923}, {126499, 2}, - {126500, 17721091}, {126501, 2}, {126503, 17682435}, {126504, 2}, - {126505, 16911875}, {126506, 17708803}, {126507, 17711107}, {126508, 17682947}, - {126509, 17718019}, {126510, 17694979}, {126511, 17701635}, {126512, 17703683}, - {126513, 17697027}, {126514, 17706755}, {126515, 2}, {126516, 17745155}, - {126517, 17686787}, {126518, 17689859}, {126519, 17684995}, {126520, 2}, - {126521, 17698051}, {126522, 2}, {126523, 17702659}, {126524, 2}, - {126530, 17681923}, {126531, 2}, {126535, 17682435}, {126536, 2}, - {126537, 16911875}, {126538, 2}, {126539, 17711107}, {126540, 2}, - {126541, 17718019}, {126542, 17694979}, {126543, 17701635}, {126544, 2}, - {126545, 17697027}, {126546, 17706755}, {126547, 2}, {126548, 17745155}, - {126549, 2}, {126551, 17684995}, {126552, 2}, {126553, 17698051}, - {126554, 2}, {126555, 17702659}, {126556, 2}, {126557, 17673475}, - {126558, 2}, {126559, 17955331}, {126560, 2}, {126561, 17683715}, - {126562, 17681923}, {126563, 2}, {126564, 17721091}, {126565, 2}, - {126567, 17682435}, {126568, 17700099}, {126569, 16911875}, {126570, 17708803}, - {126571, 2}, {126572, 17682947}, {126573, 17718019}, {126574, 17694979}, - {126575, 17701635}, {126576, 17703683}, {126577, 17697027}, {126578, 17706755}, - {126579, 2}, {126580, 17745155}, {126581, 17686787}, {126582, 17689859}, - {126583, 17684995}, {126584, 2}, {126585, 17698051}, {126586, 17701123}, - {126587, 17702659}, {126588, 17954819}, {126589, 2}, {126590, 17955075}, - {126591, 2}, {126592, 16910339}, {126593, 17683715}, {126594, 17681923}, - {126595, 17834499}, {126596, 17721091}, {126597, 16910851}, {126598, 17731587}, - {126599, 17682435}, {126600, 17700099}, {126601, 16911875}, {126602, 2}, - {126603, 17711107}, {126604, 17682947}, {126605, 17718019}, {126606, 17694979}, - {126607, 17701635}, {126608, 17703683}, {126609, 17697027}, {126610, 17706755}, - {126611, 17725187}, {126612, 17745155}, {126613, 17686787}, {126614, 17689859}, - {126615, 17684995}, {126616, 17724675}, {126617, 17698051}, {126618, 17701123}, - {126619, 17702659}, {126620, 2}, {126625, 17683715}, {126626, 17681923}, - {126627, 17834499}, {126628, 2}, {126629, 16910851}, {126630, 17731587}, - {126631, 17682435}, {126632, 17700099}, {126633, 16911875}, {126634, 2}, - {126635, 17711107}, {126636, 17682947}, {126637, 17718019}, {126638, 17694979}, - {126639, 17701635}, {126640, 17703683}, {126641, 17697027}, {126642, 17706755}, - {126643, 17725187}, {126644, 17745155}, {126645, 17686787}, {126646, 17689859}, - {126647, 17684995}, {126648, 17724675}, {126649, 17698051}, {126650, 17701123}, - {126651, 17702659}, {126652, 2}, {126704, 1}, {126706, 2}, - {126976, 1}, {127020, 2}, {127024, 1}, {127124, 2}, - {127136, 1}, {127151, 2}, {127153, 1}, {127168, 2}, - {127169, 1}, {127184, 2}, {127185, 1}, {127222, 2}, - {127233, 34732803}, {127234, 34733315}, {127235, 34733827}, {127236, 34734339}, - {127237, 34734851}, {127238, 34735363}, {127239, 34735875}, {127240, 34736387}, - {127241, 34736899}, {127242, 34737411}, {127243, 1}, {127248, 50644995}, - {127249, 50645763}, {127250, 50646531}, {127251, 50647299}, {127252, 50648067}, - {127253, 50648835}, {127254, 50649603}, {127255, 50650371}, {127256, 50651139}, - {127257, 50651907}, {127258, 50652675}, {127259, 50653443}, {127260, 50654211}, - {127261, 50654979}, {127262, 50655747}, {127263, 50656515}, {127264, 50657283}, - {127265, 50658051}, {127266, 50658819}, {127267, 50659587}, {127268, 50660355}, - {127269, 50661123}, {127270, 50661891}, {127271, 50662659}, {127272, 50663427}, - {127273, 50664195}, {127274, 51515139}, {127275, 16777731}, {127276, 16781571}, - {127277, 33554947}, {127278, 34738691}, {127279, 1}, {127280, 16777219}, - {127281, 16777475}, {127282, 16777731}, {127283, 16777987}, {127284, 16778243}, - {127285, 16778499}, {127286, 16778755}, {127287, 16779011}, {127288, 16779267}, - {127289, 16779523}, {127290, 16779779}, {127291, 16780035}, {127292, 16780291}, - {127293, 16780547}, {127294, 16780803}, {127295, 16781059}, {127296, 16781315}, - {127297, 16781571}, {127298, 16781827}, {127299, 16782083}, {127300, 16782339}, - {127301, 16782595}, {127302, 16782851}, {127303, 16783107}, {127304, 16783363}, - {127305, 16783619}, {127306, 34739203}, {127307, 34226691}, {127308, 34739715}, - {127309, 33752579}, {127310, 51517443}, {127311, 34740995}, {127312, 1}, - {127338, 34209539}, {127339, 34189571}, {127340, 34741507}, {127341, 1}, - {127376, 34742019}, {127377, 1}, {127406, 2}, {127462, 1}, - {127488, 34742531}, {127489, 34743043}, {127490, 17307907}, {127491, 2}, - {127504, 17157891}, {127505, 17966339}, {127506, 17966595}, {127507, 17351683}, - {127508, 17143299}, {127509, 17966851}, {127510, 17967107}, {127511, 17225475}, - {127512, 17967363}, {127513, 17967619}, {127514, 17967875}, {127515, 17584643}, - {127516, 17968131}, {127517, 17968387}, {127518, 17968643}, {127519, 17968899}, - {127520, 17969155}, {127521, 17969411}, {127522, 17167107}, {127523, 17969667}, - {127524, 17969923}, {127525, 17970179}, {127526, 17970435}, {127527, 17970691}, - {127528, 17970947}, {127529, 17141763}, {127530, 17223427}, {127531, 17971203}, - {127532, 17288707}, {127533, 17224195}, {127534, 17288963}, {127535, 17971459}, - {127536, 17181443}, {127537, 17971715}, {127538, 17971971}, {127539, 17972227}, - {127540, 17972483}, {127541, 17972739}, {127542, 17264387}, {127543, 17160451}, - {127544, 17972995}, {127545, 17973251}, {127546, 17973507}, {127547, 17973763}, - {127548, 2}, {127552, 51528451}, {127553, 51529219}, {127554, 51529987}, - {127555, 51530755}, {127556, 51531523}, {127557, 51532291}, {127558, 51533059}, - {127559, 51533827}, {127560, 51534595}, {127561, 2}, {127568, 17980931}, - {127569, 17981187}, {127570, 2}, {127584, 1}, {127590, 2}, - {127744, 1}, {128728, 2}, {128732, 1}, {128749, 2}, - {128752, 1}, {128765, 2}, {128768, 1}, {128887, 2}, - {128891, 1}, {128986, 2}, {128992, 1}, {129004, 2}, - {129008, 1}, {129009, 2}, {129024, 1}, {129036, 2}, - {129040, 1}, {129096, 2}, {129104, 1}, {129114, 2}, - {129120, 1}, {129160, 2}, {129168, 1}, {129198, 2}, - {129200, 1}, {129202, 2}, {129280, 1}, {129620, 2}, - {129632, 1}, {129646, 2}, {129648, 1}, {129661, 2}, - {129664, 1}, {129673, 2}, {129680, 1}, {129726, 2}, - {129727, 1}, {129734, 2}, {129742, 1}, {129756, 2}, - {129760, 1}, {129769, 2}, {129776, 1}, {129785, 2}, - {129792, 1}, {129939, 2}, {129940, 1}, {129995, 2}, - {130032, 17035523}, {130033, 16786947}, {130034, 16785155}, {130035, 16785411}, - {130036, 16787715}, {130037, 17035779}, {130038, 17036035}, {130039, 17036291}, - {130040, 17036547}, {130041, 17036803}, {130042, 2}, {131072, 1}, + {7304, 16946435}, {7305, 16946691}, {7306, 1}, {7307, 2}, + {7312, 16946947}, {7313, 16947203}, {7314, 16947459}, {7315, 16947715}, + {7316, 16947971}, {7317, 16948227}, {7318, 16948483}, {7319, 16948739}, + {7320, 16948995}, {7321, 16949251}, {7322, 16949507}, {7323, 16949763}, + {7324, 16944643}, {7325, 16950019}, {7326, 16950275}, {7327, 16950531}, + {7328, 16950787}, {7329, 16951043}, {7330, 16951299}, {7331, 16951555}, + {7332, 16951811}, {7333, 16952067}, {7334, 16952323}, {7335, 16952579}, + {7336, 16952835}, {7337, 16953091}, {7338, 16953347}, {7339, 16953603}, + {7340, 16953859}, {7341, 16954115}, {7342, 16954371}, {7343, 16954627}, + {7344, 16954883}, {7345, 16955139}, {7346, 16955395}, {7347, 16955651}, + {7348, 16955907}, {7349, 16956163}, {7350, 16956419}, {7351, 16956675}, + {7352, 16956931}, {7353, 16957187}, {7354, 16957443}, {7355, 2}, + {7357, 16957699}, {7358, 16957955}, {7359, 16958211}, {7360, 1}, + {7368, 2}, {7376, 1}, {7419, 2}, {7424, 1}, + {7468, 16777219}, {7469, 16791043}, {7470, 16777475}, {7471, 1}, + {7472, 16777987}, {7473, 16778243}, {7474, 16816131}, {7475, 16778755}, + {7476, 16779011}, {7477, 16779267}, {7478, 16779523}, {7479, 16779779}, + {7480, 16780035}, {7481, 16780291}, {7482, 16780547}, {7483, 1}, + {7484, 16780803}, {7485, 16835843}, {7486, 16781059}, {7487, 16781571}, + {7488, 16782083}, {7489, 16782339}, {7490, 16782851}, {7491, 16777219}, + {7492, 16958467}, {7493, 16958723}, {7494, 16958979}, {7495, 16777475}, + {7496, 16777987}, {7497, 16778243}, {7498, 16816387}, {7499, 16816643}, + {7500, 16959235}, {7501, 16778755}, {7502, 1}, {7503, 16779779}, + {7504, 16780291}, {7505, 16807171}, {7506, 16780803}, {7507, 16814851}, + {7508, 16959491}, {7509, 16959747}, {7510, 16781059}, {7511, 16782083}, + {7512, 16782339}, {7513, 16960003}, {7514, 16818435}, {7515, 16782595}, + {7516, 16960259}, {7517, 16851971}, {7518, 16852227}, {7519, 16852483}, + {7520, 16856323}, {7521, 16856579}, {7522, 16779267}, {7523, 16781571}, + {7524, 16782339}, {7525, 16782595}, {7526, 16851971}, {7527, 16852227}, + {7528, 16855299}, {7529, 16856323}, {7530, 16856579}, {7531, 1}, + {7544, 16869891}, {7545, 1}, {7579, 16960515}, {7580, 16777731}, + {7581, 16960771}, {7582, 16793603}, {7583, 16959235}, {7584, 16778499}, + {7585, 16961027}, {7586, 16961283}, {7587, 16961539}, {7588, 16817923}, + {7589, 16817667}, {7590, 16961795}, {7591, 16962051}, {7592, 16962307}, + {7593, 16962563}, {7594, 16962819}, {7595, 16963075}, {7596, 16963331}, + {7597, 16963587}, {7598, 16818691}, {7599, 16963843}, {7600, 16964099}, + {7601, 16818947}, {7602, 16964355}, {7603, 16964611}, {7604, 16820483}, + {7605, 16964867}, {7606, 16839683}, {7607, 16821507}, {7608, 16965123}, + {7609, 16821763}, {7610, 16839939}, {7611, 16783619}, {7612, 16965379}, + {7613, 16965635}, {7614, 16822531}, {7615, 16853507}, {7616, 1}, + {7680, 16965891}, {7681, 1}, {7682, 16966147}, {7683, 1}, + {7684, 16966403}, {7685, 1}, {7686, 16966659}, {7687, 1}, + {7688, 16966915}, {7689, 1}, {7690, 16967171}, {7691, 1}, + {7692, 16967427}, {7693, 1}, {7694, 16967683}, {7695, 1}, + {7696, 16967939}, {7697, 1}, {7698, 16968195}, {7699, 1}, + {7700, 16968451}, {7701, 1}, {7702, 16968707}, {7703, 1}, + {7704, 16968963}, {7705, 1}, {7706, 16969219}, {7707, 1}, + {7708, 16969475}, {7709, 1}, {7710, 16969731}, {7711, 1}, + {7712, 16969987}, {7713, 1}, {7714, 16970243}, {7715, 1}, + {7716, 16970499}, {7717, 1}, {7718, 16970755}, {7719, 1}, + {7720, 16971011}, {7721, 1}, {7722, 16971267}, {7723, 1}, + {7724, 16971523}, {7725, 1}, {7726, 16971779}, {7727, 1}, + {7728, 16972035}, {7729, 1}, {7730, 16972291}, {7731, 1}, + {7732, 16972547}, {7733, 1}, {7734, 16972803}, {7735, 1}, + {7736, 16973059}, {7737, 1}, {7738, 16973315}, {7739, 1}, + {7740, 16973571}, {7741, 1}, {7742, 16973827}, {7743, 1}, + {7744, 16974083}, {7745, 1}, {7746, 16974339}, {7747, 1}, + {7748, 16974595}, {7749, 1}, {7750, 16974851}, {7751, 1}, + {7752, 16975107}, {7753, 1}, {7754, 16975363}, {7755, 1}, + {7756, 16975619}, {7757, 1}, {7758, 16975875}, {7759, 1}, + {7760, 16976131}, {7761, 1}, {7762, 16976387}, {7763, 1}, + {7764, 16976643}, {7765, 1}, {7766, 16976899}, {7767, 1}, + {7768, 16977155}, {7769, 1}, {7770, 16977411}, {7771, 1}, + {7772, 16977667}, {7773, 1}, {7774, 16977923}, {7775, 1}, + {7776, 16978179}, {7777, 1}, {7778, 16978435}, {7779, 1}, + {7780, 16978691}, {7781, 1}, {7782, 16978947}, {7783, 1}, + {7784, 16979203}, {7785, 1}, {7786, 16979459}, {7787, 1}, + {7788, 16979715}, {7789, 1}, {7790, 16979971}, {7791, 1}, + {7792, 16980227}, {7793, 1}, {7794, 16980483}, {7795, 1}, + {7796, 16980739}, {7797, 1}, {7798, 16980995}, {7799, 1}, + {7800, 16981251}, {7801, 1}, {7802, 16981507}, {7803, 1}, + {7804, 16981763}, {7805, 1}, {7806, 16982019}, {7807, 1}, + {7808, 16982275}, {7809, 1}, {7810, 16982531}, {7811, 1}, + {7812, 16982787}, {7813, 1}, {7814, 16983043}, {7815, 1}, + {7816, 16983299}, {7817, 1}, {7818, 16983555}, {7819, 1}, + {7820, 16983811}, {7821, 1}, {7822, 16984067}, {7823, 1}, + {7824, 16984323}, {7825, 1}, {7826, 16984579}, {7827, 1}, + {7828, 16984835}, {7829, 1}, {7834, 33762307}, {7835, 16978179}, + {7836, 1}, {7838, 16985603}, {7839, 1}, {7840, 16985859}, + {7841, 1}, {7842, 16986115}, {7843, 1}, {7844, 16986371}, + {7845, 1}, {7846, 16986627}, {7847, 1}, {7848, 16986883}, + {7849, 1}, {7850, 16987139}, {7851, 1}, {7852, 16987395}, + {7853, 1}, {7854, 16987651}, {7855, 1}, {7856, 16987907}, + {7857, 1}, {7858, 16988163}, {7859, 1}, {7860, 16988419}, + {7861, 1}, {7862, 16988675}, {7863, 1}, {7864, 16988931}, + {7865, 1}, {7866, 16989187}, {7867, 1}, {7868, 16989443}, + {7869, 1}, {7870, 16989699}, {7871, 1}, {7872, 16989955}, + {7873, 1}, {7874, 16990211}, {7875, 1}, {7876, 16990467}, + {7877, 1}, {7878, 16990723}, {7879, 1}, {7880, 16990979}, + {7881, 1}, {7882, 16991235}, {7883, 1}, {7884, 16991491}, + {7885, 1}, {7886, 16991747}, {7887, 1}, {7888, 16992003}, + {7889, 1}, {7890, 16992259}, {7891, 1}, {7892, 16992515}, + {7893, 1}, {7894, 16992771}, {7895, 1}, {7896, 16993027}, + {7897, 1}, {7898, 16993283}, {7899, 1}, {7900, 16993539}, + {7901, 1}, {7902, 16993795}, {7903, 1}, {7904, 16994051}, + {7905, 1}, {7906, 16994307}, {7907, 1}, {7908, 16994563}, + {7909, 1}, {7910, 16994819}, {7911, 1}, {7912, 16995075}, + {7913, 1}, {7914, 16995331}, {7915, 1}, {7916, 16995587}, + {7917, 1}, {7918, 16995843}, {7919, 1}, {7920, 16996099}, + {7921, 1}, {7922, 16996355}, {7923, 1}, {7924, 16996611}, + {7925, 1}, {7926, 16996867}, {7927, 1}, {7928, 16997123}, + {7929, 1}, {7930, 16997379}, {7931, 1}, {7932, 16997635}, + {7933, 1}, {7934, 16997891}, {7935, 1}, {7944, 16998147}, + {7945, 16998403}, {7946, 16998659}, {7947, 16998915}, {7948, 16999171}, + {7949, 16999427}, {7950, 16999683}, {7951, 16999939}, {7952, 1}, + {7958, 2}, {7960, 17000195}, {7961, 17000451}, {7962, 17000707}, + {7963, 17000963}, {7964, 17001219}, {7965, 17001475}, {7966, 2}, + {7968, 1}, {7976, 17001731}, {7977, 17001987}, {7978, 17002243}, + {7979, 17002499}, {7980, 17002755}, {7981, 17003011}, {7982, 17003267}, + {7983, 17003523}, {7984, 1}, {7992, 17003779}, {7993, 17004035}, + {7994, 17004291}, {7995, 17004547}, {7996, 17004803}, {7997, 17005059}, + {7998, 17005315}, {7999, 17005571}, {8000, 1}, {8006, 2}, + {8008, 17005827}, {8009, 17006083}, {8010, 17006339}, {8011, 17006595}, + {8012, 17006851}, {8013, 17007107}, {8014, 2}, {8016, 1}, + {8024, 2}, {8025, 17007363}, {8026, 2}, {8027, 17007619}, + {8028, 2}, {8029, 17007875}, {8030, 2}, {8031, 17008131}, + {8032, 1}, {8040, 17008387}, {8041, 17008643}, {8042, 17008899}, + {8043, 17009155}, {8044, 17009411}, {8045, 17009667}, {8046, 17009923}, + {8047, 17010179}, {8048, 1}, {8049, 16849923}, {8050, 1}, + {8051, 16850179}, {8052, 1}, {8053, 16850435}, {8054, 1}, + {8055, 16850691}, {8056, 1}, {8057, 16850947}, {8058, 1}, + {8059, 16851203}, {8060, 1}, {8061, 16851459}, {8062, 2}, + {8064, 33787651}, {8065, 33788163}, {8066, 33788675}, {8067, 33789187}, + {8068, 33789699}, {8069, 33790211}, {8070, 33790723}, {8071, 33791235}, + {8072, 33787651}, {8073, 33788163}, {8074, 33788675}, {8075, 33789187}, + {8076, 33789699}, {8077, 33790211}, {8078, 33790723}, {8079, 33791235}, + {8080, 33791747}, {8081, 33792259}, {8082, 33792771}, {8083, 33793283}, + {8084, 33793795}, {8085, 33794307}, {8086, 33794819}, {8087, 33795331}, + {8088, 33791747}, {8089, 33792259}, {8090, 33792771}, {8091, 33793283}, + {8092, 33793795}, {8093, 33794307}, {8094, 33794819}, {8095, 33795331}, + {8096, 33795843}, {8097, 33796355}, {8098, 33796867}, {8099, 33797379}, + {8100, 33797891}, {8101, 33798403}, {8102, 33798915}, {8103, 33799427}, + {8104, 33795843}, {8105, 33796355}, {8106, 33796867}, {8107, 33797379}, + {8108, 33797891}, {8109, 33798403}, {8110, 33798915}, {8111, 33799427}, + {8112, 1}, {8114, 33799939}, {8115, 33800451}, {8116, 33800963}, + {8117, 2}, {8118, 1}, {8119, 33801475}, {8120, 17024771}, + {8121, 17025027}, {8122, 17022723}, {8123, 16849923}, {8124, 33800451}, + {8125, 33802499}, {8126, 16846851}, {8127, 33802499}, {8128, 33803011}, + {8129, 50580739}, {8130, 33804291}, {8131, 33804803}, {8132, 33805315}, + {8133, 2}, {8134, 1}, {8135, 33805827}, {8136, 17029123}, + {8137, 16850179}, {8138, 17027075}, {8139, 16850435}, {8140, 33804803}, + {8141, 50583811}, {8142, 50584579}, {8143, 50585347}, {8144, 1}, + {8147, 17031683}, {8148, 2}, {8150, 1}, {8152, 17031939}, + {8153, 17032195}, {8154, 17032451}, {8155, 16850691}, {8156, 2}, + {8157, 50587139}, {8158, 50587907}, {8159, 50588675}, {8160, 1}, + {8163, 17035011}, {8164, 1}, {8168, 17035267}, {8169, 17035523}, + {8170, 17035779}, {8171, 16851203}, {8172, 17036035}, {8173, 50590723}, + {8174, 50403587}, {8175, 17037059}, {8176, 2}, {8178, 33814531}, + {8179, 33815043}, {8180, 33815555}, {8181, 2}, {8182, 1}, + {8183, 33816067}, {8184, 17039363}, {8185, 16850947}, {8186, 17037315}, + {8187, 16851459}, {8188, 33815043}, {8189, 33562883}, {8190, 33809923}, + {8191, 2}, {8192, 16783875}, {8203, 0}, {8204, 1}, + {8206, 2}, {8208, 1}, {8209, 17039619}, {8210, 1}, + {8215, 33817091}, {8216, 1}, {8228, 2}, {8231, 1}, + {8232, 2}, {8239, 16783875}, {8240, 1}, {8243, 33817603}, + {8244, 50595331}, {8245, 1}, {8246, 33818883}, {8247, 50596611}, + {8248, 1}, {8252, 33820163}, {8253, 1}, {8254, 33820675}, + {8255, 1}, {8263, 33821187}, {8264, 33821699}, {8265, 33822211}, + {8266, 1}, {8279, 67372035}, {8280, 1}, {8287, 16783875}, + {8288, 0}, {8293, 2}, {8298, 0}, {8304, 17045507}, + {8305, 16779267}, {8306, 2}, {8308, 16787715}, {8309, 17045763}, + {8310, 17046019}, {8311, 17046275}, {8312, 17046531}, {8313, 17046787}, + {8314, 17047043}, {8315, 17047299}, {8316, 17047555}, {8317, 17047811}, + {8318, 17048067}, {8319, 16780547}, {8320, 17045507}, {8321, 16786947}, + {8322, 16785155}, {8323, 16785411}, {8324, 16787715}, {8325, 17045763}, + {8326, 17046019}, {8327, 17046275}, {8328, 17046531}, {8329, 17046787}, + {8330, 17047043}, {8331, 17047299}, {8332, 17047555}, {8333, 17047811}, + {8334, 17048067}, {8335, 2}, {8336, 16777219}, {8337, 16778243}, + {8338, 16780803}, {8339, 16783107}, {8340, 16816387}, {8341, 16779011}, + {8342, 16779779}, {8343, 16780035}, {8344, 16780291}, {8345, 16780547}, + {8346, 16781059}, {8347, 16781827}, {8348, 16782083}, {8349, 2}, + {8352, 1}, {8360, 33558787}, {8361, 1}, {8385, 2}, + {8400, 1}, {8433, 2}, {8448, 50602755}, {8449, 50603523}, + {8450, 16777731}, {8451, 33827075}, {8452, 1}, {8453, 50604803}, + {8454, 50605571}, {8455, 16816643}, {8456, 1}, {8457, 33829123}, + {8458, 16778755}, {8459, 16779011}, {8463, 16802051}, {8464, 16779267}, + {8466, 16780035}, {8468, 1}, {8469, 16780547}, {8470, 33557763}, + {8471, 1}, {8473, 16781059}, {8474, 16781315}, {8475, 16781571}, + {8478, 1}, {8480, 33829635}, {8481, 50607363}, {8482, 33830915}, + {8483, 1}, {8484, 16783619}, {8485, 1}, {8486, 16857091}, + {8487, 1}, {8488, 16783619}, {8489, 1}, {8490, 16779779}, + {8491, 16790787}, {8492, 16777475}, {8493, 16777731}, {8494, 1}, + {8495, 16778243}, {8497, 16778499}, {8498, 17054211}, {8499, 16780291}, + {8500, 16780803}, {8501, 17054467}, {8502, 17054723}, {8503, 17054979}, + {8504, 17055235}, {8505, 16779267}, {8506, 1}, {8507, 50609923}, + {8508, 16855043}, {8509, 16852227}, {8511, 16855043}, {8512, 17056259}, + {8513, 1}, {8517, 16777987}, {8519, 16778243}, {8520, 16779267}, + {8521, 16779523}, {8522, 1}, {8528, 50610947}, {8529, 50611715}, + {8530, 67389699}, {8531, 50613507}, {8532, 50614275}, {8533, 50615043}, + {8534, 50615811}, {8535, 50616579}, {8536, 50617347}, {8537, 50618115}, + {8538, 50618883}, {8539, 50619651}, {8540, 50620419}, {8541, 50621187}, + {8542, 50621955}, {8543, 33564419}, {8544, 16779267}, {8545, 33845507}, + {8546, 50623235}, {8547, 33846787}, {8548, 16782595}, {8549, 33847299}, + {8550, 50625027}, {8551, 67403011}, {8552, 33849603}, {8553, 16783107}, + {8554, 33850115}, {8555, 50627843}, {8556, 16780035}, {8557, 16777731}, + {8558, 16777987}, {8559, 16780291}, {8560, 16779267}, {8561, 33845507}, + {8562, 50622723}, {8563, 33846787}, {8564, 16782595}, {8565, 33847299}, + {8566, 50625027}, {8567, 67403011}, {8568, 33849603}, {8569, 16783107}, + {8570, 33850115}, {8571, 50627843}, {8572, 16780035}, {8573, 16777731}, + {8574, 16777987}, {8575, 16780291}, {8576, 1}, {8579, 17074179}, + {8580, 1}, {8585, 50628867}, {8586, 1}, {8588, 2}, + {8592, 1}, {8748, 33852419}, {8749, 50630147}, {8750, 1}, + {8751, 33853699}, {8752, 50631427}, {8753, 1}, {9001, 17077763}, + {9002, 17078019}, {9003, 1}, {9258, 2}, {9280, 1}, + {9291, 2}, {9312, 16786947}, {9313, 16785155}, {9314, 16785411}, + {9315, 16787715}, {9316, 17045763}, {9317, 17046019}, {9318, 17046275}, + {9319, 17046531}, {9320, 17046787}, {9321, 33835779}, {9322, 33564163}, + {9323, 33855491}, {9324, 33856003}, {9325, 33856515}, {9326, 33857027}, + {9327, 33857539}, {9328, 33858051}, {9329, 33858563}, {9330, 33859075}, + {9331, 33859587}, {9332, 50637315}, {9333, 50638083}, {9334, 50638851}, + {9335, 50639619}, {9336, 50640387}, {9337, 50641155}, {9338, 50641923}, + {9339, 50642691}, {9340, 50643459}, {9341, 67421443}, {9342, 67422467}, + {9343, 67423491}, {9344, 67424515}, {9345, 67425539}, {9346, 67426563}, + {9347, 67427587}, {9348, 67428611}, {9349, 67429635}, {9350, 67430659}, + {9351, 67431683}, {9352, 2}, {9372, 50655491}, {9373, 50656259}, + {9374, 50657027}, {9375, 50657795}, {9376, 50658563}, {9377, 50659331}, + {9378, 50660099}, {9379, 50660867}, {9380, 50661635}, {9381, 50662403}, + {9382, 50663171}, {9383, 50663939}, {9384, 50664707}, {9385, 50665475}, + {9386, 50666243}, {9387, 50667011}, {9388, 50667779}, {9389, 50668547}, + {9390, 50669315}, {9391, 50670083}, {9392, 50670851}, {9393, 50671619}, + {9394, 50672387}, {9395, 50673155}, {9396, 50673923}, {9397, 50674691}, + {9398, 16777219}, {9399, 16777475}, {9400, 16777731}, {9401, 16777987}, + {9402, 16778243}, {9403, 16778499}, {9404, 16778755}, {9405, 16779011}, + {9406, 16779267}, {9407, 16779523}, {9408, 16779779}, {9409, 16780035}, + {9410, 16780291}, {9411, 16780547}, {9412, 16780803}, {9413, 16781059}, + {9414, 16781315}, {9415, 16781571}, {9416, 16781827}, {9417, 16782083}, + {9418, 16782339}, {9419, 16782595}, {9420, 16782851}, {9421, 16783107}, + {9422, 16783363}, {9423, 16783619}, {9424, 16777219}, {9425, 16777475}, + {9426, 16777731}, {9427, 16777987}, {9428, 16778243}, {9429, 16778499}, + {9430, 16778755}, {9431, 16779011}, {9432, 16779267}, {9433, 16779523}, + {9434, 16779779}, {9435, 16780035}, {9436, 16780291}, {9437, 16780547}, + {9438, 16780803}, {9439, 16781059}, {9440, 16781315}, {9441, 16781571}, + {9442, 16781827}, {9443, 16782083}, {9444, 16782339}, {9445, 16782595}, + {9446, 16782851}, {9447, 16783107}, {9448, 16783363}, {9449, 16783619}, + {9450, 17045507}, {9451, 1}, {10764, 67406851}, {10765, 1}, + {10868, 50675459}, {10869, 33899011}, {10870, 50675971}, {10871, 1}, + {10972, 33899523}, {10973, 1}, {11124, 2}, {11126, 1}, + {11158, 2}, {11159, 1}, {11264, 17122819}, {11265, 17123075}, + {11266, 17123331}, {11267, 17123587}, {11268, 17123843}, {11269, 17124099}, + {11270, 17124355}, {11271, 17124611}, {11272, 17124867}, {11273, 17125123}, + {11274, 17125379}, {11275, 17125635}, {11276, 17125891}, {11277, 17126147}, + {11278, 17126403}, {11279, 17126659}, {11280, 17126915}, {11281, 17127171}, + {11282, 17127427}, {11283, 17127683}, {11284, 17127939}, {11285, 17128195}, + {11286, 17128451}, {11287, 17128707}, {11288, 17128963}, {11289, 17129219}, + {11290, 17129475}, {11291, 17129731}, {11292, 17129987}, {11293, 17130243}, + {11294, 17130499}, {11295, 17130755}, {11296, 17131011}, {11297, 17131267}, + {11298, 17131523}, {11299, 17131779}, {11300, 17132035}, {11301, 17132291}, + {11302, 17132547}, {11303, 17132803}, {11304, 17133059}, {11305, 17133315}, + {11306, 17133571}, {11307, 17133827}, {11308, 17134083}, {11309, 17134339}, + {11310, 17134595}, {11311, 17134851}, {11312, 1}, {11360, 17135107}, + {11361, 1}, {11362, 17135363}, {11363, 17135619}, {11364, 17135875}, + {11365, 1}, {11367, 17136131}, {11368, 1}, {11369, 17136387}, + {11370, 1}, {11371, 17136643}, {11372, 1}, {11373, 16958723}, + {11374, 16963331}, {11375, 16958467}, {11376, 16960515}, {11377, 1}, + {11378, 17136899}, {11379, 1}, {11381, 17137155}, {11382, 1}, + {11388, 16779523}, {11389, 16782595}, {11390, 17137411}, {11391, 17137667}, + {11392, 17137923}, {11393, 1}, {11394, 17138179}, {11395, 1}, + {11396, 17138435}, {11397, 1}, {11398, 17138691}, {11399, 1}, + {11400, 17138947}, {11401, 1}, {11402, 17139203}, {11403, 1}, + {11404, 17139459}, {11405, 1}, {11406, 17139715}, {11407, 1}, + {11408, 17139971}, {11409, 1}, {11410, 17140227}, {11411, 1}, + {11412, 17140483}, {11413, 1}, {11414, 17140739}, {11415, 1}, + {11416, 17140995}, {11417, 1}, {11418, 17141251}, {11419, 1}, + {11420, 17141507}, {11421, 1}, {11422, 17141763}, {11423, 1}, + {11424, 17142019}, {11425, 1}, {11426, 17142275}, {11427, 1}, + {11428, 17142531}, {11429, 1}, {11430, 17142787}, {11431, 1}, + {11432, 17143043}, {11433, 1}, {11434, 17143299}, {11435, 1}, + {11436, 17143555}, {11437, 1}, {11438, 17143811}, {11439, 1}, + {11440, 17144067}, {11441, 1}, {11442, 17144323}, {11443, 1}, + {11444, 17144579}, {11445, 1}, {11446, 17144835}, {11447, 1}, + {11448, 17145091}, {11449, 1}, {11450, 17145347}, {11451, 1}, + {11452, 17145603}, {11453, 1}, {11454, 17145859}, {11455, 1}, + {11456, 17146115}, {11457, 1}, {11458, 17146371}, {11459, 1}, + {11460, 17146627}, {11461, 1}, {11462, 17146883}, {11463, 1}, + {11464, 17147139}, {11465, 1}, {11466, 17147395}, {11467, 1}, + {11468, 17147651}, {11469, 1}, {11470, 17147907}, {11471, 1}, + {11472, 17148163}, {11473, 1}, {11474, 17148419}, {11475, 1}, + {11476, 17148675}, {11477, 1}, {11478, 17148931}, {11479, 1}, + {11480, 17149187}, {11481, 1}, {11482, 17149443}, {11483, 1}, + {11484, 17149699}, {11485, 1}, {11486, 17149955}, {11487, 1}, + {11488, 17150211}, {11489, 1}, {11490, 17150467}, {11491, 1}, + {11499, 17150723}, {11500, 1}, {11501, 17150979}, {11502, 1}, + {11506, 17151235}, {11507, 1}, {11508, 2}, {11513, 1}, + {11558, 2}, {11559, 1}, {11560, 2}, {11565, 1}, + {11566, 2}, {11568, 1}, {11624, 2}, {11631, 17151491}, + {11632, 1}, {11633, 2}, {11647, 1}, {11671, 2}, + {11680, 1}, {11687, 2}, {11688, 1}, {11695, 2}, + {11696, 1}, {11703, 2}, {11704, 1}, {11711, 2}, + {11712, 1}, {11719, 2}, {11720, 1}, {11727, 2}, + {11728, 1}, {11735, 2}, {11736, 1}, {11743, 2}, + {11744, 1}, {11870, 2}, {11904, 1}, {11930, 2}, + {11931, 1}, {11935, 17151747}, {11936, 1}, {12019, 17152003}, + {12020, 2}, {12032, 17152259}, {12033, 17152515}, {12034, 17152771}, + {12035, 17153027}, {12036, 17153283}, {12037, 17153539}, {12038, 17153795}, + {12039, 17154051}, {12040, 17154307}, {12041, 17154563}, {12042, 17154819}, + {12043, 17155075}, {12044, 17155331}, {12045, 17155587}, {12046, 17155843}, + {12047, 17156099}, {12048, 17156355}, {12049, 17156611}, {12050, 17156867}, + {12051, 17157123}, {12052, 17157379}, {12053, 17157635}, {12054, 17157891}, + {12055, 17158147}, {12056, 17158403}, {12057, 17158659}, {12058, 17158915}, + {12059, 17159171}, {12060, 17159427}, {12061, 17159683}, {12062, 17159939}, + {12063, 17160195}, {12064, 17160451}, {12065, 17160707}, {12066, 17160963}, + {12067, 17161219}, {12068, 17161475}, {12069, 17161731}, {12070, 17161987}, + {12071, 17162243}, {12072, 17162499}, {12073, 17162755}, {12074, 17163011}, + {12075, 17163267}, {12076, 17163523}, {12077, 17163779}, {12078, 17164035}, + {12079, 17164291}, {12080, 17164547}, {12081, 17164803}, {12082, 17165059}, + {12083, 17165315}, {12084, 17165571}, {12085, 17165827}, {12086, 17166083}, + {12087, 17166339}, {12088, 17166595}, {12089, 17166851}, {12090, 17167107}, + {12091, 17167363}, {12092, 17167619}, {12093, 17167875}, {12094, 17168131}, + {12095, 17168387}, {12096, 17168643}, {12097, 17168899}, {12098, 17169155}, + {12099, 17169411}, {12100, 17169667}, {12101, 17169923}, {12102, 17170179}, + {12103, 17170435}, {12104, 17170691}, {12105, 17170947}, {12106, 17171203}, + {12107, 17171459}, {12108, 17171715}, {12109, 17171971}, {12110, 17172227}, + {12111, 17172483}, {12112, 17172739}, {12113, 17172995}, {12114, 17173251}, + {12115, 17173507}, {12116, 17173763}, {12117, 17174019}, {12118, 17174275}, + {12119, 17174531}, {12120, 17174787}, {12121, 17175043}, {12122, 17175299}, + {12123, 17175555}, {12124, 17175811}, {12125, 17176067}, {12126, 17176323}, + {12127, 17176579}, {12128, 17176835}, {12129, 17177091}, {12130, 17177347}, + {12131, 17177603}, {12132, 17177859}, {12133, 17178115}, {12134, 17178371}, + {12135, 17178627}, {12136, 17178883}, {12137, 17179139}, {12138, 17179395}, + {12139, 17179651}, {12140, 17179907}, {12141, 17180163}, {12142, 17180419}, + {12143, 17180675}, {12144, 17180931}, {12145, 17181187}, {12146, 17181443}, + {12147, 17181699}, {12148, 17181955}, {12149, 17182211}, {12150, 17182467}, + {12151, 17182723}, {12152, 17182979}, {12153, 17183235}, {12154, 17183491}, + {12155, 17183747}, {12156, 17184003}, {12157, 17184259}, {12158, 17184515}, + {12159, 17184771}, {12160, 17185027}, {12161, 17185283}, {12162, 17185539}, + {12163, 17185795}, {12164, 17186051}, {12165, 17186307}, {12166, 17186563}, + {12167, 17186819}, {12168, 17187075}, {12169, 17187331}, {12170, 17187587}, + {12171, 17187843}, {12172, 17188099}, {12173, 17188355}, {12174, 17188611}, + {12175, 17188867}, {12176, 17189123}, {12177, 17189379}, {12178, 17189635}, + {12179, 17189891}, {12180, 17190147}, {12181, 17190403}, {12182, 17190659}, + {12183, 17190915}, {12184, 17191171}, {12185, 17191427}, {12186, 17191683}, + {12187, 17191939}, {12188, 17192195}, {12189, 17192451}, {12190, 17192707}, + {12191, 17192963}, {12192, 17193219}, {12193, 17193475}, {12194, 17193731}, + {12195, 17193987}, {12196, 17194243}, {12197, 17194499}, {12198, 17194755}, + {12199, 17195011}, {12200, 17195267}, {12201, 17195523}, {12202, 17195779}, + {12203, 17196035}, {12204, 17196291}, {12205, 17196547}, {12206, 17196803}, + {12207, 17197059}, {12208, 17197315}, {12209, 17197571}, {12210, 17197827}, + {12211, 17198083}, {12212, 17198339}, {12213, 17198595}, {12214, 17198851}, + {12215, 17199107}, {12216, 17199363}, {12217, 17199619}, {12218, 17199875}, + {12219, 17200131}, {12220, 17200387}, {12221, 17200643}, {12222, 17200899}, + {12223, 17201155}, {12224, 17201411}, {12225, 17201667}, {12226, 17201923}, + {12227, 17202179}, {12228, 17202435}, {12229, 17202691}, {12230, 17202947}, + {12231, 17203203}, {12232, 17203459}, {12233, 17203715}, {12234, 17203971}, + {12235, 17204227}, {12236, 17204483}, {12237, 17204739}, {12238, 17204995}, + {12239, 17205251}, {12240, 17205507}, {12241, 17205763}, {12242, 17206019}, + {12243, 17206275}, {12244, 17206531}, {12245, 17206787}, {12246, 2}, + {12288, 16783875}, {12289, 1}, {12290, 17207043}, {12291, 1}, + {12342, 17207299}, {12343, 1}, {12344, 17158147}, {12345, 17207555}, + {12346, 17207811}, {12347, 1}, {12352, 2}, {12353, 1}, + {12439, 2}, {12441, 1}, {12443, 33985283}, {12444, 33985795}, + {12445, 1}, {12447, 33986307}, {12448, 1}, {12543, 33986819}, + {12544, 2}, {12549, 1}, {12592, 2}, {12593, 17210115}, + {12594, 17210371}, {12595, 17210627}, {12596, 17210883}, {12597, 17211139}, + {12598, 17211395}, {12599, 17211651}, {12600, 17211907}, {12601, 17212163}, + {12602, 17212419}, {12603, 17212675}, {12604, 17212931}, {12605, 17213187}, + {12606, 17213443}, {12607, 17213699}, {12608, 17213955}, {12609, 17214211}, + {12610, 17214467}, {12611, 17214723}, {12612, 17214979}, {12613, 17215235}, + {12614, 17215491}, {12615, 17215747}, {12616, 17216003}, {12617, 17216259}, + {12618, 17216515}, {12619, 17216771}, {12620, 17217027}, {12621, 17217283}, + {12622, 17217539}, {12623, 17217795}, {12624, 17218051}, {12625, 17218307}, + {12626, 17218563}, {12627, 17218819}, {12628, 17219075}, {12629, 17219331}, + {12630, 17219587}, {12631, 17219843}, {12632, 17220099}, {12633, 17220355}, + {12634, 17220611}, {12635, 17220867}, {12636, 17221123}, {12637, 17221379}, + {12638, 17221635}, {12639, 17221891}, {12640, 17222147}, {12641, 17222403}, + {12642, 17222659}, {12643, 17222915}, {12644, 0}, {12645, 17223171}, + {12646, 17223427}, {12647, 17223683}, {12648, 17223939}, {12649, 17224195}, + {12650, 17224451}, {12651, 17224707}, {12652, 17224963}, {12653, 17225219}, + {12654, 17225475}, {12655, 17225731}, {12656, 17225987}, {12657, 17226243}, + {12658, 17226499}, {12659, 17226755}, {12660, 17227011}, {12661, 17227267}, + {12662, 17227523}, {12663, 17227779}, {12664, 17228035}, {12665, 17228291}, + {12666, 17228547}, {12667, 17228803}, {12668, 17229059}, {12669, 17229315}, + {12670, 17229571}, {12671, 17229827}, {12672, 17230083}, {12673, 17230339}, + {12674, 17230595}, {12675, 17230851}, {12676, 17231107}, {12677, 17231363}, + {12678, 17231619}, {12679, 17231875}, {12680, 17232131}, {12681, 17232387}, + {12682, 17232643}, {12683, 17232899}, {12684, 17233155}, {12685, 17233411}, + {12686, 17233667}, {12687, 2}, {12688, 1}, {12690, 17152259}, + {12691, 17153795}, {12692, 17233923}, {12693, 17234179}, {12694, 17234435}, + {12695, 17234691}, {12696, 17234947}, {12697, 17235203}, {12698, 17153283}, + {12699, 17235459}, {12700, 17235715}, {12701, 17235971}, {12702, 17236227}, + {12703, 17154307}, {12704, 1}, {12774, 2}, {12784, 1}, + {12800, 50790915}, {12801, 50791683}, {12802, 50792451}, {12803, 50793219}, + {12804, 50793987}, {12805, 50794755}, {12806, 50795523}, {12807, 50796291}, + {12808, 50797059}, {12809, 50797827}, {12810, 50798595}, {12811, 50799363}, + {12812, 50800131}, {12813, 50800899}, {12814, 50801667}, {12815, 50802435}, + {12816, 50803203}, {12817, 50803971}, {12818, 50804739}, {12819, 50805507}, + {12820, 50806275}, {12821, 50807043}, {12822, 50807811}, {12823, 50808579}, + {12824, 50809347}, {12825, 50810115}, {12826, 50810883}, {12827, 50811651}, + {12828, 50812419}, {12829, 67590403}, {12830, 67591427}, {12831, 2}, + {12832, 50815235}, {12833, 50816003}, {12834, 50816771}, {12835, 50817539}, + {12836, 50818307}, {12837, 50819075}, {12838, 50819843}, {12839, 50820611}, + {12840, 50821379}, {12841, 50822147}, {12842, 50822915}, {12843, 50823683}, + {12844, 50824451}, {12845, 50825219}, {12846, 50825987}, {12847, 50826755}, + {12848, 50827523}, {12849, 50828291}, {12850, 50829059}, {12851, 50829827}, + {12852, 50830595}, {12853, 50831363}, {12854, 50832131}, {12855, 50832899}, + {12856, 50833667}, {12857, 50834435}, {12858, 50835203}, {12859, 50835971}, + {12860, 50836739}, {12861, 50837507}, {12862, 50838275}, {12863, 50839043}, + {12864, 50839811}, {12865, 50840579}, {12866, 50841347}, {12867, 50842115}, + {12868, 17288451}, {12869, 17288707}, {12870, 17169155}, {12871, 17288963}, + {12872, 1}, {12880, 50843651}, {12881, 33855747}, {12882, 34067203}, + {12883, 33562371}, {12884, 34067715}, {12885, 34068227}, {12886, 34068739}, + {12887, 34069251}, {12888, 34069763}, {12889, 34070275}, {12890, 34070787}, + {12891, 33837571}, {12892, 33836803}, {12893, 34071299}, {12894, 34071811}, + {12895, 34072323}, {12896, 17210115}, {12897, 17210883}, {12898, 17211651}, + {12899, 17212163}, {12900, 17214211}, {12901, 17214467}, {12902, 17215235}, + {12903, 17215747}, {12904, 17216003}, {12905, 17216515}, {12906, 17216771}, + {12907, 17217027}, {12908, 17217283}, {12909, 17217539}, {12910, 17247491}, + {12911, 17248259}, {12912, 17249027}, {12913, 17249795}, {12914, 17250563}, + {12915, 17251331}, {12916, 17252099}, {12917, 17252867}, {12918, 17253635}, + {12919, 17254403}, {12920, 17255171}, {12921, 17255939}, {12922, 17256707}, + {12923, 17257475}, {12924, 34072835}, {12925, 34073347}, {12926, 17296643}, + {12927, 1}, {12928, 17152259}, {12929, 17153795}, {12930, 17233923}, + {12931, 17234179}, {12932, 17264131}, {12933, 17264899}, {12934, 17265667}, + {12935, 17155075}, {12936, 17267203}, {12937, 17158147}, {12938, 17170947}, + {12939, 17174019}, {12940, 17173763}, {12941, 17171203}, {12942, 17194755}, + {12943, 17160195}, {12944, 17170435}, {12945, 17274115}, {12946, 17274883}, + {12947, 17275651}, {12948, 17276419}, {12949, 17277187}, {12950, 17277955}, + {12951, 17278723}, {12952, 17279491}, {12953, 17296899}, {12954, 17297155}, + {12955, 17161731}, {12956, 17297411}, {12957, 17297667}, {12958, 17297923}, + {12959, 17298179}, {12960, 17298435}, {12961, 17286403}, {12962, 17298691}, + {12963, 17298947}, {12964, 17234435}, {12965, 17234691}, {12966, 17234947}, + {12967, 17299203}, {12968, 17299459}, {12969, 17299715}, {12970, 17299971}, + {12971, 17281795}, {12972, 17282563}, {12973, 17283331}, {12974, 17284099}, + {12975, 17284867}, {12976, 17300227}, {12977, 34077699}, {12978, 34078211}, + {12979, 34078723}, {12980, 34079235}, {12981, 34079747}, {12982, 33564931}, + {12983, 34067971}, {12984, 34072067}, {12985, 34080259}, {12986, 34080771}, + {12987, 34081283}, {12988, 34081795}, {12989, 34082307}, {12990, 34082819}, + {12991, 34083331}, {12992, 34083843}, {12993, 34084355}, {12994, 34084867}, + {12995, 34085379}, {12996, 34085891}, {12997, 34086403}, {12998, 34086915}, + {12999, 34087427}, {13000, 34087939}, {13001, 50865667}, {13002, 50866435}, + {13003, 50867203}, {13004, 34090755}, {13005, 50868483}, {13006, 34092035}, + {13007, 50869763}, {13008, 17316099}, {13009, 17316355}, {13010, 17316611}, + {13011, 17316867}, {13012, 17317123}, {13013, 17317379}, {13014, 17317635}, + {13015, 17317891}, {13016, 17318147}, {13017, 17209603}, {13018, 17318403}, + {13019, 17318659}, {13020, 17318915}, {13021, 17319171}, {13022, 17319427}, + {13023, 17319683}, {13024, 17319939}, {13025, 17320195}, {13026, 17320451}, + {13027, 17209859}, {13028, 17320707}, {13029, 17320963}, {13030, 17321219}, + {13031, 17321475}, {13032, 17321731}, {13033, 17321987}, {13034, 17322243}, + {13035, 17322499}, {13036, 17322755}, {13037, 17323011}, {13038, 17323267}, + {13039, 17323523}, {13040, 17323779}, {13041, 17324035}, {13042, 17324291}, + {13043, 17324547}, {13044, 17324803}, {13045, 17325059}, {13046, 17325315}, + {13047, 17325571}, {13048, 17325827}, {13049, 17326083}, {13050, 17326339}, + {13051, 17326595}, {13052, 17326851}, {13053, 17327107}, {13054, 17327363}, + {13055, 34104835}, {13056, 67659779}, {13057, 67660803}, {13058, 67661827}, + {13059, 50885635}, {13060, 67663619}, {13061, 50887427}, {13062, 50888195}, + {13063, 84443395}, {13064, 67667459}, {13065, 50891267}, {13066, 50892035}, + {13067, 50892803}, {13068, 67670787}, {13069, 67671811}, {13070, 50895619}, + {13071, 50896387}, {13072, 34119939}, {13073, 50897667}, {13074, 67675651}, + {13075, 67676675}, {13076, 34123267}, {13077, 84455427}, {13078, 101233923}, + {13079, 84458243}, {13080, 50901507}, {13081, 84459523}, {13082, 84460803}, + {13083, 67684867}, {13084, 50908675}, {13085, 50909443}, {13086, 50910211}, + {13087, 67688195}, {13088, 84466435}, {13089, 67690499}, {13090, 50914307}, + {13091, 50915075}, {13092, 50915843}, {13093, 34139395}, {13094, 34139907}, + {13095, 34128643}, {13096, 34140419}, {13097, 50918147}, {13098, 50918915}, + {13099, 84474115}, {13100, 50920963}, {13101, 67698947}, {13102, 84477187}, + {13103, 50924035}, {13104, 34147587}, {13105, 34148099}, {13106, 84480259}, + {13107, 67704323}, {13108, 84482563}, {13109, 50929411}, {13110, 84484611}, + {13111, 34154243}, {13112, 50931971}, {13113, 50932739}, {13114, 50933507}, + {13115, 50934275}, {13116, 50935043}, {13117, 67713027}, {13118, 50936835}, + {13119, 34160387}, {13120, 50938115}, {13121, 50938883}, {13122, 50939651}, + {13123, 67717635}, {13124, 50941443}, {13125, 50942211}, {13126, 50942979}, + {13127, 84498179}, {13128, 67722243}, {13129, 34168835}, {13130, 84500995}, + {13131, 34170627}, {13132, 67725571}, {13133, 67680003}, {13134, 50949379}, + {13135, 50950147}, {13136, 50950915}, {13137, 67728899}, {13138, 34175491}, + {13139, 50953219}, {13140, 67731203}, {13141, 34177795}, {13142, 84509955}, + {13143, 50904323}, {13144, 34179587}, {13145, 34180099}, {13146, 34180611}, + {13147, 34181123}, {13148, 34181635}, {13149, 34182147}, {13150, 34182659}, + {13151, 34183171}, {13152, 34183683}, {13153, 34184195}, {13154, 50961923}, + {13155, 50962691}, {13156, 50963459}, {13157, 50964227}, {13158, 50964995}, + {13159, 50965763}, {13160, 50966531}, {13161, 50967299}, {13162, 50968067}, + {13163, 50968835}, {13164, 50969603}, {13165, 50970371}, {13166, 50971139}, + {13167, 50971907}, {13168, 50972675}, {13169, 50973443}, {13170, 34196995}, + {13171, 34197507}, {13172, 50975235}, {13173, 34198787}, {13174, 34199299}, + {13175, 34199811}, {13176, 50977539}, {13177, 50978307}, {13178, 34201859}, + {13179, 34202371}, {13180, 34202883}, {13181, 34203395}, {13182, 34203907}, + {13183, 67758851}, {13184, 34196483}, {13185, 34205443}, {13186, 34205955}, + {13187, 34206467}, {13188, 34206979}, {13189, 34207491}, {13190, 34208003}, + {13191, 34208515}, {13192, 50986243}, {13193, 67764227}, {13194, 34210819}, + {13195, 34211331}, {13196, 34211843}, {13197, 34212355}, {13198, 34212867}, + {13199, 34213379}, {13200, 34213891}, {13201, 50991619}, {13202, 50992387}, + {13203, 50990851}, {13204, 50993155}, {13205, 34216707}, {13206, 34217219}, + {13207, 34217731}, {13208, 33556995}, {13209, 34218243}, {13210, 34218755}, + {13211, 34219267}, {13212, 34219779}, {13213, 34220291}, {13214, 34220803}, + {13215, 50998531}, {13216, 50999299}, {13217, 34200579}, {13218, 51000067}, + {13219, 51000835}, {13220, 51001603}, {13221, 34201347}, {13222, 51002371}, + {13223, 51003139}, {13224, 67781123}, {13225, 34196483}, {13226, 51004931}, + {13227, 51005699}, {13228, 51006467}, {13229, 51007235}, {13230, 84562435}, + {13231, 101340931}, {13232, 34233603}, {13233, 34234115}, {13234, 34234627}, + {13235, 34235139}, {13236, 34235651}, {13237, 34236163}, {13238, 34236675}, + {13239, 34237187}, {13240, 34237699}, {13241, 34237187}, {13242, 34238211}, + {13243, 34238723}, {13244, 34239235}, {13245, 34239747}, {13246, 34240259}, + {13247, 34239747}, {13248, 34240771}, {13249, 34241283}, {13250, 2}, + {13251, 34241795}, {13252, 33827331}, {13253, 33554947}, {13254, 67796739}, + {13255, 2}, {13256, 34243331}, {13257, 34243843}, {13258, 34244355}, + {13259, 34196227}, {13260, 34244867}, {13261, 34245379}, {13262, 34220803}, + {13263, 34245891}, {13264, 33557251}, {13265, 34246403}, {13266, 51024131}, + {13267, 34247683}, {13268, 34208003}, {13269, 51025411}, {13270, 51026179}, + {13271, 34249731}, {13272, 2}, {13273, 51027459}, {13274, 34251011}, + {13275, 34231811}, {13276, 34251523}, {13277, 34252035}, {13278, 51029763}, + {13279, 51030531}, {13280, 34254083}, {13281, 34254595}, {13282, 34255107}, + {13283, 34255619}, {13284, 34256131}, {13285, 34256643}, {13286, 34257155}, + {13287, 34257667}, {13288, 34258179}, {13289, 51035907}, {13290, 51036675}, + {13291, 51037443}, {13292, 51038211}, {13293, 51038979}, {13294, 51039747}, + {13295, 51040515}, {13296, 51041283}, {13297, 51042051}, {13298, 51042819}, + {13299, 51043587}, {13300, 51044355}, {13301, 51045123}, {13302, 51045891}, + {13303, 51046659}, {13304, 51047427}, {13305, 51048195}, {13306, 51048963}, + {13307, 51049731}, {13308, 51050499}, {13309, 51051267}, {13310, 51052035}, + {13311, 51052803}, {13312, 1}, {42125, 2}, {42128, 1}, + {42183, 2}, {42192, 1}, {42540, 2}, {42560, 17499139}, + {42561, 1}, {42562, 17499395}, {42563, 1}, {42564, 17499651}, + {42565, 1}, {42566, 17499907}, {42567, 1}, {42568, 17500163}, + {42569, 1}, {42570, 16946435}, {42571, 1}, {42572, 17500419}, + {42573, 1}, {42574, 17500675}, {42575, 1}, {42576, 17500931}, + {42577, 1}, {42578, 17501187}, {42579, 1}, {42580, 17501443}, + {42581, 1}, {42582, 17501699}, {42583, 1}, {42584, 17501955}, + {42585, 1}, {42586, 17502211}, {42587, 1}, {42588, 17502467}, + {42589, 1}, {42590, 17502723}, {42591, 1}, {42592, 17502979}, + {42593, 1}, {42594, 17503235}, {42595, 1}, {42596, 17503491}, + {42597, 1}, {42598, 17503747}, {42599, 1}, {42600, 17504003}, + {42601, 1}, {42602, 17504259}, {42603, 1}, {42604, 17504515}, + {42605, 1}, {42624, 17504771}, {42625, 1}, {42626, 17505027}, + {42627, 1}, {42628, 17505283}, {42629, 1}, {42630, 17505539}, + {42631, 1}, {42632, 17505795}, {42633, 1}, {42634, 17506051}, + {42635, 1}, {42636, 17506307}, {42637, 1}, {42638, 17506563}, + {42639, 1}, {42640, 17506819}, {42641, 1}, {42642, 17507075}, + {42643, 1}, {42644, 17507331}, {42645, 1}, {42646, 17507587}, + {42647, 1}, {42648, 17507843}, {42649, 1}, {42650, 17508099}, + {42651, 1}, {42652, 16873219}, {42653, 16873731}, {42654, 1}, + {42744, 2}, {42752, 1}, {42786, 17508355}, {42787, 1}, + {42788, 17508611}, {42789, 1}, {42790, 17508867}, {42791, 1}, + {42792, 17509123}, {42793, 1}, {42794, 17509379}, {42795, 1}, + {42796, 17509635}, {42797, 1}, {42798, 17509891}, {42799, 1}, + {42802, 17510147}, {42803, 1}, {42804, 17510403}, {42805, 1}, + {42806, 17510659}, {42807, 1}, {42808, 17510915}, {42809, 1}, + {42810, 17511171}, {42811, 1}, {42812, 17511427}, {42813, 1}, + {42814, 17511683}, {42815, 1}, {42816, 17511939}, {42817, 1}, + {42818, 17512195}, {42819, 1}, {42820, 17512451}, {42821, 1}, + {42822, 17512707}, {42823, 1}, {42824, 17512963}, {42825, 1}, + {42826, 17513219}, {42827, 1}, {42828, 17513475}, {42829, 1}, + {42830, 17513731}, {42831, 1}, {42832, 17513987}, {42833, 1}, + {42834, 17514243}, {42835, 1}, {42836, 17514499}, {42837, 1}, + {42838, 17514755}, {42839, 1}, {42840, 17515011}, {42841, 1}, + {42842, 17515267}, {42843, 1}, {42844, 17515523}, {42845, 1}, + {42846, 17515779}, {42847, 1}, {42848, 17516035}, {42849, 1}, + {42850, 17516291}, {42851, 1}, {42852, 17516547}, {42853, 1}, + {42854, 17516803}, {42855, 1}, {42856, 17517059}, {42857, 1}, + {42858, 17517315}, {42859, 1}, {42860, 17517571}, {42861, 1}, + {42862, 17517827}, {42863, 1}, {42864, 17517827}, {42865, 1}, + {42873, 17518083}, {42874, 1}, {42875, 17518339}, {42876, 1}, + {42877, 17518595}, {42878, 17518851}, {42879, 1}, {42880, 17519107}, + {42881, 1}, {42882, 17519363}, {42883, 1}, {42884, 17519619}, + {42885, 1}, {42886, 17519875}, {42887, 1}, {42891, 17520131}, + {42892, 1}, {42893, 16961539}, {42894, 1}, {42896, 17520387}, + {42897, 1}, {42898, 17520643}, {42899, 1}, {42902, 17520899}, + {42903, 1}, {42904, 17521155}, {42905, 1}, {42906, 17521411}, + {42907, 1}, {42908, 17521667}, {42909, 1}, {42910, 17521923}, + {42911, 1}, {42912, 17522179}, {42913, 1}, {42914, 17522435}, + {42915, 1}, {42916, 17522691}, {42917, 1}, {42918, 17522947}, + {42919, 1}, {42920, 17523203}, {42921, 1}, {42922, 16841475}, + {42923, 16959235}, {42924, 16961283}, {42925, 17523459}, {42926, 16961795}, + {42927, 1}, {42928, 17523715}, {42929, 17523971}, {42930, 16962307}, + {42931, 17524227}, {42932, 17524483}, {42933, 1}, {42934, 17524739}, + {42935, 1}, {42936, 17524995}, {42937, 1}, {42938, 17525251}, + {42939, 1}, {42940, 17525507}, {42941, 1}, {42942, 17525763}, + {42943, 1}, {42944, 17526019}, {42945, 1}, {42946, 17526275}, + {42947, 1}, {42948, 17526531}, {42949, 16964611}, {42950, 17526787}, + {42951, 17527043}, {42952, 1}, {42953, 17527299}, {42954, 1}, + {42955, 17527555}, {42956, 17527811}, {42957, 1}, {42958, 2}, + {42960, 17528067}, {42961, 1}, {42962, 2}, {42963, 1}, + {42964, 2}, {42965, 1}, {42966, 17528323}, {42967, 1}, + {42968, 17528579}, {42969, 1}, {42970, 17528835}, {42971, 1}, + {42972, 17529091}, {42973, 2}, {42994, 16777731}, {42995, 16778499}, + {42996, 16781315}, {42997, 17529347}, {42998, 1}, {43000, 16802051}, + {43001, 16808195}, {43002, 1}, {43053, 2}, {43056, 1}, + {43066, 2}, {43072, 1}, {43128, 2}, {43136, 1}, + {43206, 2}, {43214, 1}, {43226, 2}, {43232, 1}, + {43348, 2}, {43359, 1}, {43389, 2}, {43392, 1}, + {43470, 2}, {43471, 1}, {43482, 2}, {43486, 1}, + {43519, 2}, {43520, 1}, {43575, 2}, {43584, 1}, + {43598, 2}, {43600, 1}, {43610, 2}, {43612, 1}, + {43715, 2}, {43739, 1}, {43767, 2}, {43777, 1}, + {43783, 2}, {43785, 1}, {43791, 2}, {43793, 1}, + {43799, 2}, {43808, 1}, {43815, 2}, {43816, 1}, + {43823, 2}, {43824, 1}, {43868, 17508867}, {43869, 17529603}, + {43870, 17135363}, {43871, 17529859}, {43872, 1}, {43881, 17530115}, + {43882, 1}, {43884, 2}, {43888, 17530371}, {43889, 17530627}, + {43890, 17530883}, {43891, 17531139}, {43892, 17531395}, {43893, 17531651}, + {43894, 17531907}, {43895, 17532163}, {43896, 17532419}, {43897, 17532675}, + {43898, 17532931}, {43899, 17533187}, {43900, 17533443}, {43901, 17533699}, + {43902, 17533955}, {43903, 17534211}, {43904, 17534467}, {43905, 17534723}, + {43906, 17534979}, {43907, 17535235}, {43908, 17535491}, {43909, 17535747}, + {43910, 17536003}, {43911, 17536259}, {43912, 17536515}, {43913, 17536771}, + {43914, 17537027}, {43915, 17537283}, {43916, 17537539}, {43917, 17537795}, + {43918, 17538051}, {43919, 17538307}, {43920, 17538563}, {43921, 17538819}, + {43922, 17539075}, {43923, 17539331}, {43924, 17539587}, {43925, 17539843}, + {43926, 17540099}, {43927, 17540355}, {43928, 17540611}, {43929, 17540867}, + {43930, 17541123}, {43931, 17541379}, {43932, 17541635}, {43933, 17541891}, + {43934, 17542147}, {43935, 17542403}, {43936, 17542659}, {43937, 17542915}, + {43938, 17543171}, {43939, 17543427}, {43940, 17543683}, {43941, 17543939}, + {43942, 17544195}, {43943, 17544451}, {43944, 17544707}, {43945, 17544963}, + {43946, 17545219}, {43947, 17545475}, {43948, 17545731}, {43949, 17545987}, + {43950, 17546243}, {43951, 17546499}, {43952, 17546755}, {43953, 17547011}, + {43954, 17547267}, {43955, 17547523}, {43956, 17547779}, {43957, 17548035}, + {43958, 17548291}, {43959, 17548547}, {43960, 17548803}, {43961, 17549059}, + {43962, 17549315}, {43963, 17549571}, {43964, 17549827}, {43965, 17550083}, + {43966, 17550339}, {43967, 17550595}, {43968, 1}, {44014, 2}, + {44016, 1}, {44026, 2}, {44032, 1}, {55204, 2}, + {55216, 1}, {55239, 2}, {55243, 1}, {55292, 2}, + {63744, 17550851}, {63745, 17551107}, {63746, 17192707}, {63747, 17551363}, + {63748, 17551619}, {63749, 17551875}, {63750, 17552131}, {63751, 17206531}, + {63753, 17552387}, {63754, 17194755}, {63755, 17552643}, {63756, 17552899}, + {63757, 17553155}, {63758, 17553411}, {63759, 17553667}, {63760, 17553923}, + {63761, 17554179}, {63762, 17554435}, {63763, 17554691}, {63764, 17554947}, + {63765, 17555203}, {63766, 17555459}, {63767, 17555715}, {63768, 17555971}, + {63769, 17556227}, {63770, 17556483}, {63771, 17556739}, {63772, 17556995}, + {63773, 17557251}, {63774, 17557507}, {63775, 17557763}, {63776, 17558019}, + {63777, 17558275}, {63778, 17558531}, {63779, 17558787}, {63780, 17559043}, + {63781, 17559299}, {63782, 17559555}, {63783, 17559811}, {63784, 17560067}, + {63785, 17560323}, {63786, 17560579}, {63787, 17560835}, {63788, 17561091}, + {63789, 17561347}, {63790, 17561603}, {63791, 17561859}, {63792, 17562115}, + {63793, 17562371}, {63794, 17562627}, {63795, 17562883}, {63796, 17184003}, + {63797, 17563139}, {63798, 17563395}, {63799, 17563651}, {63800, 17563907}, + {63801, 17564163}, {63802, 17564419}, {63803, 17564675}, {63804, 17564931}, + {63805, 17565187}, {63806, 17565443}, {63807, 17565699}, {63808, 17202691}, + {63809, 17565955}, {63810, 17566211}, {63811, 17566467}, {63812, 17566723}, + {63813, 17566979}, {63814, 17567235}, {63815, 17567491}, {63816, 17567747}, + {63817, 17568003}, {63818, 17568259}, {63819, 17568515}, {63820, 17568771}, + {63821, 17569027}, {63822, 17569283}, {63823, 17569539}, {63824, 17569795}, + {63825, 17570051}, {63826, 17570307}, {63827, 17570563}, {63828, 17570819}, + {63829, 17571075}, {63830, 17571331}, {63831, 17571587}, {63832, 17571843}, + {63833, 17572099}, {63834, 17572355}, {63835, 17572611}, {63836, 17554947}, + {63837, 17572867}, {63838, 17573123}, {63839, 17573379}, {63840, 17573635}, + {63841, 17573891}, {63842, 17574147}, {63843, 17574403}, {63844, 17574659}, + {63845, 17574915}, {63846, 17575171}, {63847, 17575427}, {63848, 17575683}, + {63849, 17575939}, {63850, 17576195}, {63851, 17576451}, {63852, 17576707}, + {63853, 17576963}, {63854, 17577219}, {63855, 17577475}, {63856, 17577731}, + {63857, 17193219}, {63858, 17577987}, {63859, 17578243}, {63860, 17578499}, + {63861, 17578755}, {63862, 17579011}, {63863, 17579267}, {63864, 17579523}, + {63865, 17579779}, {63866, 17580035}, {63867, 17580291}, {63868, 17580547}, + {63869, 17580803}, {63870, 17581059}, {63871, 17581315}, {63872, 17581571}, + {63873, 17161731}, {63874, 17581827}, {63875, 17582083}, {63876, 17582339}, + {63877, 17582595}, {63878, 17582851}, {63879, 17583107}, {63880, 17583363}, + {63881, 17583619}, {63882, 17156867}, {63883, 17583875}, {63884, 17584131}, + {63885, 17584387}, {63886, 17584643}, {63887, 17584899}, {63888, 17585155}, + {63889, 17585411}, {63890, 17585667}, {63891, 17585923}, {63892, 17586179}, + {63893, 17586435}, {63894, 17586691}, {63895, 17586947}, {63896, 17587203}, + {63897, 17587459}, {63898, 17587715}, {63899, 17587971}, {63900, 17588227}, + {63901, 17588483}, {63902, 17588739}, {63903, 17588995}, {63904, 17589251}, + {63905, 17577475}, {63906, 17589507}, {63907, 17589763}, {63908, 17590019}, + {63909, 17590275}, {63910, 17590531}, {63911, 17590787}, {63912, 17327619}, + {63913, 17591043}, {63914, 17573379}, {63915, 17591299}, {63916, 17591555}, + {63917, 17591811}, {63918, 17592067}, {63919, 17592323}, {63920, 17592579}, + {63921, 17592835}, {63922, 17593091}, {63923, 17593347}, {63924, 17593603}, + {63925, 17593859}, {63926, 17594115}, {63927, 17594371}, {63928, 17594627}, + {63929, 17594883}, {63930, 17595139}, {63931, 17595395}, {63932, 17595651}, + {63933, 17595907}, {63934, 17596163}, {63935, 17554947}, {63936, 17596419}, + {63937, 17596675}, {63938, 17596931}, {63939, 17597187}, {63940, 17206275}, + {63941, 17597443}, {63942, 17597699}, {63943, 17597955}, {63944, 17598211}, + {63945, 17598467}, {63946, 17598723}, {63947, 17598979}, {63948, 17599235}, + {63949, 17599491}, {63950, 17599747}, {63951, 17600003}, {63952, 17600259}, + {63953, 17264899}, {63954, 17600515}, {63955, 17600771}, {63956, 17601027}, + {63957, 17601283}, {63958, 17601539}, {63959, 17601795}, {63960, 17602051}, + {63961, 17602307}, {63962, 17602563}, {63963, 17573891}, {63964, 17602819}, + {63965, 17603075}, {63966, 17603331}, {63967, 17603587}, {63968, 17603843}, + {63969, 17604099}, {63970, 17604355}, {63971, 17604611}, {63972, 17604867}, + {63973, 17605123}, {63974, 17605379}, {63975, 17605635}, {63976, 17605891}, + {63977, 17194499}, {63978, 17606147}, {63979, 17606403}, {63980, 17606659}, + {63981, 17606915}, {63982, 17607171}, {63983, 17607427}, {63984, 17607683}, + {63985, 17607939}, {63986, 17608195}, {63987, 17608451}, {63988, 17608707}, + {63989, 17608963}, {63990, 17609219}, {63991, 17181955}, {63992, 17609475}, + {63993, 17609731}, {63994, 17609987}, {63995, 17610243}, {63996, 17610499}, + {63997, 17610755}, {63998, 17611011}, {63999, 17611267}, {64000, 17611523}, + {64001, 17611779}, {64002, 17612035}, {64003, 17612291}, {64004, 17612547}, + {64005, 17612803}, {64006, 17613059}, {64007, 17613315}, {64008, 17188867}, + {64009, 17613571}, {64010, 17189635}, {64011, 17613827}, {64012, 17614083}, + {64013, 17614339}, {64014, 1}, {64016, 17614595}, {64017, 1}, + {64018, 17614851}, {64019, 1}, {64021, 17615107}, {64022, 17615363}, + {64023, 17615619}, {64024, 17615875}, {64025, 17616131}, {64026, 17616387}, + {64027, 17616643}, {64028, 17616899}, {64029, 17617155}, {64030, 17183747}, + {64031, 1}, {64032, 17617411}, {64033, 1}, {64034, 17617667}, + {64035, 1}, {64037, 17617923}, {64038, 17618179}, {64039, 1}, + {64042, 17618435}, {64043, 17618691}, {64044, 17618947}, {64045, 17619203}, + {64046, 17619459}, {64047, 17619715}, {64048, 17619971}, {64049, 17620227}, + {64050, 17620483}, {64051, 17620739}, {64052, 17620995}, {64053, 17621251}, + {64054, 17621507}, {64055, 17621763}, {64056, 17622019}, {64057, 17622275}, + {64058, 17622531}, {64059, 17622787}, {64060, 17163523}, {64061, 17623043}, + {64062, 17623299}, {64063, 17623555}, {64064, 17623811}, {64065, 17624067}, + {64066, 17624323}, {64067, 17624579}, {64068, 17624835}, {64069, 17625091}, + {64070, 17625347}, {64071, 17625603}, {64072, 17625859}, {64073, 17626115}, + {64074, 17626371}, {64075, 17626627}, {64076, 17275651}, {64077, 17626883}, + {64078, 17627139}, {64079, 17627395}, {64080, 17627651}, {64081, 17278723}, + {64082, 17627907}, {64083, 17628163}, {64084, 17628419}, {64085, 17628675}, + {64086, 17628931}, {64087, 17586691}, {64088, 17629187}, {64089, 17629443}, + {64090, 17629699}, {64091, 17629955}, {64092, 17630211}, {64093, 17630467}, + {64095, 17630723}, {64096, 17630979}, {64097, 17631235}, {64098, 17631491}, + {64099, 17631747}, {64100, 17632003}, {64101, 17632259}, {64102, 17632515}, + {64103, 17617923}, {64104, 17632771}, {64105, 17633027}, {64106, 17633283}, + {64107, 17633539}, {64108, 17633795}, {64109, 17634051}, {64110, 2}, + {64112, 17634307}, {64113, 17634563}, {64114, 17634819}, {64115, 17635075}, + {64116, 17635331}, {64117, 17635587}, {64118, 17635843}, {64119, 17636099}, + {64120, 17621507}, {64121, 17636355}, {64122, 17636611}, {64123, 17636867}, + {64124, 17614595}, {64125, 17637123}, {64126, 17637379}, {64127, 17637635}, + {64128, 17637891}, {64129, 17638147}, {64130, 17638403}, {64131, 17638659}, + {64132, 17638915}, {64133, 17639171}, {64134, 17639427}, {64135, 17639683}, + {64136, 17639939}, {64137, 17623555}, {64138, 17640195}, {64139, 17623811}, + {64140, 17640451}, {64141, 17640707}, {64142, 17640963}, {64143, 17641219}, + {64144, 17641475}, {64145, 17614851}, {64146, 17560323}, {64147, 17641731}, + {64148, 17641987}, {64149, 17171971}, {64150, 17577731}, {64151, 17598723}, + {64152, 17642243}, {64153, 17642499}, {64154, 17625603}, {64155, 17642755}, + {64156, 17625859}, {64157, 17643011}, {64158, 17643267}, {64159, 17643523}, + {64160, 17615363}, {64161, 17643779}, {64162, 17644035}, {64163, 17644291}, + {64164, 17644547}, {64165, 17644803}, {64166, 17615619}, {64167, 17645059}, + {64168, 17645315}, {64169, 17645571}, {64170, 17645827}, {64171, 17646083}, + {64172, 17646339}, {64173, 17628931}, {64174, 17646595}, {64175, 17646851}, + {64176, 17586691}, {64177, 17647107}, {64178, 17629955}, {64179, 17647363}, + {64180, 17647619}, {64181, 17647875}, {64182, 17648131}, {64183, 17648387}, + {64184, 17631235}, {64185, 17648643}, {64186, 17617667}, {64187, 17648899}, + {64188, 17631491}, {64189, 17572867}, {64190, 17649155}, {64191, 17631747}, + {64192, 17649411}, {64193, 17632259}, {64194, 17649667}, {64195, 17649923}, + {64196, 17650179}, {64197, 17650435}, {64198, 17650691}, {64199, 17632771}, + {64200, 17616899}, {64201, 17650947}, {64202, 17633027}, {64203, 17651203}, + {64204, 17633283}, {64205, 17651459}, {64206, 17206531}, {64207, 17651715}, + {64208, 17651971}, {64209, 17652227}, {64210, 17652483}, {64211, 17652739}, + {64212, 17652995}, {64213, 17653251}, {64214, 17653507}, {64215, 17653763}, + {64216, 17654019}, {64217, 17654275}, {64218, 2}, {64256, 34431747}, + {64257, 34432259}, {64258, 34432771}, {64259, 51209219}, {64260, 51210499}, + {64261, 33559043}, {64263, 2}, {64275, 34434051}, {64276, 34434563}, + {64277, 34435075}, {64278, 34435587}, {64279, 34436099}, {64280, 2}, + {64285, 34436611}, {64286, 1}, {64287, 34437123}, {64288, 17660419}, + {64289, 17054467}, {64290, 17055235}, {64291, 17660675}, {64292, 17660931}, + {64293, 17661187}, {64294, 17661443}, {64295, 17661699}, {64296, 17661955}, + {64297, 17047043}, {64298, 34439427}, {64299, 34439939}, {64300, 51217667}, + {64301, 51218435}, {64302, 34441987}, {64303, 34442499}, {64304, 34443011}, + {64305, 34443523}, {64306, 34444035}, {64307, 34444547}, {64308, 34445059}, + {64309, 34445571}, {64310, 34446083}, {64311, 2}, {64312, 34446595}, + {64313, 34447107}, {64314, 34447619}, {64315, 34448131}, {64316, 34448643}, + {64317, 2}, {64318, 34449155}, {64319, 2}, {64320, 34449667}, + {64321, 34450179}, {64322, 2}, {64323, 34450691}, {64324, 34451203}, + {64325, 2}, {64326, 34451715}, {64327, 34452227}, {64328, 34452739}, + {64329, 34440451}, {64330, 34453251}, {64331, 34453763}, {64332, 34454275}, + {64333, 34454787}, {64334, 34455299}, {64335, 34455811}, {64336, 17679107}, + {64338, 17679363}, {64342, 17679619}, {64346, 17679875}, {64350, 17680131}, + {64354, 17680387}, {64358, 17680643}, {64362, 17680899}, {64366, 17681155}, + {64370, 17681411}, {64374, 17681667}, {64378, 17681923}, {64382, 17682179}, + {64386, 17682435}, {64388, 17682691}, {64390, 17682947}, {64392, 17683203}, + {64394, 17683459}, {64396, 17683715}, {64398, 17683971}, {64402, 17684227}, + {64406, 17684483}, {64410, 17684739}, {64414, 17684995}, {64416, 17685251}, + {64420, 17685507}, {64422, 17685763}, {64426, 17686019}, {64430, 17686275}, + {64432, 17686531}, {64434, 1}, {64451, 2}, {64467, 17686787}, + {64471, 16911619}, {64473, 17687043}, {64475, 17687299}, {64477, 33688835}, + {64478, 17687555}, {64480, 17687811}, {64482, 17688067}, {64484, 17688323}, + {64488, 17688579}, {64490, 34466051}, {64492, 34466563}, {64494, 34467075}, + {64496, 34467587}, {64498, 34468099}, {64500, 34468611}, {64502, 34469123}, + {64505, 34469635}, {64508, 17692931}, {64512, 34470403}, {64513, 34470915}, + {64514, 34471427}, {64515, 34469635}, {64516, 34471939}, {64517, 34472451}, + {64518, 34472963}, {64519, 34473475}, {64520, 34473987}, {64521, 34474499}, + {64522, 34475011}, {64523, 34475523}, {64524, 34476035}, {64525, 34476547}, + {64526, 34477059}, {64527, 34477571}, {64528, 34478083}, {64529, 34478595}, + {64530, 34479107}, {64531, 34479619}, {64532, 34480131}, {64533, 34480643}, + {64534, 34481155}, {64535, 34480899}, {64536, 34481667}, {64537, 34482179}, + {64538, 34482691}, {64539, 34483203}, {64540, 34483715}, {64541, 34484227}, + {64542, 34484739}, {64543, 34485251}, {64544, 34485763}, {64545, 34486275}, + {64546, 34486787}, {64547, 34487299}, {64548, 34487811}, {64549, 34488323}, + {64550, 34488835}, {64551, 34489347}, {64552, 34489859}, {64553, 34490371}, + {64554, 34490883}, {64555, 34491395}, {64556, 34491907}, {64557, 34492419}, + {64558, 34492931}, {64559, 34493443}, {64560, 34493955}, {64561, 34494467}, + {64562, 34494979}, {64563, 34495491}, {64564, 34496003}, {64565, 34496515}, + {64566, 34497027}, {64567, 34497539}, {64568, 34498051}, {64569, 34498563}, + {64570, 34499075}, {64571, 34499587}, {64572, 34500099}, {64573, 34500611}, + {64574, 34501123}, {64575, 34501635}, {64576, 34502147}, {64577, 34502659}, + {64578, 34503171}, {64579, 34503683}, {64580, 34504195}, {64581, 34504707}, + {64582, 34481411}, {64583, 34481923}, {64584, 34505219}, {64585, 34505731}, + {64586, 34506243}, {64587, 34506755}, {64588, 34507267}, {64589, 34507779}, + {64590, 34508291}, {64591, 34508803}, {64592, 34509315}, {64593, 34509827}, + {64594, 34510339}, {64595, 34510851}, {64596, 34511363}, {64597, 34480387}, + {64598, 34511875}, {64599, 34512387}, {64600, 34504451}, {64601, 34512899}, + {64602, 34511619}, {64603, 34513411}, {64604, 34513923}, {64605, 34514435}, + {64606, 51292163}, {64607, 51292931}, {64608, 51293699}, {64609, 51294467}, + {64610, 51295235}, {64611, 51296003}, {64612, 34519555}, {64613, 34520067}, + {64614, 34471427}, {64615, 34520579}, {64616, 34469635}, {64617, 34471939}, + {64618, 34521091}, {64619, 34521603}, {64620, 34473987}, {64621, 34522115}, + {64622, 34474499}, {64623, 34475011}, {64624, 34522627}, {64625, 34523139}, + {64626, 34477059}, {64627, 34523651}, {64628, 34477571}, {64629, 34478083}, + {64630, 34524163}, {64631, 34524675}, {64632, 34479107}, {64633, 34525187}, + {64634, 34479619}, {64635, 34480131}, {64636, 34494467}, {64637, 34494979}, + {64638, 34496515}, {64639, 34497027}, {64640, 34497539}, {64641, 34499587}, + {64642, 34500099}, {64643, 34500611}, {64644, 34501123}, {64645, 34503171}, + {64646, 34503683}, {64647, 34504195}, {64648, 34525699}, {64649, 34505219}, + {64650, 34526211}, {64651, 34526723}, {64652, 34508291}, {64653, 34527235}, + {64654, 34508803}, {64655, 34509315}, {64656, 34514435}, {64657, 34527747}, + {64658, 34528259}, {64659, 34504451}, {64660, 34506499}, {64661, 34512899}, + {64662, 34511619}, {64663, 34470403}, {64664, 34470915}, {64665, 34528771}, + {64666, 34471427}, {64667, 34529283}, {64668, 34472451}, {64669, 34472963}, + {64670, 34473475}, {64671, 34473987}, {64672, 34529795}, {64673, 34475523}, + {64674, 34476035}, {64675, 34476547}, {64676, 34477059}, {64677, 34530307}, + {64678, 34479107}, {64679, 34480643}, {64680, 34481155}, {64681, 34480899}, + {64682, 34481667}, {64683, 34482179}, {64684, 34483203}, {64685, 34483715}, + {64686, 34484227}, {64687, 34484739}, {64688, 34485251}, {64689, 34485763}, + {64690, 34530819}, {64691, 34486275}, {64692, 34486787}, {64693, 34487299}, + {64694, 34487811}, {64695, 34488323}, {64696, 34488835}, {64697, 34489859}, + {64698, 34490371}, {64699, 34490883}, {64700, 34491395}, {64701, 34491907}, + {64702, 34492419}, {64703, 34492931}, {64704, 34493443}, {64705, 34493955}, + {64706, 34495491}, {64707, 34496003}, {64708, 34498051}, {64709, 34498563}, + {64710, 34499075}, {64711, 34499587}, {64712, 34500099}, {64713, 34501635}, + {64714, 34502147}, {64715, 34502659}, {64716, 34503171}, {64717, 34531331}, + {64718, 34504707}, {64719, 34481411}, {64720, 34481923}, {64721, 34505219}, + {64722, 34506755}, {64723, 34507267}, {64724, 34507779}, {64725, 34508291}, + {64726, 34531843}, {64727, 34509827}, {64728, 34510339}, {64729, 34532355}, + {64730, 34480387}, {64731, 34511875}, {64732, 34512387}, {64733, 34504451}, + {64734, 34509571}, {64735, 34471427}, {64736, 34529283}, {64737, 34473987}, + {64738, 34529795}, {64739, 34477059}, {64740, 34530307}, {64741, 34479107}, + {64742, 34532867}, {64743, 34485251}, {64744, 34533379}, {64745, 34533891}, + {64746, 34534403}, {64747, 34499587}, {64748, 34500099}, {64749, 34503171}, + {64750, 34508291}, {64751, 34531843}, {64752, 34504451}, {64753, 34509571}, + {64754, 51312131}, {64755, 51312899}, {64756, 51313667}, {64757, 34537219}, + {64758, 34537731}, {64759, 34538243}, {64760, 34538755}, {64761, 34539267}, + {64762, 34539779}, {64763, 34540291}, {64764, 34540803}, {64765, 34541315}, + {64766, 34541827}, {64767, 34542339}, {64768, 34512131}, {64769, 34542851}, + {64770, 34543363}, {64771, 34543875}, {64772, 34512643}, {64773, 34544387}, + {64774, 34544899}, {64775, 34545411}, {64776, 34545923}, {64777, 34546435}, + {64778, 34546947}, {64779, 34547459}, {64780, 34533891}, {64781, 34547971}, + {64782, 34548483}, {64783, 34548995}, {64784, 34549507}, {64785, 34537219}, + {64786, 34537731}, {64787, 34538243}, {64788, 34538755}, {64789, 34539267}, + {64790, 34539779}, {64791, 34540291}, {64792, 34540803}, {64793, 34541315}, + {64794, 34541827}, {64795, 34542339}, {64796, 34512131}, {64797, 34542851}, + {64798, 34543363}, {64799, 34543875}, {64800, 34512643}, {64801, 34544387}, + {64802, 34544899}, {64803, 34545411}, {64804, 34545923}, {64805, 34546435}, + {64806, 34546947}, {64807, 34547459}, {64808, 34533891}, {64809, 34547971}, + {64810, 34548483}, {64811, 34548995}, {64812, 34549507}, {64813, 34546435}, + {64814, 34546947}, {64815, 34547459}, {64816, 34533891}, {64817, 34533379}, + {64818, 34534403}, {64819, 34489347}, {64820, 34483715}, {64821, 34484227}, + {64822, 34484739}, {64823, 34546435}, {64824, 34546947}, {64825, 34547459}, + {64826, 34489347}, {64827, 34489859}, {64828, 34550019}, {64830, 1}, + {64848, 51327747}, {64849, 51328515}, {64851, 51329283}, {64852, 51330051}, + {64853, 51330819}, {64854, 51331587}, {64855, 51332355}, {64856, 51258371}, + {64858, 51333123}, {64859, 51333891}, {64860, 51334659}, {64861, 51335427}, + {64862, 51336195}, {64863, 51336963}, {64865, 51337731}, {64866, 51338499}, + {64868, 51339267}, {64870, 51340035}, {64871, 51340803}, {64873, 51341571}, + {64874, 51342339}, {64876, 51343107}, {64878, 51343875}, {64879, 51344643}, + {64881, 51345411}, {64883, 51346179}, {64884, 51346947}, {64885, 51347715}, + {64886, 51348483}, {64888, 51349251}, {64889, 51350019}, {64890, 51350787}, + {64891, 51351555}, {64892, 51352323}, {64894, 51353091}, {64895, 51353859}, + {64896, 51354627}, {64897, 51355395}, {64898, 51356163}, {64899, 51356931}, + {64901, 51357699}, {64903, 51358467}, {64905, 51359235}, {64906, 51258627}, + {64907, 51360003}, {64908, 51360771}, {64909, 51281923}, {64910, 51259139}, + {64911, 51361539}, {64912, 2}, {64914, 51362307}, {64915, 51363075}, + {64916, 51363843}, {64917, 51364611}, {64918, 51365379}, {64919, 51366147}, + {64921, 51366915}, {64922, 51367683}, {64923, 51368451}, {64924, 51369219}, + {64926, 51369987}, {64927, 51370755}, {64928, 51371523}, {64929, 51372291}, + {64930, 51373059}, {64931, 51373827}, {64932, 51374595}, {64933, 51375363}, + {64934, 51376131}, {64935, 51376899}, {64936, 51377667}, {64937, 51378435}, + {64938, 51379203}, {64939, 51379971}, {64940, 51380739}, {64941, 51381507}, + {64942, 51289091}, {64943, 51382275}, {64944, 51383043}, {64945, 51383811}, + {64946, 51384579}, {64947, 51385347}, {64948, 51353091}, {64949, 51354627}, + {64950, 51386115}, {64951, 51386883}, {64952, 51387651}, {64953, 51388419}, + {64954, 51389187}, {64955, 51389955}, {64956, 51389187}, {64957, 51387651}, + {64958, 51390723}, {64959, 51391491}, {64960, 51392259}, {64961, 51393027}, + {64962, 51393795}, {64963, 51389955}, {64964, 51347715}, {64965, 51340035}, + {64966, 51394563}, {64967, 51395331}, {64968, 2}, {64975, 1}, + {64976, 2}, {65008, 51396099}, {65009, 51396867}, {65010, 68174851}, + {65011, 68175875}, {65012, 68176899}, {65013, 68177923}, {65014, 68178947}, + {65015, 68179971}, {65016, 68180995}, {65017, 51404803}, {65018, 303063811}, + {65019, 135296259}, {65020, 68189443}, {65021, 1}, {65024, 0}, + {65040, 17858819}, {65041, 17859075}, {65042, 2}, {65043, 17121027}, + {65044, 16848643}, {65045, 17042947}, {65046, 17043971}, {65047, 17859331}, + {65048, 17859587}, {65049, 2}, {65056, 1}, {65072, 2}, + {65073, 17859843}, {65074, 17860099}, {65075, 17860355}, {65077, 17047811}, + {65078, 17048067}, {65079, 17860611}, {65080, 17860867}, {65081, 17861123}, + {65082, 17861379}, {65083, 17861635}, {65084, 17861891}, {65085, 17862147}, + {65086, 17862403}, {65087, 17077763}, {65088, 17078019}, {65089, 17862659}, + {65090, 17862915}, {65091, 17863171}, {65092, 17863427}, {65093, 1}, + {65095, 17863683}, {65096, 17863939}, {65097, 33820675}, {65101, 17860355}, + {65104, 17858819}, {65105, 17859075}, {65106, 2}, {65108, 16848643}, + {65109, 17121027}, {65110, 17043971}, {65111, 17042947}, {65112, 17859843}, + {65113, 17047811}, {65114, 17048067}, {65115, 17860611}, {65116, 17860867}, + {65117, 17861123}, {65118, 17861379}, {65119, 17864195}, {65120, 17864451}, + {65121, 17864707}, {65122, 17047043}, {65123, 17864963}, {65124, 17865219}, + {65125, 17865475}, {65126, 17047555}, {65127, 2}, {65128, 17865731}, + {65129, 17865987}, {65130, 17866243}, {65131, 17866499}, {65132, 2}, + {65136, 34643971}, {65137, 34644483}, {65138, 34514947}, {65139, 1}, + {65140, 34515715}, {65141, 2}, {65142, 34516483}, {65143, 34534915}, + {65144, 34517251}, {65145, 34535683}, {65146, 34518019}, {65147, 34536451}, + {65148, 34518787}, {65149, 34644995}, {65150, 34645507}, {65151, 34646019}, + {65152, 17869315}, {65153, 17869571}, {65155, 17869827}, {65157, 17870083}, + {65159, 17870339}, {65161, 17688835}, {65165, 16910595}, {65167, 17695235}, + {65171, 17870595}, {65173, 17698307}, {65177, 17701379}, {65181, 17693443}, + {65185, 17693955}, {65189, 17696515}, {65193, 17846019}, {65195, 17736195}, + {65197, 17736707}, {65199, 17743107}, {65201, 17706499}, {65205, 17756675}, + {65209, 17708547}, {65213, 17709571}, {65217, 17711619}, {65221, 17712643}, + {65225, 17713155}, {65229, 17714179}, {65233, 17715203}, {65237, 17718275}, + {65241, 17720323}, {65245, 17722627}, {65249, 17694467}, {65253, 17729539}, + {65257, 17732611}, {65261, 16911107}, {65263, 17688579}, {65265, 16912131}, + {65269, 34648067}, {65271, 34648579}, {65273, 34649091}, {65275, 34633987}, + {65277, 2}, {65279, 0}, {65280, 2}, {65281, 17042947}, + {65282, 17872387}, {65283, 17864195}, {65284, 17865987}, {65285, 17866243}, + {65286, 17864451}, {65287, 17872643}, {65288, 17047811}, {65289, 17048067}, + {65290, 17864707}, {65291, 17047043}, {65292, 17858819}, {65293, 17864963}, + {65294, 17207043}, {65295, 17048579}, {65296, 17045507}, {65297, 16786947}, + {65298, 16785155}, {65299, 16785411}, {65300, 16787715}, {65301, 17045763}, + {65302, 17046019}, {65303, 17046275}, {65304, 17046531}, {65305, 17046787}, + {65306, 17121027}, {65307, 16848643}, {65308, 17865219}, {65309, 17047555}, + {65310, 17865475}, {65311, 17043971}, {65312, 17866499}, {65313, 16777219}, + {65314, 16777475}, {65315, 16777731}, {65316, 16777987}, {65317, 16778243}, + {65318, 16778499}, {65319, 16778755}, {65320, 16779011}, {65321, 16779267}, + {65322, 16779523}, {65323, 16779779}, {65324, 16780035}, {65325, 16780291}, + {65326, 16780547}, {65327, 16780803}, {65328, 16781059}, {65329, 16781315}, + {65330, 16781571}, {65331, 16781827}, {65332, 16782083}, {65333, 16782339}, + {65334, 16782595}, {65335, 16782851}, {65336, 16783107}, {65337, 16783363}, + {65338, 16783619}, {65339, 17863683}, {65340, 17865731}, {65341, 17863939}, + {65342, 17872899}, {65343, 17860355}, {65344, 17037059}, {65345, 16777219}, + {65346, 16777475}, {65347, 16777731}, {65348, 16777987}, {65349, 16778243}, + {65350, 16778499}, {65351, 16778755}, {65352, 16779011}, {65353, 16779267}, + {65354, 16779523}, {65355, 16779779}, {65356, 16780035}, {65357, 16780291}, + {65358, 16780547}, {65359, 16780803}, {65360, 16781059}, {65361, 16781315}, + {65362, 16781571}, {65363, 16781827}, {65364, 16782083}, {65365, 16782339}, + {65366, 16782595}, {65367, 16782851}, {65368, 16783107}, {65369, 16783363}, + {65370, 16783619}, {65371, 17860611}, {65372, 17873155}, {65373, 17860867}, + {65374, 17873411}, {65375, 17873667}, {65376, 17873923}, {65377, 17207043}, + {65378, 17862659}, {65379, 17862915}, {65380, 17859075}, {65381, 17874179}, + {65382, 17327363}, {65383, 17329923}, {65384, 17372931}, {65385, 17874435}, + {65386, 17374467}, {65387, 17334019}, {65388, 17874691}, {65389, 17344259}, + {65390, 17390083}, {65391, 17339651}, {65392, 17328643}, {65393, 17316099}, + {65394, 17316355}, {65395, 17316611}, {65396, 17316867}, {65397, 17317123}, + {65398, 17317379}, {65399, 17317635}, {65400, 17317891}, {65401, 17318147}, + {65402, 17209603}, {65403, 17318403}, {65404, 17318659}, {65405, 17318915}, + {65406, 17319171}, {65407, 17319427}, {65408, 17319683}, {65409, 17319939}, + {65410, 17320195}, {65411, 17320451}, {65412, 17209859}, {65413, 17320707}, + {65414, 17320963}, {65415, 17321219}, {65416, 17321475}, {65417, 17321731}, + {65418, 17321987}, {65419, 17322243}, {65420, 17322499}, {65421, 17322755}, + {65422, 17323011}, {65423, 17323267}, {65424, 17323523}, {65425, 17323779}, + {65426, 17324035}, {65427, 17324291}, {65428, 17324547}, {65429, 17324803}, + {65430, 17325059}, {65431, 17325315}, {65432, 17325571}, {65433, 17325827}, + {65434, 17326083}, {65435, 17326339}, {65436, 17326595}, {65437, 17330435}, + {65438, 17208323}, {65439, 17208835}, {65440, 0}, {65441, 17210115}, + {65442, 17210371}, {65443, 17210627}, {65444, 17210883}, {65445, 17211139}, + {65446, 17211395}, {65447, 17211651}, {65448, 17211907}, {65449, 17212163}, + {65450, 17212419}, {65451, 17212675}, {65452, 17212931}, {65453, 17213187}, + {65454, 17213443}, {65455, 17213699}, {65456, 17213955}, {65457, 17214211}, + {65458, 17214467}, {65459, 17214723}, {65460, 17214979}, {65461, 17215235}, + {65462, 17215491}, {65463, 17215747}, {65464, 17216003}, {65465, 17216259}, + {65466, 17216515}, {65467, 17216771}, {65468, 17217027}, {65469, 17217283}, + {65470, 17217539}, {65471, 2}, {65474, 17217795}, {65475, 17218051}, + {65476, 17218307}, {65477, 17218563}, {65478, 17218819}, {65479, 17219075}, + {65480, 2}, {65482, 17219331}, {65483, 17219587}, {65484, 17219843}, + {65485, 17220099}, {65486, 17220355}, {65487, 17220611}, {65488, 2}, + {65490, 17220867}, {65491, 17221123}, {65492, 17221379}, {65493, 17221635}, + {65494, 17221891}, {65495, 17222147}, {65496, 2}, {65498, 17222403}, + {65499, 17222659}, {65500, 17222915}, {65501, 2}, {65504, 17874947}, + {65505, 17875203}, {65506, 17875459}, {65507, 33561859}, {65508, 17875715}, + {65509, 17875971}, {65510, 17876227}, {65511, 2}, {65512, 17876483}, + {65513, 17876739}, {65514, 17876995}, {65515, 17877251}, {65516, 17877507}, + {65517, 17877763}, {65518, 17878019}, {65519, 2}, {65536, 1}, + {65548, 2}, {65549, 1}, {65575, 2}, {65576, 1}, + {65595, 2}, {65596, 1}, {65598, 2}, {65599, 1}, + {65614, 2}, {65616, 1}, {65630, 2}, {65664, 1}, + {65787, 2}, {65792, 1}, {65795, 2}, {65799, 1}, + {65844, 2}, {65847, 1}, {65935, 2}, {65936, 1}, + {65949, 2}, {65952, 1}, {65953, 2}, {66000, 1}, + {66046, 2}, {66176, 1}, {66205, 2}, {66208, 1}, + {66257, 2}, {66272, 1}, {66300, 2}, {66304, 1}, + {66340, 2}, {66349, 1}, {66379, 2}, {66384, 1}, + {66427, 2}, {66432, 1}, {66462, 2}, {66463, 1}, + {66500, 2}, {66504, 1}, {66518, 2}, {66560, 17878275}, + {66561, 17878531}, {66562, 17878787}, {66563, 17879043}, {66564, 17879299}, + {66565, 17879555}, {66566, 17879811}, {66567, 17880067}, {66568, 17880323}, + {66569, 17880579}, {66570, 17880835}, {66571, 17881091}, {66572, 17881347}, + {66573, 17881603}, {66574, 17881859}, {66575, 17882115}, {66576, 17882371}, + {66577, 17882627}, {66578, 17882883}, {66579, 17883139}, {66580, 17883395}, + {66581, 17883651}, {66582, 17883907}, {66583, 17884163}, {66584, 17884419}, + {66585, 17884675}, {66586, 17884931}, {66587, 17885187}, {66588, 17885443}, + {66589, 17885699}, {66590, 17885955}, {66591, 17886211}, {66592, 17886467}, + {66593, 17886723}, {66594, 17886979}, {66595, 17887235}, {66596, 17887491}, + {66597, 17887747}, {66598, 17888003}, {66599, 17888259}, {66600, 1}, + {66718, 2}, {66720, 1}, {66730, 2}, {66736, 17888515}, + {66737, 17888771}, {66738, 17889027}, {66739, 17889283}, {66740, 17889539}, + {66741, 17889795}, {66742, 17890051}, {66743, 17890307}, {66744, 17890563}, + {66745, 17890819}, {66746, 17891075}, {66747, 17891331}, {66748, 17891587}, + {66749, 17891843}, {66750, 17892099}, {66751, 17892355}, {66752, 17892611}, + {66753, 17892867}, {66754, 17893123}, {66755, 17893379}, {66756, 17893635}, + {66757, 17893891}, {66758, 17894147}, {66759, 17894403}, {66760, 17894659}, + {66761, 17894915}, {66762, 17895171}, {66763, 17895427}, {66764, 17895683}, + {66765, 17895939}, {66766, 17896195}, {66767, 17896451}, {66768, 17896707}, + {66769, 17896963}, {66770, 17897219}, {66771, 17897475}, {66772, 2}, + {66776, 1}, {66812, 2}, {66816, 1}, {66856, 2}, + {66864, 1}, {66916, 2}, {66927, 1}, {66928, 17897731}, + {66929, 17897987}, {66930, 17898243}, {66931, 17898499}, {66932, 17898755}, + {66933, 17899011}, {66934, 17899267}, {66935, 17899523}, {66936, 17899779}, + {66937, 17900035}, {66938, 17900291}, {66939, 2}, {66940, 17900547}, + {66941, 17900803}, {66942, 17901059}, {66943, 17901315}, {66944, 17901571}, + {66945, 17901827}, {66946, 17902083}, {66947, 17902339}, {66948, 17902595}, + {66949, 17902851}, {66950, 17903107}, {66951, 17903363}, {66952, 17903619}, + {66953, 17903875}, {66954, 17904131}, {66955, 2}, {66956, 17904387}, + {66957, 17904643}, {66958, 17904899}, {66959, 17905155}, {66960, 17905411}, + {66961, 17905667}, {66962, 17905923}, {66963, 2}, {66964, 17906179}, + {66965, 17906435}, {66966, 2}, {66967, 1}, {66978, 2}, + {66979, 1}, {66994, 2}, {66995, 1}, {67002, 2}, + {67003, 1}, {67005, 2}, {67008, 1}, {67060, 2}, + {67072, 1}, {67383, 2}, {67392, 1}, {67414, 2}, + {67424, 1}, {67432, 2}, {67456, 1}, {67457, 17906691}, + {67458, 17906947}, {67459, 16791043}, {67460, 17907203}, {67461, 16814083}, + {67462, 2}, {67463, 17907459}, {67464, 17907715}, {67465, 17907971}, + {67466, 17908227}, {67467, 16815363}, {67468, 16815619}, {67469, 17908483}, + {67470, 17908739}, {67471, 17908995}, {67472, 17909251}, {67473, 17527555}, + {67474, 17909507}, {67475, 16817155}, {67476, 17909763}, {67477, 16802051}, + {67478, 17910019}, {67479, 17910275}, {67480, 17910531}, {67481, 17910787}, + {67482, 17911043}, {67483, 17523459}, {67484, 17911299}, {67485, 17911555}, + {67486, 17911811}, {67487, 17912067}, {67488, 17912323}, {67489, 17912579}, + {67490, 16795395}, {67491, 17912835}, {67492, 17913091}, {67493, 16781315}, + {67494, 17913347}, {67495, 17913603}, {67496, 17135875}, {67497, 17913859}, + {67498, 16819971}, {67499, 17914115}, {67500, 17914371}, {67501, 17914627}, + {67502, 17914883}, {67503, 16820995}, {67504, 17915139}, {67505, 2}, + {67506, 17915395}, {67507, 17915651}, {67508, 17915907}, {67509, 17916163}, + {67510, 17916419}, {67511, 17916675}, {67512, 17916931}, {67513, 17917187}, + {67514, 17917443}, {67515, 2}, {67584, 1}, {67590, 2}, + {67592, 1}, {67593, 2}, {67594, 1}, {67638, 2}, + {67639, 1}, {67641, 2}, {67644, 1}, {67645, 2}, + {67647, 1}, {67670, 2}, {67671, 1}, {67743, 2}, + {67751, 1}, {67760, 2}, {67808, 1}, {67827, 2}, + {67828, 1}, {67830, 2}, {67835, 1}, {67868, 2}, + {67871, 1}, {67898, 2}, {67903, 1}, {67904, 2}, + {67968, 1}, {68024, 2}, {68028, 1}, {68048, 2}, + {68050, 1}, {68100, 2}, {68101, 1}, {68103, 2}, + {68108, 1}, {68116, 2}, {68117, 1}, {68120, 2}, + {68121, 1}, {68150, 2}, {68152, 1}, {68155, 2}, + {68159, 1}, {68169, 2}, {68176, 1}, {68185, 2}, + {68192, 1}, {68256, 2}, {68288, 1}, {68327, 2}, + {68331, 1}, {68343, 2}, {68352, 1}, {68406, 2}, + {68409, 1}, {68438, 2}, {68440, 1}, {68467, 2}, + {68472, 1}, {68498, 2}, {68505, 1}, {68509, 2}, + {68521, 1}, {68528, 2}, {68608, 1}, {68681, 2}, + {68736, 17917699}, {68737, 17917955}, {68738, 17918211}, {68739, 17918467}, + {68740, 17918723}, {68741, 17918979}, {68742, 17919235}, {68743, 17919491}, + {68744, 17919747}, {68745, 17920003}, {68746, 17920259}, {68747, 17920515}, + {68748, 17920771}, {68749, 17921027}, {68750, 17921283}, {68751, 17921539}, + {68752, 17921795}, {68753, 17922051}, {68754, 17922307}, {68755, 17922563}, + {68756, 17922819}, {68757, 17923075}, {68758, 17923331}, {68759, 17923587}, + {68760, 17923843}, {68761, 17924099}, {68762, 17924355}, {68763, 17924611}, + {68764, 17924867}, {68765, 17925123}, {68766, 17925379}, {68767, 17925635}, + {68768, 17925891}, {68769, 17926147}, {68770, 17926403}, {68771, 17926659}, + {68772, 17926915}, {68773, 17927171}, {68774, 17927427}, {68775, 17927683}, + {68776, 17927939}, {68777, 17928195}, {68778, 17928451}, {68779, 17928707}, + {68780, 17928963}, {68781, 17929219}, {68782, 17929475}, {68783, 17929731}, + {68784, 17929987}, {68785, 17930243}, {68786, 17930499}, {68787, 2}, + {68800, 1}, {68851, 2}, {68858, 1}, {68904, 2}, + {68912, 1}, {68922, 2}, {68928, 1}, {68944, 17930755}, + {68945, 17931011}, {68946, 17931267}, {68947, 17931523}, {68948, 17931779}, + {68949, 17932035}, {68950, 17932291}, {68951, 17932547}, {68952, 17932803}, + {68953, 17933059}, {68954, 17933315}, {68955, 17933571}, {68956, 17933827}, + {68957, 17934083}, {68958, 17934339}, {68959, 17934595}, {68960, 17934851}, + {68961, 17935107}, {68962, 17935363}, {68963, 17935619}, {68964, 17935875}, + {68965, 17936131}, {68966, 2}, {68969, 1}, {68998, 2}, + {69006, 1}, {69008, 2}, {69216, 1}, {69247, 2}, + {69248, 1}, {69290, 2}, {69291, 1}, {69294, 2}, + {69296, 1}, {69298, 2}, {69314, 1}, {69317, 2}, + {69372, 1}, {69416, 2}, {69424, 1}, {69466, 2}, + {69488, 1}, {69514, 2}, {69552, 1}, {69580, 2}, + {69600, 1}, {69623, 2}, {69632, 1}, {69710, 2}, + {69714, 1}, {69750, 2}, {69759, 1}, {69821, 2}, + {69822, 1}, {69827, 2}, {69840, 1}, {69865, 2}, + {69872, 1}, {69882, 2}, {69888, 1}, {69941, 2}, + {69942, 1}, {69960, 2}, {69968, 1}, {70007, 2}, + {70016, 1}, {70112, 2}, {70113, 1}, {70133, 2}, + {70144, 1}, {70162, 2}, {70163, 1}, {70210, 2}, + {70272, 1}, {70279, 2}, {70280, 1}, {70281, 2}, + {70282, 1}, {70286, 2}, {70287, 1}, {70302, 2}, + {70303, 1}, {70314, 2}, {70320, 1}, {70379, 2}, + {70384, 1}, {70394, 2}, {70400, 1}, {70404, 2}, + {70405, 1}, {70413, 2}, {70415, 1}, {70417, 2}, + {70419, 1}, {70441, 2}, {70442, 1}, {70449, 2}, + {70450, 1}, {70452, 2}, {70453, 1}, {70458, 2}, + {70459, 1}, {70469, 2}, {70471, 1}, {70473, 2}, + {70475, 1}, {70478, 2}, {70480, 1}, {70481, 2}, + {70487, 1}, {70488, 2}, {70493, 1}, {70500, 2}, + {70502, 1}, {70509, 2}, {70512, 1}, {70517, 2}, + {70528, 1}, {70538, 2}, {70539, 1}, {70540, 2}, + {70542, 1}, {70543, 2}, {70544, 1}, {70582, 2}, + {70583, 1}, {70593, 2}, {70594, 1}, {70595, 2}, + {70597, 1}, {70598, 2}, {70599, 1}, {70603, 2}, + {70604, 1}, {70614, 2}, {70615, 1}, {70617, 2}, + {70625, 1}, {70627, 2}, {70656, 1}, {70748, 2}, + {70749, 1}, {70754, 2}, {70784, 1}, {70856, 2}, + {70864, 1}, {70874, 2}, {71040, 1}, {71094, 2}, + {71096, 1}, {71134, 2}, {71168, 1}, {71237, 2}, + {71248, 1}, {71258, 2}, {71264, 1}, {71277, 2}, + {71296, 1}, {71354, 2}, {71360, 1}, {71370, 2}, + {71376, 1}, {71396, 2}, {71424, 1}, {71451, 2}, + {71453, 1}, {71468, 2}, {71472, 1}, {71495, 2}, + {71680, 1}, {71740, 2}, {71840, 17936387}, {71841, 17936643}, + {71842, 17936899}, {71843, 17937155}, {71844, 17937411}, {71845, 17937667}, + {71846, 17937923}, {71847, 17938179}, {71848, 17938435}, {71849, 17938691}, + {71850, 17938947}, {71851, 17939203}, {71852, 17939459}, {71853, 17939715}, + {71854, 17939971}, {71855, 17940227}, {71856, 17940483}, {71857, 17940739}, + {71858, 17940995}, {71859, 17941251}, {71860, 17941507}, {71861, 17941763}, + {71862, 17942019}, {71863, 17942275}, {71864, 17942531}, {71865, 17942787}, + {71866, 17943043}, {71867, 17943299}, {71868, 17943555}, {71869, 17943811}, + {71870, 17944067}, {71871, 17944323}, {71872, 1}, {71923, 2}, + {71935, 1}, {71943, 2}, {71945, 1}, {71946, 2}, + {71948, 1}, {71956, 2}, {71957, 1}, {71959, 2}, + {71960, 1}, {71990, 2}, {71991, 1}, {71993, 2}, + {71995, 1}, {72007, 2}, {72016, 1}, {72026, 2}, + {72096, 1}, {72104, 2}, {72106, 1}, {72152, 2}, + {72154, 1}, {72165, 2}, {72192, 1}, {72264, 2}, + {72272, 1}, {72355, 2}, {72368, 1}, {72441, 2}, + {72448, 1}, {72458, 2}, {72640, 1}, {72674, 2}, + {72688, 1}, {72698, 2}, {72704, 1}, {72713, 2}, + {72714, 1}, {72759, 2}, {72760, 1}, {72774, 2}, + {72784, 1}, {72813, 2}, {72816, 1}, {72848, 2}, + {72850, 1}, {72872, 2}, {72873, 1}, {72887, 2}, + {72960, 1}, {72967, 2}, {72968, 1}, {72970, 2}, + {72971, 1}, {73015, 2}, {73018, 1}, {73019, 2}, + {73020, 1}, {73022, 2}, {73023, 1}, {73032, 2}, + {73040, 1}, {73050, 2}, {73056, 1}, {73062, 2}, + {73063, 1}, {73065, 2}, {73066, 1}, {73103, 2}, + {73104, 1}, {73106, 2}, {73107, 1}, {73113, 2}, + {73120, 1}, {73130, 2}, {73440, 1}, {73465, 2}, + {73472, 1}, {73489, 2}, {73490, 1}, {73531, 2}, + {73534, 1}, {73563, 2}, {73648, 1}, {73649, 2}, + {73664, 1}, {73714, 2}, {73727, 1}, {74650, 2}, + {74752, 1}, {74863, 2}, {74864, 1}, {74869, 2}, + {74880, 1}, {75076, 2}, {77712, 1}, {77811, 2}, + {77824, 1}, {78896, 2}, {78912, 1}, {78934, 2}, + {78944, 1}, {82939, 2}, {82944, 1}, {83527, 2}, + {90368, 1}, {90426, 2}, {92160, 1}, {92729, 2}, + {92736, 1}, {92767, 2}, {92768, 1}, {92778, 2}, + {92782, 1}, {92863, 2}, {92864, 1}, {92874, 2}, + {92880, 1}, {92910, 2}, {92912, 1}, {92918, 2}, + {92928, 1}, {92998, 2}, {93008, 1}, {93018, 2}, + {93019, 1}, {93026, 2}, {93027, 1}, {93048, 2}, + {93053, 1}, {93072, 2}, {93504, 1}, {93562, 2}, + {93760, 17944579}, {93761, 17944835}, {93762, 17945091}, {93763, 17945347}, + {93764, 17945603}, {93765, 17945859}, {93766, 17946115}, {93767, 17946371}, + {93768, 17946627}, {93769, 17946883}, {93770, 17947139}, {93771, 17947395}, + {93772, 17947651}, {93773, 17947907}, {93774, 17948163}, {93775, 17948419}, + {93776, 17948675}, {93777, 17948931}, {93778, 17949187}, {93779, 17949443}, + {93780, 17949699}, {93781, 17949955}, {93782, 17950211}, {93783, 17950467}, + {93784, 17950723}, {93785, 17950979}, {93786, 17951235}, {93787, 17951491}, + {93788, 17951747}, {93789, 17952003}, {93790, 17952259}, {93791, 17952515}, + {93792, 1}, {93851, 2}, {93952, 1}, {94027, 2}, + {94031, 1}, {94088, 2}, {94095, 1}, {94112, 2}, + {94176, 1}, {94181, 2}, {94192, 1}, {94194, 2}, + {94208, 1}, {100344, 2}, {100352, 1}, {101590, 2}, + {101631, 1}, {101641, 2}, {110576, 1}, {110580, 2}, + {110581, 1}, {110588, 2}, {110589, 1}, {110591, 2}, + {110592, 1}, {110883, 2}, {110898, 1}, {110899, 2}, + {110928, 1}, {110931, 2}, {110933, 1}, {110934, 2}, + {110948, 1}, {110952, 2}, {110960, 1}, {111356, 2}, + {113664, 1}, {113771, 2}, {113776, 1}, {113789, 2}, + {113792, 1}, {113801, 2}, {113808, 1}, {113818, 2}, + {113820, 1}, {113824, 0}, {113828, 2}, {117760, 1}, + {117974, 16777219}, {117975, 16777475}, {117976, 16777731}, {117977, 16777987}, + {117978, 16778243}, {117979, 16778499}, {117980, 16778755}, {117981, 16779011}, + {117982, 16779267}, {117983, 16779523}, {117984, 16779779}, {117985, 16780035}, + {117986, 16780291}, {117987, 16780547}, {117988, 16780803}, {117989, 16781059}, + {117990, 16781315}, {117991, 16781571}, {117992, 16781827}, {117993, 16782083}, + {117994, 16782339}, {117995, 16782595}, {117996, 16782851}, {117997, 16783107}, + {117998, 16783363}, {117999, 16783619}, {118000, 17045507}, {118001, 16786947}, + {118002, 16785155}, {118003, 16785411}, {118004, 16787715}, {118005, 17045763}, + {118006, 17046019}, {118007, 17046275}, {118008, 17046531}, {118009, 17046787}, + {118010, 2}, {118016, 1}, {118452, 2}, {118528, 1}, + {118574, 2}, {118576, 1}, {118599, 2}, {118608, 1}, + {118724, 2}, {118784, 1}, {119030, 2}, {119040, 1}, + {119079, 2}, {119081, 1}, {119134, 34729987}, {119135, 34730499}, + {119136, 51508227}, {119137, 51508995}, {119138, 51509763}, {119139, 51510531}, + {119140, 51511299}, {119141, 1}, {119155, 0}, {119163, 1}, + {119227, 34734851}, {119228, 34735363}, {119229, 51513091}, {119230, 51513859}, + {119231, 51514627}, {119232, 51515395}, {119233, 1}, {119275, 2}, + {119296, 1}, {119366, 2}, {119488, 1}, {119508, 2}, + {119520, 1}, {119540, 2}, {119552, 1}, {119639, 2}, + {119648, 1}, {119673, 2}, {119808, 16777219}, {119809, 16777475}, + {119810, 16777731}, {119811, 16777987}, {119812, 16778243}, {119813, 16778499}, + {119814, 16778755}, {119815, 16779011}, {119816, 16779267}, {119817, 16779523}, + {119818, 16779779}, {119819, 16780035}, {119820, 16780291}, {119821, 16780547}, + {119822, 16780803}, {119823, 16781059}, {119824, 16781315}, {119825, 16781571}, + {119826, 16781827}, {119827, 16782083}, {119828, 16782339}, {119829, 16782595}, + {119830, 16782851}, {119831, 16783107}, {119832, 16783363}, {119833, 16783619}, + {119834, 16777219}, {119835, 16777475}, {119836, 16777731}, {119837, 16777987}, + {119838, 16778243}, {119839, 16778499}, {119840, 16778755}, {119841, 16779011}, + {119842, 16779267}, {119843, 16779523}, {119844, 16779779}, {119845, 16780035}, + {119846, 16780291}, {119847, 16780547}, {119848, 16780803}, {119849, 16781059}, + {119850, 16781315}, {119851, 16781571}, {119852, 16781827}, {119853, 16782083}, + {119854, 16782339}, {119855, 16782595}, {119856, 16782851}, {119857, 16783107}, + {119858, 16783363}, {119859, 16783619}, {119860, 16777219}, {119861, 16777475}, + {119862, 16777731}, {119863, 16777987}, {119864, 16778243}, {119865, 16778499}, + {119866, 16778755}, {119867, 16779011}, {119868, 16779267}, {119869, 16779523}, + {119870, 16779779}, {119871, 16780035}, {119872, 16780291}, {119873, 16780547}, + {119874, 16780803}, {119875, 16781059}, {119876, 16781315}, {119877, 16781571}, + {119878, 16781827}, {119879, 16782083}, {119880, 16782339}, {119881, 16782595}, + {119882, 16782851}, {119883, 16783107}, {119884, 16783363}, {119885, 16783619}, + {119886, 16777219}, {119887, 16777475}, {119888, 16777731}, {119889, 16777987}, + {119890, 16778243}, {119891, 16778499}, {119892, 16778755}, {119893, 2}, + {119894, 16779267}, {119895, 16779523}, {119896, 16779779}, {119897, 16780035}, + {119898, 16780291}, {119899, 16780547}, {119900, 16780803}, {119901, 16781059}, + {119902, 16781315}, {119903, 16781571}, {119904, 16781827}, {119905, 16782083}, + {119906, 16782339}, {119907, 16782595}, {119908, 16782851}, {119909, 16783107}, + {119910, 16783363}, {119911, 16783619}, {119912, 16777219}, {119913, 16777475}, + {119914, 16777731}, {119915, 16777987}, {119916, 16778243}, {119917, 16778499}, + {119918, 16778755}, {119919, 16779011}, {119920, 16779267}, {119921, 16779523}, + {119922, 16779779}, {119923, 16780035}, {119924, 16780291}, {119925, 16780547}, + {119926, 16780803}, {119927, 16781059}, {119928, 16781315}, {119929, 16781571}, + {119930, 16781827}, {119931, 16782083}, {119932, 16782339}, {119933, 16782595}, + {119934, 16782851}, {119935, 16783107}, {119936, 16783363}, {119937, 16783619}, + {119938, 16777219}, {119939, 16777475}, {119940, 16777731}, {119941, 16777987}, + {119942, 16778243}, {119943, 16778499}, {119944, 16778755}, {119945, 16779011}, + {119946, 16779267}, {119947, 16779523}, {119948, 16779779}, {119949, 16780035}, + {119950, 16780291}, {119951, 16780547}, {119952, 16780803}, {119953, 16781059}, + {119954, 16781315}, {119955, 16781571}, {119956, 16781827}, {119957, 16782083}, + {119958, 16782339}, {119959, 16782595}, {119960, 16782851}, {119961, 16783107}, + {119962, 16783363}, {119963, 16783619}, {119964, 16777219}, {119965, 2}, + {119966, 16777731}, {119967, 16777987}, {119968, 2}, {119970, 16778755}, + {119971, 2}, {119973, 16779523}, {119974, 16779779}, {119975, 2}, + {119977, 16780547}, {119978, 16780803}, {119979, 16781059}, {119980, 16781315}, + {119981, 2}, {119982, 16781827}, {119983, 16782083}, {119984, 16782339}, + {119985, 16782595}, {119986, 16782851}, {119987, 16783107}, {119988, 16783363}, + {119989, 16783619}, {119990, 16777219}, {119991, 16777475}, {119992, 16777731}, + {119993, 16777987}, {119994, 2}, {119995, 16778499}, {119996, 2}, + {119997, 16779011}, {119998, 16779267}, {119999, 16779523}, {120000, 16779779}, + {120001, 16780035}, {120002, 16780291}, {120003, 16780547}, {120004, 2}, + {120005, 16781059}, {120006, 16781315}, {120007, 16781571}, {120008, 16781827}, + {120009, 16782083}, {120010, 16782339}, {120011, 16782595}, {120012, 16782851}, + {120013, 16783107}, {120014, 16783363}, {120015, 16783619}, {120016, 16777219}, + {120017, 16777475}, {120018, 16777731}, {120019, 16777987}, {120020, 16778243}, + {120021, 16778499}, {120022, 16778755}, {120023, 16779011}, {120024, 16779267}, + {120025, 16779523}, {120026, 16779779}, {120027, 16780035}, {120028, 16780291}, + {120029, 16780547}, {120030, 16780803}, {120031, 16781059}, {120032, 16781315}, + {120033, 16781571}, {120034, 16781827}, {120035, 16782083}, {120036, 16782339}, + {120037, 16782595}, {120038, 16782851}, {120039, 16783107}, {120040, 16783363}, + {120041, 16783619}, {120042, 16777219}, {120043, 16777475}, {120044, 16777731}, + {120045, 16777987}, {120046, 16778243}, {120047, 16778499}, {120048, 16778755}, + {120049, 16779011}, {120050, 16779267}, {120051, 16779523}, {120052, 16779779}, + {120053, 16780035}, {120054, 16780291}, {120055, 16780547}, {120056, 16780803}, + {120057, 16781059}, {120058, 16781315}, {120059, 16781571}, {120060, 16781827}, + {120061, 16782083}, {120062, 16782339}, {120063, 16782595}, {120064, 16782851}, + {120065, 16783107}, {120066, 16783363}, {120067, 16783619}, {120068, 16777219}, + {120069, 16777475}, {120070, 2}, {120071, 16777987}, {120072, 16778243}, + {120073, 16778499}, {120074, 16778755}, {120075, 2}, {120077, 16779523}, + {120078, 16779779}, {120079, 16780035}, {120080, 16780291}, {120081, 16780547}, + {120082, 16780803}, {120083, 16781059}, {120084, 16781315}, {120085, 2}, + {120086, 16781827}, {120087, 16782083}, {120088, 16782339}, {120089, 16782595}, + {120090, 16782851}, {120091, 16783107}, {120092, 16783363}, {120093, 2}, + {120094, 16777219}, {120095, 16777475}, {120096, 16777731}, {120097, 16777987}, + {120098, 16778243}, {120099, 16778499}, {120100, 16778755}, {120101, 16779011}, + {120102, 16779267}, {120103, 16779523}, {120104, 16779779}, {120105, 16780035}, + {120106, 16780291}, {120107, 16780547}, {120108, 16780803}, {120109, 16781059}, + {120110, 16781315}, {120111, 16781571}, {120112, 16781827}, {120113, 16782083}, + {120114, 16782339}, {120115, 16782595}, {120116, 16782851}, {120117, 16783107}, + {120118, 16783363}, {120119, 16783619}, {120120, 16777219}, {120121, 16777475}, + {120122, 2}, {120123, 16777987}, {120124, 16778243}, {120125, 16778499}, + {120126, 16778755}, {120127, 2}, {120128, 16779267}, {120129, 16779523}, + {120130, 16779779}, {120131, 16780035}, {120132, 16780291}, {120133, 2}, + {120134, 16780803}, {120135, 2}, {120138, 16781827}, {120139, 16782083}, + {120140, 16782339}, {120141, 16782595}, {120142, 16782851}, {120143, 16783107}, + {120144, 16783363}, {120145, 2}, {120146, 16777219}, {120147, 16777475}, + {120148, 16777731}, {120149, 16777987}, {120150, 16778243}, {120151, 16778499}, + {120152, 16778755}, {120153, 16779011}, {120154, 16779267}, {120155, 16779523}, + {120156, 16779779}, {120157, 16780035}, {120158, 16780291}, {120159, 16780547}, + {120160, 16780803}, {120161, 16781059}, {120162, 16781315}, {120163, 16781571}, + {120164, 16781827}, {120165, 16782083}, {120166, 16782339}, {120167, 16782595}, + {120168, 16782851}, {120169, 16783107}, {120170, 16783363}, {120171, 16783619}, + {120172, 16777219}, {120173, 16777475}, {120174, 16777731}, {120175, 16777987}, + {120176, 16778243}, {120177, 16778499}, {120178, 16778755}, {120179, 16779011}, + {120180, 16779267}, {120181, 16779523}, {120182, 16779779}, {120183, 16780035}, + {120184, 16780291}, {120185, 16780547}, {120186, 16780803}, {120187, 16781059}, + {120188, 16781315}, {120189, 16781571}, {120190, 16781827}, {120191, 16782083}, + {120192, 16782339}, {120193, 16782595}, {120194, 16782851}, {120195, 16783107}, + {120196, 16783363}, {120197, 16783619}, {120198, 16777219}, {120199, 16777475}, + {120200, 16777731}, {120201, 16777987}, {120202, 16778243}, {120203, 16778499}, + {120204, 16778755}, {120205, 16779011}, {120206, 16779267}, {120207, 16779523}, + {120208, 16779779}, {120209, 16780035}, {120210, 16780291}, {120211, 16780547}, + {120212, 16780803}, {120213, 16781059}, {120214, 16781315}, {120215, 16781571}, + {120216, 16781827}, {120217, 16782083}, {120218, 16782339}, {120219, 16782595}, + {120220, 16782851}, {120221, 16783107}, {120222, 16783363}, {120223, 16783619}, + {120224, 16777219}, {120225, 16777475}, {120226, 16777731}, {120227, 16777987}, + {120228, 16778243}, {120229, 16778499}, {120230, 16778755}, {120231, 16779011}, + {120232, 16779267}, {120233, 16779523}, {120234, 16779779}, {120235, 16780035}, + {120236, 16780291}, {120237, 16780547}, {120238, 16780803}, {120239, 16781059}, + {120240, 16781315}, {120241, 16781571}, {120242, 16781827}, {120243, 16782083}, + {120244, 16782339}, {120245, 16782595}, {120246, 16782851}, {120247, 16783107}, + {120248, 16783363}, {120249, 16783619}, {120250, 16777219}, {120251, 16777475}, + {120252, 16777731}, {120253, 16777987}, {120254, 16778243}, {120255, 16778499}, + {120256, 16778755}, {120257, 16779011}, {120258, 16779267}, {120259, 16779523}, + {120260, 16779779}, {120261, 16780035}, {120262, 16780291}, {120263, 16780547}, + {120264, 16780803}, {120265, 16781059}, {120266, 16781315}, {120267, 16781571}, + {120268, 16781827}, {120269, 16782083}, {120270, 16782339}, {120271, 16782595}, + {120272, 16782851}, {120273, 16783107}, {120274, 16783363}, {120275, 16783619}, + {120276, 16777219}, {120277, 16777475}, {120278, 16777731}, {120279, 16777987}, + {120280, 16778243}, {120281, 16778499}, {120282, 16778755}, {120283, 16779011}, + {120284, 16779267}, {120285, 16779523}, {120286, 16779779}, {120287, 16780035}, + {120288, 16780291}, {120289, 16780547}, {120290, 16780803}, {120291, 16781059}, + {120292, 16781315}, {120293, 16781571}, {120294, 16781827}, {120295, 16782083}, + {120296, 16782339}, {120297, 16782595}, {120298, 16782851}, {120299, 16783107}, + {120300, 16783363}, {120301, 16783619}, {120302, 16777219}, {120303, 16777475}, + {120304, 16777731}, {120305, 16777987}, {120306, 16778243}, {120307, 16778499}, + {120308, 16778755}, {120309, 16779011}, {120310, 16779267}, {120311, 16779523}, + {120312, 16779779}, {120313, 16780035}, {120314, 16780291}, {120315, 16780547}, + {120316, 16780803}, {120317, 16781059}, {120318, 16781315}, {120319, 16781571}, + {120320, 16781827}, {120321, 16782083}, {120322, 16782339}, {120323, 16782595}, + {120324, 16782851}, {120325, 16783107}, {120326, 16783363}, {120327, 16783619}, + {120328, 16777219}, {120329, 16777475}, {120330, 16777731}, {120331, 16777987}, + {120332, 16778243}, {120333, 16778499}, {120334, 16778755}, {120335, 16779011}, + {120336, 16779267}, {120337, 16779523}, {120338, 16779779}, {120339, 16780035}, + {120340, 16780291}, {120341, 16780547}, {120342, 16780803}, {120343, 16781059}, + {120344, 16781315}, {120345, 16781571}, {120346, 16781827}, {120347, 16782083}, + {120348, 16782339}, {120349, 16782595}, {120350, 16782851}, {120351, 16783107}, + {120352, 16783363}, {120353, 16783619}, {120354, 16777219}, {120355, 16777475}, + {120356, 16777731}, {120357, 16777987}, {120358, 16778243}, {120359, 16778499}, + {120360, 16778755}, {120361, 16779011}, {120362, 16779267}, {120363, 16779523}, + {120364, 16779779}, {120365, 16780035}, {120366, 16780291}, {120367, 16780547}, + {120368, 16780803}, {120369, 16781059}, {120370, 16781315}, {120371, 16781571}, + {120372, 16781827}, {120373, 16782083}, {120374, 16782339}, {120375, 16782595}, + {120376, 16782851}, {120377, 16783107}, {120378, 16783363}, {120379, 16783619}, + {120380, 16777219}, {120381, 16777475}, {120382, 16777731}, {120383, 16777987}, + {120384, 16778243}, {120385, 16778499}, {120386, 16778755}, {120387, 16779011}, + {120388, 16779267}, {120389, 16779523}, {120390, 16779779}, {120391, 16780035}, + {120392, 16780291}, {120393, 16780547}, {120394, 16780803}, {120395, 16781059}, + {120396, 16781315}, {120397, 16781571}, {120398, 16781827}, {120399, 16782083}, + {120400, 16782339}, {120401, 16782595}, {120402, 16782851}, {120403, 16783107}, + {120404, 16783363}, {120405, 16783619}, {120406, 16777219}, {120407, 16777475}, + {120408, 16777731}, {120409, 16777987}, {120410, 16778243}, {120411, 16778499}, + {120412, 16778755}, {120413, 16779011}, {120414, 16779267}, {120415, 16779523}, + {120416, 16779779}, {120417, 16780035}, {120418, 16780291}, {120419, 16780547}, + {120420, 16780803}, {120421, 16781059}, {120422, 16781315}, {120423, 16781571}, + {120424, 16781827}, {120425, 16782083}, {120426, 16782339}, {120427, 16782595}, + {120428, 16782851}, {120429, 16783107}, {120430, 16783363}, {120431, 16783619}, + {120432, 16777219}, {120433, 16777475}, {120434, 16777731}, {120435, 16777987}, + {120436, 16778243}, {120437, 16778499}, {120438, 16778755}, {120439, 16779011}, + {120440, 16779267}, {120441, 16779523}, {120442, 16779779}, {120443, 16780035}, + {120444, 16780291}, {120445, 16780547}, {120446, 16780803}, {120447, 16781059}, + {120448, 16781315}, {120449, 16781571}, {120450, 16781827}, {120451, 16782083}, + {120452, 16782339}, {120453, 16782595}, {120454, 16782851}, {120455, 16783107}, + {120456, 16783363}, {120457, 16783619}, {120458, 16777219}, {120459, 16777475}, + {120460, 16777731}, {120461, 16777987}, {120462, 16778243}, {120463, 16778499}, + {120464, 16778755}, {120465, 16779011}, {120466, 16779267}, {120467, 16779523}, + {120468, 16779779}, {120469, 16780035}, {120470, 16780291}, {120471, 16780547}, + {120472, 16780803}, {120473, 16781059}, {120474, 16781315}, {120475, 16781571}, + {120476, 16781827}, {120477, 16782083}, {120478, 16782339}, {120479, 16782595}, + {120480, 16782851}, {120481, 16783107}, {120482, 16783363}, {120483, 16783619}, + {120484, 17961731}, {120485, 17961987}, {120486, 2}, {120488, 16851715}, + {120489, 16851971}, {120490, 16852227}, {120491, 16852483}, {120492, 16852739}, + {120493, 16852995}, {120494, 16853251}, {120495, 16853507}, {120496, 16846851}, + {120497, 16853763}, {120498, 16854019}, {120499, 16786179}, {120500, 16854275}, + {120501, 16854531}, {120502, 16854787}, {120503, 16855043}, {120504, 16855299}, + {120505, 16853507}, {120506, 16855555}, {120507, 16855811}, {120508, 16856067}, + {120509, 16856323}, {120510, 16856579}, {120511, 16856835}, {120512, 16857091}, + {120513, 17962243}, {120514, 16851715}, {120515, 16851971}, {120516, 16852227}, + {120517, 16852483}, {120518, 16852739}, {120519, 16852995}, {120520, 16853251}, + {120521, 16853507}, {120522, 16846851}, {120523, 16853763}, {120524, 16854019}, + {120525, 16786179}, {120526, 16854275}, {120527, 16854531}, {120528, 16854787}, + {120529, 16855043}, {120530, 16855299}, {120531, 16855555}, {120533, 16855811}, + {120534, 16856067}, {120535, 16856323}, {120536, 16856579}, {120537, 16856835}, + {120538, 16857091}, {120539, 17962499}, {120540, 16852739}, {120541, 16853507}, + {120542, 16853763}, {120543, 16856323}, {120544, 16855299}, {120545, 16855043}, + {120546, 16851715}, {120547, 16851971}, {120548, 16852227}, {120549, 16852483}, + {120550, 16852739}, {120551, 16852995}, {120552, 16853251}, {120553, 16853507}, + {120554, 16846851}, {120555, 16853763}, {120556, 16854019}, {120557, 16786179}, + {120558, 16854275}, {120559, 16854531}, {120560, 16854787}, {120561, 16855043}, + {120562, 16855299}, {120563, 16853507}, {120564, 16855555}, {120565, 16855811}, + {120566, 16856067}, {120567, 16856323}, {120568, 16856579}, {120569, 16856835}, + {120570, 16857091}, {120571, 17962243}, {120572, 16851715}, {120573, 16851971}, + {120574, 16852227}, {120575, 16852483}, {120576, 16852739}, {120577, 16852995}, + {120578, 16853251}, {120579, 16853507}, {120580, 16846851}, {120581, 16853763}, + {120582, 16854019}, {120583, 16786179}, {120584, 16854275}, {120585, 16854531}, + {120586, 16854787}, {120587, 16855043}, {120588, 16855299}, {120589, 16855555}, + {120591, 16855811}, {120592, 16856067}, {120593, 16856323}, {120594, 16856579}, + {120595, 16856835}, {120596, 16857091}, {120597, 17962499}, {120598, 16852739}, + {120599, 16853507}, {120600, 16853763}, {120601, 16856323}, {120602, 16855299}, + {120603, 16855043}, {120604, 16851715}, {120605, 16851971}, {120606, 16852227}, + {120607, 16852483}, {120608, 16852739}, {120609, 16852995}, {120610, 16853251}, + {120611, 16853507}, {120612, 16846851}, {120613, 16853763}, {120614, 16854019}, + {120615, 16786179}, {120616, 16854275}, {120617, 16854531}, {120618, 16854787}, + {120619, 16855043}, {120620, 16855299}, {120621, 16853507}, {120622, 16855555}, + {120623, 16855811}, {120624, 16856067}, {120625, 16856323}, {120626, 16856579}, + {120627, 16856835}, {120628, 16857091}, {120629, 17962243}, {120630, 16851715}, + {120631, 16851971}, {120632, 16852227}, {120633, 16852483}, {120634, 16852739}, + {120635, 16852995}, {120636, 16853251}, {120637, 16853507}, {120638, 16846851}, + {120639, 16853763}, {120640, 16854019}, {120641, 16786179}, {120642, 16854275}, + {120643, 16854531}, {120644, 16854787}, {120645, 16855043}, {120646, 16855299}, + {120647, 16855555}, {120649, 16855811}, {120650, 16856067}, {120651, 16856323}, + {120652, 16856579}, {120653, 16856835}, {120654, 16857091}, {120655, 17962499}, + {120656, 16852739}, {120657, 16853507}, {120658, 16853763}, {120659, 16856323}, + {120660, 16855299}, {120661, 16855043}, {120662, 16851715}, {120663, 16851971}, + {120664, 16852227}, {120665, 16852483}, {120666, 16852739}, {120667, 16852995}, + {120668, 16853251}, {120669, 16853507}, {120670, 16846851}, {120671, 16853763}, + {120672, 16854019}, {120673, 16786179}, {120674, 16854275}, {120675, 16854531}, + {120676, 16854787}, {120677, 16855043}, {120678, 16855299}, {120679, 16853507}, + {120680, 16855555}, {120681, 16855811}, {120682, 16856067}, {120683, 16856323}, + {120684, 16856579}, {120685, 16856835}, {120686, 16857091}, {120687, 17962243}, + {120688, 16851715}, {120689, 16851971}, {120690, 16852227}, {120691, 16852483}, + {120692, 16852739}, {120693, 16852995}, {120694, 16853251}, {120695, 16853507}, + {120696, 16846851}, {120697, 16853763}, {120698, 16854019}, {120699, 16786179}, + {120700, 16854275}, {120701, 16854531}, {120702, 16854787}, {120703, 16855043}, + {120704, 16855299}, {120705, 16855555}, {120707, 16855811}, {120708, 16856067}, + {120709, 16856323}, {120710, 16856579}, {120711, 16856835}, {120712, 16857091}, + {120713, 17962499}, {120714, 16852739}, {120715, 16853507}, {120716, 16853763}, + {120717, 16856323}, {120718, 16855299}, {120719, 16855043}, {120720, 16851715}, + {120721, 16851971}, {120722, 16852227}, {120723, 16852483}, {120724, 16852739}, + {120725, 16852995}, {120726, 16853251}, {120727, 16853507}, {120728, 16846851}, + {120729, 16853763}, {120730, 16854019}, {120731, 16786179}, {120732, 16854275}, + {120733, 16854531}, {120734, 16854787}, {120735, 16855043}, {120736, 16855299}, + {120737, 16853507}, {120738, 16855555}, {120739, 16855811}, {120740, 16856067}, + {120741, 16856323}, {120742, 16856579}, {120743, 16856835}, {120744, 16857091}, + {120745, 17962243}, {120746, 16851715}, {120747, 16851971}, {120748, 16852227}, + {120749, 16852483}, {120750, 16852739}, {120751, 16852995}, {120752, 16853251}, + {120753, 16853507}, {120754, 16846851}, {120755, 16853763}, {120756, 16854019}, + {120757, 16786179}, {120758, 16854275}, {120759, 16854531}, {120760, 16854787}, + {120761, 16855043}, {120762, 16855299}, {120763, 16855555}, {120765, 16855811}, + {120766, 16856067}, {120767, 16856323}, {120768, 16856579}, {120769, 16856835}, + {120770, 16857091}, {120771, 17962499}, {120772, 16852739}, {120773, 16853507}, + {120774, 16853763}, {120775, 16856323}, {120776, 16855299}, {120777, 16855043}, + {120778, 16858627}, {120780, 2}, {120782, 17045507}, {120783, 16786947}, + {120784, 16785155}, {120785, 16785411}, {120786, 16787715}, {120787, 17045763}, + {120788, 17046019}, {120789, 17046275}, {120790, 17046531}, {120791, 17046787}, + {120792, 17045507}, {120793, 16786947}, {120794, 16785155}, {120795, 16785411}, + {120796, 16787715}, {120797, 17045763}, {120798, 17046019}, {120799, 17046275}, + {120800, 17046531}, {120801, 17046787}, {120802, 17045507}, {120803, 16786947}, + {120804, 16785155}, {120805, 16785411}, {120806, 16787715}, {120807, 17045763}, + {120808, 17046019}, {120809, 17046275}, {120810, 17046531}, {120811, 17046787}, + {120812, 17045507}, {120813, 16786947}, {120814, 16785155}, {120815, 16785411}, + {120816, 16787715}, {120817, 17045763}, {120818, 17046019}, {120819, 17046275}, + {120820, 17046531}, {120821, 17046787}, {120822, 17045507}, {120823, 16786947}, + {120824, 16785155}, {120825, 16785411}, {120826, 16787715}, {120827, 17045763}, + {120828, 17046019}, {120829, 17046275}, {120830, 17046531}, {120831, 17046787}, + {120832, 1}, {121484, 2}, {121499, 1}, {121504, 2}, + {121505, 1}, {121520, 2}, {122624, 1}, {122655, 2}, + {122661, 1}, {122667, 2}, {122880, 1}, {122887, 2}, + {122888, 1}, {122905, 2}, {122907, 1}, {122914, 2}, + {122915, 1}, {122917, 2}, {122918, 1}, {122923, 2}, + {122928, 16866563}, {122929, 16866819}, {122930, 16867075}, {122931, 16867331}, + {122932, 16867587}, {122933, 16867843}, {122934, 16868099}, {122935, 16868355}, + {122936, 16868611}, {122937, 16869123}, {122938, 16869379}, {122939, 16869635}, + {122940, 16870147}, {122941, 16870403}, {122942, 16870659}, {122943, 16870915}, + {122944, 16871171}, {122945, 16871427}, {122946, 16871683}, {122947, 16871939}, + {122948, 16872195}, {122949, 16872451}, {122950, 16872707}, {122951, 16873475}, + {122952, 16873987}, {122953, 16874243}, {122954, 17505795}, {122955, 16889091}, + {122956, 16864003}, {122957, 16864515}, {122958, 16891139}, {122959, 16883715}, + {122960, 16886019}, {122961, 16866563}, {122962, 16866819}, {122963, 16867075}, + {122964, 16867331}, {122965, 16867587}, {122966, 16867843}, {122967, 16868099}, + {122968, 16868355}, {122969, 16868611}, {122970, 16869123}, {122971, 16869379}, + {122972, 16870147}, {122973, 16870403}, {122974, 16870915}, {122975, 16871427}, + {122976, 16871683}, {122977, 16871939}, {122978, 16872195}, {122979, 16872451}, + {122980, 16872707}, {122981, 16873219}, {122982, 16873475}, {122983, 16879875}, + {122984, 16864003}, {122985, 16863747}, {122986, 16866307}, {122987, 16883203}, + {122988, 17500931}, {122989, 16883971}, {122990, 2}, {123023, 1}, + {123024, 2}, {123136, 1}, {123181, 2}, {123184, 1}, + {123198, 2}, {123200, 1}, {123210, 2}, {123214, 1}, + {123216, 2}, {123536, 1}, {123567, 2}, {123584, 1}, + {123642, 2}, {123647, 1}, {123648, 2}, {124112, 1}, + {124154, 2}, {124368, 1}, {124411, 2}, {124415, 1}, + {124416, 2}, {124896, 1}, {124903, 2}, {124904, 1}, + {124908, 2}, {124909, 1}, {124911, 2}, {124912, 1}, + {124927, 2}, {124928, 1}, {125125, 2}, {125127, 1}, + {125143, 2}, {125184, 17962755}, {125185, 17963011}, {125186, 17963267}, + {125187, 17963523}, {125188, 17963779}, {125189, 17964035}, {125190, 17964291}, + {125191, 17964547}, {125192, 17964803}, {125193, 17965059}, {125194, 17965315}, + {125195, 17965571}, {125196, 17965827}, {125197, 17966083}, {125198, 17966339}, + {125199, 17966595}, {125200, 17966851}, {125201, 17967107}, {125202, 17967363}, + {125203, 17967619}, {125204, 17967875}, {125205, 17968131}, {125206, 17968387}, + {125207, 17968643}, {125208, 17968899}, {125209, 17969155}, {125210, 17969411}, + {125211, 17969667}, {125212, 17969923}, {125213, 17970179}, {125214, 17970435}, + {125215, 17970691}, {125216, 17970947}, {125217, 17971203}, {125218, 1}, + {125260, 2}, {125264, 1}, {125274, 2}, {125278, 1}, + {125280, 2}, {126065, 1}, {126133, 2}, {126209, 1}, + {126270, 2}, {126464, 16910595}, {126465, 17695235}, {126466, 17693443}, + {126467, 17846019}, {126468, 2}, {126469, 16911107}, {126470, 17743107}, + {126471, 17693955}, {126472, 17711619}, {126473, 16912131}, {126474, 17720323}, + {126475, 17722627}, {126476, 17694467}, {126477, 17729539}, {126478, 17706499}, + {126479, 17713155}, {126480, 17715203}, {126481, 17708547}, {126482, 17718275}, + {126483, 17736707}, {126484, 17756675}, {126485, 17698307}, {126486, 17701379}, + {126487, 17696515}, {126488, 17736195}, {126489, 17709571}, {126490, 17712643}, + {126491, 17714179}, {126492, 17971459}, {126493, 17684995}, {126494, 17971715}, + {126495, 17971971}, {126496, 2}, {126497, 17695235}, {126498, 17693443}, + {126499, 2}, {126500, 17732611}, {126501, 2}, {126503, 17693955}, + {126504, 2}, {126505, 16912131}, {126506, 17720323}, {126507, 17722627}, + {126508, 17694467}, {126509, 17729539}, {126510, 17706499}, {126511, 17713155}, + {126512, 17715203}, {126513, 17708547}, {126514, 17718275}, {126515, 2}, + {126516, 17756675}, {126517, 17698307}, {126518, 17701379}, {126519, 17696515}, + {126520, 2}, {126521, 17709571}, {126522, 2}, {126523, 17714179}, + {126524, 2}, {126530, 17693443}, {126531, 2}, {126535, 17693955}, + {126536, 2}, {126537, 16912131}, {126538, 2}, {126539, 17722627}, + {126540, 2}, {126541, 17729539}, {126542, 17706499}, {126543, 17713155}, + {126544, 2}, {126545, 17708547}, {126546, 17718275}, {126547, 2}, + {126548, 17756675}, {126549, 2}, {126551, 17696515}, {126552, 2}, + {126553, 17709571}, {126554, 2}, {126555, 17714179}, {126556, 2}, + {126557, 17684995}, {126558, 2}, {126559, 17971971}, {126560, 2}, + {126561, 17695235}, {126562, 17693443}, {126563, 2}, {126564, 17732611}, + {126565, 2}, {126567, 17693955}, {126568, 17711619}, {126569, 16912131}, + {126570, 17720323}, {126571, 2}, {126572, 17694467}, {126573, 17729539}, + {126574, 17706499}, {126575, 17713155}, {126576, 17715203}, {126577, 17708547}, + {126578, 17718275}, {126579, 2}, {126580, 17756675}, {126581, 17698307}, + {126582, 17701379}, {126583, 17696515}, {126584, 2}, {126585, 17709571}, + {126586, 17712643}, {126587, 17714179}, {126588, 17971459}, {126589, 2}, + {126590, 17971715}, {126591, 2}, {126592, 16910595}, {126593, 17695235}, + {126594, 17693443}, {126595, 17846019}, {126596, 17732611}, {126597, 16911107}, + {126598, 17743107}, {126599, 17693955}, {126600, 17711619}, {126601, 16912131}, + {126602, 2}, {126603, 17722627}, {126604, 17694467}, {126605, 17729539}, + {126606, 17706499}, {126607, 17713155}, {126608, 17715203}, {126609, 17708547}, + {126610, 17718275}, {126611, 17736707}, {126612, 17756675}, {126613, 17698307}, + {126614, 17701379}, {126615, 17696515}, {126616, 17736195}, {126617, 17709571}, + {126618, 17712643}, {126619, 17714179}, {126620, 2}, {126625, 17695235}, + {126626, 17693443}, {126627, 17846019}, {126628, 2}, {126629, 16911107}, + {126630, 17743107}, {126631, 17693955}, {126632, 17711619}, {126633, 16912131}, + {126634, 2}, {126635, 17722627}, {126636, 17694467}, {126637, 17729539}, + {126638, 17706499}, {126639, 17713155}, {126640, 17715203}, {126641, 17708547}, + {126642, 17718275}, {126643, 17736707}, {126644, 17756675}, {126645, 17698307}, + {126646, 17701379}, {126647, 17696515}, {126648, 17736195}, {126649, 17709571}, + {126650, 17712643}, {126651, 17714179}, {126652, 2}, {126704, 1}, + {126706, 2}, {126976, 1}, {127020, 2}, {127024, 1}, + {127124, 2}, {127136, 1}, {127151, 2}, {127153, 1}, + {127168, 2}, {127169, 1}, {127184, 2}, {127185, 1}, + {127222, 2}, {127233, 34749443}, {127234, 34749955}, {127235, 34750467}, + {127236, 34750979}, {127237, 34751491}, {127238, 34752003}, {127239, 34752515}, + {127240, 34753027}, {127241, 34753539}, {127242, 34754051}, {127243, 1}, + {127248, 50655491}, {127249, 50656259}, {127250, 50657027}, {127251, 50657795}, + {127252, 50658563}, {127253, 50659331}, {127254, 50660099}, {127255, 50660867}, + {127256, 50661635}, {127257, 50662403}, {127258, 50663171}, {127259, 50663939}, + {127260, 50664707}, {127261, 50665475}, {127262, 50666243}, {127263, 50667011}, + {127264, 50667779}, {127265, 50668547}, {127266, 50669315}, {127267, 50670083}, + {127268, 50670851}, {127269, 50671619}, {127270, 50672387}, {127271, 50673155}, + {127272, 50673923}, {127273, 50674691}, {127274, 51531779}, {127275, 16777731}, + {127276, 16781571}, {127277, 33554947}, {127278, 34755331}, {127279, 1}, + {127280, 16777219}, {127281, 16777475}, {127282, 16777731}, {127283, 16777987}, + {127284, 16778243}, {127285, 16778499}, {127286, 16778755}, {127287, 16779011}, + {127288, 16779267}, {127289, 16779523}, {127290, 16779779}, {127291, 16780035}, + {127292, 16780291}, {127293, 16780547}, {127294, 16780803}, {127295, 16781059}, + {127296, 16781315}, {127297, 16781571}, {127298, 16781827}, {127299, 16782083}, + {127300, 16782339}, {127301, 16782595}, {127302, 16782851}, {127303, 16783107}, + {127304, 16783363}, {127305, 16783619}, {127306, 34755843}, {127307, 34237187}, + {127308, 34756355}, {127309, 34756867}, {127310, 51534595}, {127311, 34758147}, + {127312, 1}, {127338, 34220035}, {127339, 34200067}, {127340, 34758659}, + {127341, 1}, {127376, 34759171}, {127377, 1}, {127406, 2}, + {127462, 1}, {127488, 34759683}, {127489, 34760195}, {127490, 17318403}, + {127491, 2}, {127504, 17168387}, {127505, 17983491}, {127506, 17983747}, + {127507, 17362179}, {127508, 17153795}, {127509, 17984003}, {127510, 17984259}, + {127511, 17235971}, {127512, 17984515}, {127513, 17984771}, {127514, 17985027}, + {127515, 17596163}, {127516, 17985283}, {127517, 17985539}, {127518, 17985795}, + {127519, 17986051}, {127520, 17986307}, {127521, 17986563}, {127522, 17177603}, + {127523, 17986819}, {127524, 17987075}, {127525, 17987331}, {127526, 17987587}, + {127527, 17987843}, {127528, 17988099}, {127529, 17152259}, {127530, 17233923}, + {127531, 17988355}, {127532, 17299203}, {127533, 17234691}, {127534, 17299459}, + {127535, 17988611}, {127536, 17191939}, {127537, 17988867}, {127538, 17989123}, + {127539, 17989379}, {127540, 17989635}, {127541, 17989891}, {127542, 17274883}, + {127543, 17170947}, {127544, 17990147}, {127545, 17990403}, {127546, 17990659}, + {127547, 17990915}, {127548, 2}, {127552, 51545603}, {127553, 51546371}, + {127554, 51547139}, {127555, 51547907}, {127556, 51548675}, {127557, 51549443}, + {127558, 51550211}, {127559, 51550979}, {127560, 51551747}, {127561, 2}, + {127568, 17998083}, {127569, 17998339}, {127570, 2}, {127584, 1}, + {127590, 2}, {127744, 1}, {128728, 2}, {128732, 1}, + {128749, 2}, {128752, 1}, {128765, 2}, {128768, 1}, + {128887, 2}, {128891, 1}, {128986, 2}, {128992, 1}, + {129004, 2}, {129008, 1}, {129009, 2}, {129024, 1}, + {129036, 2}, {129040, 1}, {129096, 2}, {129104, 1}, + {129114, 2}, {129120, 1}, {129160, 2}, {129168, 1}, + {129198, 2}, {129200, 1}, {129212, 2}, {129216, 1}, + {129218, 2}, {129280, 1}, {129620, 2}, {129632, 1}, + {129646, 2}, {129648, 1}, {129661, 2}, {129664, 1}, + {129674, 2}, {129679, 1}, {129735, 2}, {129742, 1}, + {129757, 2}, {129759, 1}, {129770, 2}, {129776, 1}, + {129785, 2}, {129792, 1}, {129939, 2}, {129940, 1}, + {130032, 17045507}, {130033, 16786947}, {130034, 16785155}, {130035, 16785411}, + {130036, 16787715}, {130037, 17045763}, {130038, 17046019}, {130039, 17046275}, + {130040, 17046531}, {130041, 17046787}, {130042, 2}, {131072, 1}, {173792, 2}, {173824, 1}, {177978, 2}, {177984, 1}, {178206, 2}, {178208, 1}, {183970, 2}, {183984, 1}, - {191457, 2}, {194560, 17981443}, {194561, 17981699}, {194562, 17981955}, - {194563, 17982211}, {194564, 17982467}, {194565, 17608451}, {194566, 17982723}, - {194567, 17982979}, {194568, 17983235}, {194569, 17983491}, {194570, 17608707}, - {194571, 17983747}, {194572, 17984003}, {194573, 17984259}, {194574, 17608963}, - {194575, 17984515}, {194576, 17984771}, {194577, 17985027}, {194578, 17985283}, - {194579, 17985539}, {194580, 17985795}, {194581, 17968643}, {194582, 17986051}, - {194583, 17986307}, {194584, 17986563}, {194585, 17986819}, {194586, 17987075}, - {194587, 17623043}, {194588, 17987331}, {194589, 17145859}, {194590, 17987587}, - {194591, 17987843}, {194592, 17988099}, {194593, 17988355}, {194594, 17973251}, - {194595, 17988611}, {194596, 17988867}, {194597, 17624323}, {194598, 17609219}, - {194599, 17609475}, {194600, 17624579}, {194601, 17989123}, {194602, 17989379}, - {194603, 17562883}, {194604, 17989635}, {194605, 17609731}, {194606, 17989891}, - {194607, 17990147}, {194608, 17990403}, {194609, 17990659}, {194612, 17990915}, - {194613, 17991171}, {194614, 17991427}, {194615, 17991683}, {194616, 17991939}, - {194617, 17992195}, {194618, 17992451}, {194619, 17992707}, {194620, 17992963}, - {194621, 17993219}, {194622, 17993475}, {194623, 17993731}, {194624, 17993987}, - {194625, 17994243}, {194626, 17994499}, {194627, 17994755}, {194628, 17995011}, - {194629, 17995267}, {194631, 17625091}, {194632, 17995523}, {194633, 17995779}, - {194634, 17996035}, {194635, 17996291}, {194636, 17610243}, {194637, 17996547}, - {194638, 17996803}, {194639, 17997059}, {194640, 17600003}, {194641, 17997315}, - {194642, 17997571}, {194643, 17997827}, {194644, 17998083}, {194645, 17998339}, - {194646, 17998595}, {194647, 17998851}, {194648, 17999107}, {194649, 17999363}, - {194650, 17999619}, {194651, 17999875}, {194652, 18000131}, {194653, 17966851}, - {194654, 18000387}, {194655, 18000643}, {194656, 18000899}, {194657, 18001155}, - {194658, 18001411}, {194659, 18001667}, {194660, 18001923}, {194661, 18002179}, - {194662, 18002435}, {194663, 18002691}, {194664, 2}, {194665, 18002947}, - {194666, 18003203}, {194668, 18003459}, {194669, 18003715}, {194670, 18003971}, - {194671, 17561859}, {194672, 18004227}, {194673, 18004483}, {194674, 18004739}, - {194675, 18004995}, {194676, 2}, {194677, 17152515}, {194678, 18005251}, - {194679, 18005507}, {194680, 17153027}, {194681, 18005763}, {194682, 18006019}, - {194683, 18006275}, {194684, 18006531}, {194685, 18006787}, {194686, 18007043}, - {194687, 18007299}, {194688, 18007555}, {194689, 18007811}, {194690, 18008067}, - {194691, 18008323}, {194692, 18008579}, {194693, 18008835}, {194694, 18009091}, - {194695, 18009347}, {194696, 18009603}, {194697, 18009859}, {194698, 18010115}, - {194699, 18010371}, {194700, 18010627}, {194701, 18010883}, {194702, 17548547}, - {194703, 18011139}, {194704, 17155587}, {194705, 18011395}, {194707, 18011651}, - {194708, 18011907}, {194710, 18012163}, {194711, 18012419}, {194712, 18012675}, - {194713, 18012931}, {194714, 18013187}, {194715, 18013443}, {194716, 18013699}, - {194717, 18013955}, {194718, 18014211}, {194719, 18014467}, {194720, 18014723}, - {194721, 18014979}, {194722, 18015235}, {194723, 17611523}, {194724, 18015491}, - {194725, 18015747}, {194726, 18016003}, {194727, 18016259}, {194728, 17628163}, - {194729, 18016259}, {194730, 18016515}, {194731, 17612035}, {194732, 18016771}, - {194733, 18017027}, {194734, 18017283}, {194735, 18017539}, {194736, 17612291}, - {194737, 17541635}, {194738, 17414915}, {194739, 18017795}, {194740, 18018051}, - {194741, 18018307}, {194742, 18018563}, {194743, 18018819}, {194744, 18019075}, - {194745, 18019331}, {194746, 18019587}, {194747, 18019843}, {194748, 18020099}, - {194749, 18020355}, {194750, 18020611}, {194751, 18020867}, {194752, 18021123}, - {194753, 18021379}, {194754, 18021635}, {194755, 18021891}, {194756, 18022147}, - {194757, 18022403}, {194758, 18022659}, {194759, 18022915}, {194760, 17612547}, - {194761, 18023171}, {194762, 18023427}, {194763, 18023683}, {194764, 18023939}, - {194765, 18024195}, {194766, 18024451}, {194767, 17613059}, {194768, 18024707}, - {194769, 18024963}, {194770, 18025219}, {194771, 18025475}, {194772, 18025731}, - {194773, 18025987}, {194774, 18026243}, {194775, 18026499}, {194776, 17548803}, - {194777, 17630211}, {194778, 18026755}, {194779, 18027011}, {194780, 18027267}, - {194781, 18027523}, {194782, 18027779}, {194783, 18028035}, {194784, 18028291}, - {194785, 18028547}, {194786, 17613315}, {194787, 18028803}, {194788, 18029059}, - {194789, 18029315}, {194790, 18029571}, {194791, 17640963}, {194792, 18029827}, - {194793, 18030083}, {194794, 18030339}, {194795, 18030595}, {194796, 18030851}, - {194797, 18031107}, {194798, 18031363}, {194799, 18031619}, {194800, 18031875}, - {194801, 18032131}, {194802, 18032387}, {194803, 18032643}, {194804, 18032899}, - {194805, 17566211}, {194806, 18033155}, {194807, 18033411}, {194808, 18033667}, - {194809, 18033923}, {194810, 18034179}, {194811, 18034435}, {194812, 18034691}, - {194813, 18034947}, {194814, 18035203}, {194815, 18035459}, {194816, 18035715}, - {194817, 17613571}, {194818, 17587203}, {194819, 18035971}, {194820, 18036227}, - {194821, 18036483}, {194822, 18036739}, {194823, 18036995}, {194824, 18037251}, - {194825, 18037507}, {194826, 18037763}, {194827, 17630979}, {194828, 18038019}, - {194829, 18038275}, {194830, 18038531}, {194831, 18038787}, {194832, 18039043}, - {194833, 18039299}, {194834, 18039555}, {194835, 18039811}, {194836, 17631235}, - {194837, 18040067}, {194838, 18040323}, {194839, 18040579}, {194840, 18040835}, - {194841, 18041091}, {194842, 18041347}, {194843, 18041603}, {194844, 18041859}, - {194845, 18042115}, {194846, 18042371}, {194847, 2}, {194848, 18042627}, - {194849, 17631747}, {194850, 18042883}, {194851, 18043139}, {194852, 18043395}, - {194853, 18043651}, {194854, 18043907}, {194855, 18044163}, {194856, 18044419}, - {194857, 18044675}, {194858, 18044931}, {194859, 18045187}, {194860, 18045443}, - {194862, 18045699}, {194863, 18045955}, {194864, 17632259}, {194865, 18046211}, - {194866, 18046467}, {194867, 18046723}, {194868, 18046979}, {194869, 18047235}, - {194870, 18047491}, {194871, 18047747}, {194872, 17562627}, {194873, 18048003}, - {194874, 18048259}, {194875, 18048515}, {194876, 18048771}, {194877, 18049027}, - {194878, 18049283}, {194879, 18049539}, {194880, 17633795}, {194881, 18049795}, - {194882, 18050051}, {194883, 18050307}, {194884, 18050563}, {194885, 18050819}, - {194886, 18051075}, {194888, 17634051}, {194889, 17641475}, {194890, 18051331}, - {194891, 18051587}, {194892, 18051843}, {194893, 18052099}, {194894, 18052355}, - {194895, 17553155}, {194896, 17634563}, {194897, 18052611}, {194898, 18052867}, - {194899, 17616131}, {194900, 18053123}, {194901, 18053379}, {194902, 17605123}, - {194903, 18053635}, {194904, 18053891}, {194905, 17616899}, {194906, 18054147}, - {194907, 18054403}, {194908, 18054659}, {194909, 18054915}, {194911, 2}, - {194912, 18055171}, {194913, 18055427}, {194914, 18055683}, {194915, 18055939}, - {194916, 18056195}, {194917, 18056451}, {194918, 18056707}, {194919, 18056963}, - {194920, 18057219}, {194921, 18057475}, {194922, 18057731}, {194923, 18057987}, - {194924, 18058243}, {194925, 18058499}, {194926, 18058755}, {194927, 18059011}, - {194928, 18059267}, {194929, 18059523}, {194930, 18059779}, {194931, 18060035}, - {194932, 18060291}, {194933, 18060547}, {194934, 18060803}, {194935, 18061059}, - {194936, 18061315}, {194937, 18061571}, {194938, 17618435}, {194939, 18061827}, - {194940, 18062083}, {194941, 18062339}, {194942, 18062595}, {194943, 18062851}, - {194944, 18063107}, {194945, 18063363}, {194946, 18063619}, {194947, 18063875}, - {194948, 18064131}, {194949, 18064387}, {194950, 18064643}, {194951, 18064899}, - {194952, 18065155}, {194953, 18065411}, {194954, 18065667}, {194955, 18011651}, - {194956, 18065923}, {194957, 18066179}, {194958, 18066435}, {194959, 18066691}, - {194960, 18066947}, {194961, 18067203}, {194962, 18067459}, {194963, 18067715}, - {194964, 18067971}, {194965, 18068227}, {194966, 18068483}, {194967, 18068739}, - {194968, 17566979}, {194969, 18068995}, {194970, 18069251}, {194971, 18069507}, - {194972, 18069763}, {194973, 18070019}, {194974, 18070275}, {194975, 17619203}, - {194976, 18070531}, {194977, 18070787}, {194978, 18071043}, {194979, 18071299}, - {194980, 18071555}, {194981, 18071811}, {194982, 18072067}, {194983, 18072323}, - {194984, 18072579}, {194985, 18072835}, {194986, 18073091}, {194987, 18073347}, - {194988, 18073603}, {194989, 18073859}, {194990, 18074115}, {194991, 18074371}, - {194992, 18074627}, {194993, 18074883}, {194994, 18075139}, {194995, 18075395}, - {194996, 17551875}, {194997, 18075651}, {194998, 18075907}, {194999, 18076163}, - {195000, 18076419}, {195001, 18076675}, {195002, 18076931}, {195003, 17636355}, - {195004, 18077187}, {195005, 18077443}, {195006, 18077699}, {195007, 2}, - {195008, 18077955}, {195009, 18078211}, {195010, 18078467}, {195011, 18078723}, - {195012, 17178627}, {195013, 18078979}, {195014, 18079235}, {195015, 18079491}, - {195016, 18079747}, {195017, 18080003}, {195018, 18080259}, {195019, 18080515}, - {195020, 18080771}, {195021, 18081027}, {195022, 18081283}, {195023, 18081539}, - {195024, 17637635}, {195025, 17637891}, {195026, 17180419}, {195027, 18081795}, - {195028, 18082051}, {195029, 18082307}, {195030, 18082563}, {195031, 18082819}, - {195032, 18083075}, {195033, 18083331}, {195034, 18083587}, {195035, 18083843}, - {195036, 18084099}, {195037, 18084355}, {195038, 18084611}, {195039, 17638147}, - {195040, 18084867}, {195041, 18085123}, {195042, 18085379}, {195043, 18085635}, - {195044, 18085891}, {195045, 18086147}, {195046, 18086403}, {195047, 18086659}, - {195048, 18086915}, {195049, 18087171}, {195050, 18087427}, {195051, 18087683}, - {195052, 18087939}, {195053, 18088195}, {195054, 18088451}, {195055, 18088707}, - {195056, 18088963}, {195057, 18089219}, {195058, 18089475}, {195059, 18089731}, - {195060, 18089987}, {195061, 18090243}, {195062, 18090499}, {195063, 18090755}, - {195064, 18091011}, {195065, 18091267}, {195066, 18091523}, {195067, 18091779}, - {195068, 18092035}, {195069, 18092291}, {195070, 17639683}, {195072, 18092547}, - {195073, 18092803}, {195074, 18093059}, {195075, 18093315}, {195076, 18093571}, - {195077, 18093827}, {195078, 18094083}, {195079, 18094339}, {195080, 18094595}, - {195081, 18094851}, {195082, 17639939}, {195083, 18095107}, {195084, 18095363}, - {195085, 18095619}, {195086, 18095875}, {195087, 18096131}, {195088, 18096387}, - {195089, 18096643}, {195090, 18096899}, {195091, 18097155}, {195092, 18097411}, - {195093, 17192707}, {195094, 18097667}, {195095, 17193731}, {195096, 18097923}, - {195097, 18098179}, {195098, 18098435}, {195099, 18098691}, {195100, 17195011}, - {195101, 18098947}, {195102, 2}, {196608, 1}, {201547, 2}, - {201552, 1}, {205744, 2}, {917760, 0}, {918000, 2} + {191457, 2}, {191472, 1}, {192094, 2}, {194560, 17998595}, + {194561, 17998851}, {194562, 17999107}, {194563, 17999363}, {194564, 17999619}, + {194565, 17619971}, {194566, 17999875}, {194567, 18000131}, {194568, 18000387}, + {194569, 18000643}, {194570, 17620227}, {194571, 18000899}, {194572, 18001155}, + {194573, 18001411}, {194574, 17620483}, {194575, 18001667}, {194576, 18001923}, + {194577, 18002179}, {194578, 18002435}, {194579, 18002691}, {194580, 18002947}, + {194581, 17985795}, {194582, 18003203}, {194583, 18003459}, {194584, 18003715}, + {194585, 18003971}, {194586, 18004227}, {194587, 17634563}, {194588, 18004483}, + {194589, 17156355}, {194590, 18004739}, {194591, 18004995}, {194592, 18005251}, + {194593, 18005507}, {194594, 17990403}, {194595, 18005763}, {194596, 18006019}, + {194597, 17635843}, {194598, 17620739}, {194599, 17620995}, {194600, 17636099}, + {194601, 18006275}, {194602, 18006531}, {194603, 17574403}, {194604, 18006787}, + {194605, 17621251}, {194606, 18007043}, {194607, 18007299}, {194608, 18007555}, + {194609, 18007811}, {194612, 18008067}, {194613, 18008323}, {194614, 18008579}, + {194615, 18008835}, {194616, 18009091}, {194617, 18009347}, {194618, 18009603}, + {194619, 18009859}, {194620, 18010115}, {194621, 18010371}, {194622, 18010627}, + {194623, 18010883}, {194624, 18011139}, {194625, 18011395}, {194626, 18011651}, + {194627, 18011907}, {194628, 18012163}, {194629, 18012419}, {194631, 17636611}, + {194632, 18012675}, {194633, 18012931}, {194634, 18013187}, {194635, 18013443}, + {194636, 17621763}, {194637, 18013699}, {194638, 18013955}, {194639, 18014211}, + {194640, 17611523}, {194641, 18014467}, {194642, 18014723}, {194643, 18014979}, + {194644, 18015235}, {194645, 18015491}, {194646, 18015747}, {194647, 18016003}, + {194648, 18016259}, {194649, 18016515}, {194650, 18016771}, {194651, 18017027}, + {194652, 18017283}, {194653, 17984003}, {194654, 18017539}, {194655, 18017795}, + {194656, 18018051}, {194657, 18018307}, {194658, 18018563}, {194659, 18018819}, + {194660, 18019075}, {194661, 18019331}, {194662, 18019587}, {194663, 18019843}, + {194664, 18020099}, {194665, 18020355}, {194666, 18020611}, {194668, 18020867}, + {194669, 18021123}, {194670, 18021379}, {194671, 17573379}, {194672, 18021635}, + {194673, 18021891}, {194674, 18022147}, {194675, 18022403}, {194676, 18022659}, + {194677, 17163011}, {194678, 18022915}, {194679, 18023171}, {194680, 17163523}, + {194681, 18023427}, {194682, 18023683}, {194683, 18023939}, {194684, 18024195}, + {194685, 18024451}, {194686, 18024707}, {194687, 18024963}, {194688, 18025219}, + {194689, 18025475}, {194690, 18025731}, {194691, 18025987}, {194692, 18026243}, + {194693, 18026499}, {194694, 18026755}, {194695, 18027011}, {194696, 18027267}, + {194697, 18027523}, {194698, 18027779}, {194699, 18028035}, {194700, 18028291}, + {194701, 18028547}, {194702, 17560067}, {194703, 18028803}, {194704, 17166083}, + {194705, 18029059}, {194707, 18029315}, {194708, 18029571}, {194710, 18029827}, + {194711, 18030083}, {194712, 18030339}, {194713, 18030595}, {194714, 18030851}, + {194715, 18031107}, {194716, 18031363}, {194717, 18031619}, {194718, 18031875}, + {194719, 18032131}, {194720, 18032387}, {194721, 18032643}, {194722, 18032899}, + {194723, 17623043}, {194724, 18033155}, {194725, 18033411}, {194726, 18033667}, + {194727, 18033923}, {194728, 17639683}, {194729, 18033923}, {194730, 18034179}, + {194731, 17623555}, {194732, 18034435}, {194733, 18034691}, {194734, 18034947}, + {194735, 18035203}, {194736, 17623811}, {194737, 17553155}, {194738, 17425411}, + {194739, 18035459}, {194740, 18035715}, {194741, 18035971}, {194742, 18036227}, + {194743, 18036483}, {194744, 18036739}, {194745, 18036995}, {194746, 18037251}, + {194747, 18037507}, {194748, 18037763}, {194749, 18038019}, {194750, 18038275}, + {194751, 18038531}, {194752, 18038787}, {194753, 18039043}, {194754, 18039299}, + {194755, 18039555}, {194756, 18039811}, {194757, 18040067}, {194758, 18040323}, + {194759, 18040579}, {194760, 17624067}, {194761, 18040835}, {194762, 18041091}, + {194763, 18041347}, {194764, 18041603}, {194765, 18041859}, {194766, 18042115}, + {194767, 17624579}, {194768, 18042371}, {194769, 18042627}, {194770, 18042883}, + {194771, 18043139}, {194772, 18043395}, {194773, 18043651}, {194774, 18043907}, + {194775, 18044163}, {194776, 17560323}, {194777, 17641731}, {194778, 18044419}, + {194779, 18044675}, {194780, 18044931}, {194781, 18045187}, {194782, 18045443}, + {194783, 18045699}, {194784, 18045955}, {194785, 18046211}, {194786, 17624835}, + {194787, 18046467}, {194788, 18046723}, {194789, 18046979}, {194790, 18047235}, + {194791, 17652483}, {194792, 18047491}, {194793, 18047747}, {194794, 18048003}, + {194795, 18048259}, {194796, 18048515}, {194797, 18048771}, {194798, 18049027}, + {194799, 18049283}, {194800, 18049539}, {194801, 18049795}, {194802, 18050051}, + {194803, 18050307}, {194804, 18050563}, {194805, 17577731}, {194806, 18050819}, + {194807, 18051075}, {194808, 18051331}, {194809, 18051587}, {194810, 18051843}, + {194811, 18052099}, {194812, 18052355}, {194813, 18052611}, {194814, 18052867}, + {194815, 18053123}, {194816, 18053379}, {194817, 17625091}, {194818, 17598723}, + {194819, 18053635}, {194820, 18053891}, {194821, 18054147}, {194822, 18054403}, + {194823, 18054659}, {194824, 18054915}, {194825, 18055171}, {194826, 18055427}, + {194827, 17642499}, {194828, 18055683}, {194829, 18055939}, {194830, 18056195}, + {194831, 18056451}, {194832, 18056707}, {194833, 18056963}, {194834, 18057219}, + {194835, 18057475}, {194836, 17642755}, {194837, 18057731}, {194838, 18057987}, + {194839, 18058243}, {194840, 18058499}, {194841, 18058755}, {194842, 18059011}, + {194843, 18059267}, {194844, 18059523}, {194845, 18059779}, {194846, 18060035}, + {194847, 18060291}, {194848, 18060547}, {194849, 17643267}, {194850, 18060803}, + {194851, 18061059}, {194852, 18061315}, {194853, 18061571}, {194854, 18061827}, + {194855, 18062083}, {194856, 18062339}, {194857, 18062595}, {194858, 18062851}, + {194859, 18063107}, {194860, 18063363}, {194862, 18063619}, {194863, 18063875}, + {194864, 17643779}, {194865, 18064131}, {194866, 18064387}, {194867, 18064643}, + {194868, 18064899}, {194869, 18065155}, {194870, 18065411}, {194871, 18065667}, + {194872, 17574147}, {194873, 18065923}, {194874, 18066179}, {194875, 18066435}, + {194876, 18066691}, {194877, 18066947}, {194878, 18067203}, {194879, 18067459}, + {194880, 17645315}, {194881, 18067715}, {194882, 18067971}, {194883, 18068227}, + {194884, 18068483}, {194885, 18068739}, {194886, 18068995}, {194888, 17645571}, + {194889, 17652995}, {194890, 18069251}, {194891, 18069507}, {194892, 18069763}, + {194893, 18070019}, {194894, 18070275}, {194895, 17564675}, {194896, 17646083}, + {194897, 18070531}, {194898, 18070787}, {194899, 17627651}, {194900, 18071043}, + {194901, 18071299}, {194902, 17616643}, {194903, 18071555}, {194904, 18071811}, + {194905, 17628419}, {194906, 18072067}, {194907, 18072323}, {194908, 18072579}, + {194909, 18072835}, {194911, 18073091}, {194912, 18073347}, {194913, 18073603}, + {194914, 18073859}, {194915, 18074115}, {194916, 18074371}, {194917, 18074627}, + {194918, 18074883}, {194919, 18075139}, {194920, 18075395}, {194921, 18075651}, + {194922, 18075907}, {194923, 18076163}, {194924, 18076419}, {194925, 18076675}, + {194926, 18076931}, {194927, 18077187}, {194928, 18077443}, {194929, 18077699}, + {194930, 18077955}, {194931, 18078211}, {194932, 18078467}, {194933, 18078723}, + {194934, 18078979}, {194935, 18079235}, {194936, 18079491}, {194937, 18079747}, + {194938, 17629955}, {194939, 18080003}, {194940, 18080259}, {194941, 18080515}, + {194942, 18080771}, {194943, 18081027}, {194944, 18081283}, {194945, 18081539}, + {194946, 18081795}, {194947, 18082051}, {194948, 18082307}, {194949, 18082563}, + {194950, 18082819}, {194951, 18083075}, {194952, 18083331}, {194953, 18083587}, + {194954, 18083843}, {194955, 18029315}, {194956, 18084099}, {194957, 18084355}, + {194958, 18084611}, {194959, 18084867}, {194960, 18085123}, {194961, 18085379}, + {194962, 18085635}, {194963, 18085891}, {194964, 18086147}, {194965, 18086403}, + {194966, 18086659}, {194967, 18086915}, {194968, 17578499}, {194969, 18087171}, + {194970, 18087427}, {194971, 18087683}, {194972, 18087939}, {194973, 18088195}, + {194974, 18088451}, {194975, 17630723}, {194976, 18088707}, {194977, 18088963}, + {194978, 18089219}, {194979, 18089475}, {194980, 18089731}, {194981, 18089987}, + {194982, 18090243}, {194983, 18090499}, {194984, 18090755}, {194985, 18091011}, + {194986, 18091267}, {194987, 18091523}, {194988, 18091779}, {194989, 18092035}, + {194990, 18092291}, {194991, 18092547}, {194992, 18092803}, {194993, 18093059}, + {194994, 18093315}, {194995, 18093571}, {194996, 17563395}, {194997, 18093827}, + {194998, 18094083}, {194999, 18094339}, {195000, 18094595}, {195001, 18094851}, + {195002, 18095107}, {195003, 17647875}, {195004, 18095363}, {195005, 18095619}, + {195006, 18095875}, {195007, 18096131}, {195008, 18096387}, {195009, 18096643}, + {195010, 18096899}, {195011, 18097155}, {195012, 17189123}, {195013, 18097411}, + {195014, 18097667}, {195015, 18097923}, {195016, 18098179}, {195017, 18098435}, + {195018, 18098691}, {195019, 18098947}, {195020, 18099203}, {195021, 18099459}, + {195022, 18099715}, {195023, 18099971}, {195024, 17649155}, {195025, 17649411}, + {195026, 17190915}, {195027, 18100227}, {195028, 18100483}, {195029, 18100739}, + {195030, 18100995}, {195031, 18101251}, {195032, 18101507}, {195033, 18101763}, + {195034, 18102019}, {195035, 18102275}, {195036, 18102531}, {195037, 18102787}, + {195038, 18103043}, {195039, 17649667}, {195040, 18103299}, {195041, 18103555}, + {195042, 18103811}, {195043, 18104067}, {195044, 18104323}, {195045, 18104579}, + {195046, 18104835}, {195047, 18105091}, {195048, 18105347}, {195049, 18105603}, + {195050, 18105859}, {195051, 18106115}, {195052, 18106371}, {195053, 18106627}, + {195054, 18106883}, {195055, 18107139}, {195056, 18107395}, {195057, 18107651}, + {195058, 18107907}, {195059, 18108163}, {195060, 18108419}, {195061, 18108675}, + {195062, 18108931}, {195063, 18109187}, {195064, 18109443}, {195065, 18109699}, + {195066, 18109955}, {195067, 18110211}, {195068, 18110467}, {195069, 18110723}, + {195070, 17651203}, {195072, 18110979}, {195073, 18111235}, {195074, 18111491}, + {195075, 18111747}, {195076, 18112003}, {195077, 18112259}, {195078, 18112515}, + {195079, 18112771}, {195080, 18113027}, {195081, 18113283}, {195082, 17651459}, + {195083, 18113539}, {195084, 18113795}, {195085, 18114051}, {195086, 18114307}, + {195087, 18114563}, {195088, 18114819}, {195089, 18115075}, {195090, 18115331}, + {195091, 18115587}, {195092, 18115843}, {195093, 17203203}, {195094, 18116099}, + {195095, 17204227}, {195096, 18116355}, {195097, 18116611}, {195098, 18116867}, + {195099, 18117123}, {195100, 17205507}, {195101, 18117379}, {195102, 2}, + {196608, 1}, {201547, 2}, {201552, 1}, {205744, 2}, + {917760, 0}, {918000, 2} }; } // namespace ada::idna #endif // ADA_IDNA_TABLES_H - /* end file src/mapping_tables.cpp */ namespace ada::idna { @@ -2753,30 +2797,6 @@ uint32_t find_range_index(uint32_t key) { return low == 0 ? 0 : low - 1; } -bool ascii_has_upper_case(char* input, size_t length) { - auto broadcast = [](uint8_t v) -> uint64_t { - return 0x101010101010101ull * v; - }; - uint64_t broadcast_80 = broadcast(0x80); - uint64_t broadcast_Ap = broadcast(128 - 'A'); - uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1); - size_t i = 0; - - uint64_t runner{0}; - - for (; i + 7 < length; i += 8) { - uint64_t word{}; - memcpy(&word, input + i, sizeof(word)); - runner |= (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80); - } - if (i < length) { - uint64_t word{}; - memcpy(&word, input + i, length - i); - runner |= (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80); - } - return runner != 0; -} - void ascii_map(char* input, size_t length) { auto broadcast = [](uint8_t v) -> uint64_t { return 0x101010101010101ull * v; @@ -7915,11 +7935,11 @@ void compose(std::u32string& input) { if (composition[1] != composition[0] && previous_ccc < ccc) { // Try finding a composition. - uint16_t left = composition[0]; - uint16_t right = composition[1]; + int left = composition[0]; + int right = composition[1]; while (left + 2 < right) { // mean without overflow - uint16_t middle = left + (((right - left) >> 1) & ~1); + int middle = left + (((right - left) >> 1) & ~1); if (composition_data[middle] <= input[input_count + 1]) { left = middle; } @@ -8002,6 +8022,10 @@ static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) { } bool punycode_to_utf32(std::string_view input, std::u32string &out) { + // See https://github.com/whatwg/url/issues/803 + if (input.starts_with("xn--")) { + return false; + } int32_t written_out{0}; out.reserve(out.size() + input.size()); uint32_t n = initial_n; @@ -8058,11 +8082,13 @@ bool punycode_to_utf32(std::string_view input, std::u32string &out) { written_out++; ++i; } - return true; } bool verify_punycode(std::string_view input) { + if (input.starts_with("xn--")) { + return false; + } size_t written_out{0}; uint32_t n = initial_n; int32_t i = 0; @@ -8132,7 +8158,7 @@ bool utf32_to_punycode(std::u32string_view input, std::string &out) { ++h; out.push_back(char(c)); } - if (c > 0x10ffff || (c >= 0xd880 && c < 0xe000)) { + if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) { return false; } } @@ -8969,7 +8995,7 @@ inline static direction find_direction(uint32_t code_point) noexcept { inline static size_t find_last_not_of_nsm( const std::u32string_view label) noexcept { - for (int i = label.size() - 1; i >= 0; i--) + for (int i = static_cast(label.size() - 1); i >= 0; i--) if (find_direction(label[i]) != direction::NSM) return i; return std::u32string_view::npos; @@ -9485,12 +9511,14 @@ bool is_label_valid(const std::u32string_view label) { for (size_t i = 0; i <= last_non_nsm_char; i++) { const direction d = find_direction(label[i]); + // NOLINTBEGIN(bugprone-assignment-in-if-condition) // In an RTL label, if an EN is present, no AN may be present, and vice // versa. if ((d == direction::EN && ((has_en = true) && has_an)) || (d == direction::AN && ((has_an = true) && has_en))) { return false; } + // NOLINTEND(bugprone-assignment-in-if-condition) if (!(d == direction::R || d == direction::AL || d == direction::AN || d == direction::EN || d == direction::ES || d == direction::CS || @@ -9519,25 +9547,14 @@ bool is_label_valid(const std::u32string_view label) { #include #include +#include -namespace ada::idna { - -bool begins_with(std::u32string_view view, std::u32string_view prefix) { - if (view.size() < prefix.size()) { - return false; - } - // constexpr as of C++20 - return std::equal(prefix.begin(), prefix.end(), view.begin()); -} +#ifdef ADA_USE_SIMDUTF +#include "simdutf.h" +#endif -bool begins_with(std::string_view view, std::string_view prefix) { - if (view.size() < prefix.size()) { - return false; - } - // constexpr as of C++20 - return std::equal(prefix.begin(), prefix.end(), view.begin()); -} +namespace ada::idna { bool constexpr is_ascii(std::u32string_view view) { for (uint32_t c : view) { @@ -9577,8 +9594,7 @@ inline bool is_forbidden_domain_code_point(const char c) noexcept { } bool contains_forbidden_domain_code_point(std::string_view view) { - return ( - std::any_of(view.begin(), view.end(), is_forbidden_domain_code_point)); + return std::ranges::any_of(view, is_forbidden_domain_code_point); } // We return "" on error. @@ -9601,7 +9617,7 @@ static std::string from_ascii_to_ascii(std::string_view ut8_string) { label_start += label_size_with_dot; if (label_size == 0) { // empty label? Nothing to do. - } else if (begins_with(label_view, "xn--")) { + } else if (label_view.starts_with("xn--")) { // The xn-- part is the expensive game. out.append(label_view); std::string_view puny_segment_ascii( @@ -9612,6 +9628,12 @@ static std::string from_ascii_to_ascii(std::string_view ut8_string) { if (!is_ok) { return error; } + // If the input is just ASCII, it should not have been encoded + // as punycode. + // https://github.com/whatwg/url/issues/760 + if (is_ascii(tmp_buffer)) { + return error; + } std::u32string post_map = ada::idna::map(tmp_buffer); if (tmp_buffer != post_map) { return error; @@ -9644,11 +9666,20 @@ std::string to_ascii(std::string_view ut8_string) { } static const std::string error = ""; // We convert to UTF-32 + +#ifdef ADA_USE_SIMDUTF + size_t utf32_length = + simdutf::utf32_length_from_utf8(ut8_string.data(), ut8_string.size()); + std::u32string utf32(utf32_length, '\0'); + size_t actual_utf32_length = simdutf::convert_utf8_to_utf32( + ut8_string.data(), ut8_string.size(), utf32.data()); +#else size_t utf32_length = ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size()); std::u32string utf32(utf32_length, '\0'); size_t actual_utf32_length = ada::idna::utf8_to_utf32( ut8_string.data(), ut8_string.size(), utf32.data()); +#endif if (actual_utf32_length == 0) { return error; } @@ -9668,7 +9699,7 @@ std::string to_ascii(std::string_view ut8_string) { label_start += label_size_with_dot; if (label_size == 0) { // empty label? Nothing to do. - } else if (begins_with(label_view, U"xn--")) { + } else if (label_view.starts_with(U"xn--")) { // we do not need to check, e.g., Xn-- because mapping goes to lower case for (char32_t c : label_view) { if (c >= 0x80) { @@ -9684,6 +9715,12 @@ std::string to_ascii(std::string_view ut8_string) { if (!is_ok) { return error; } + // If the input is just ASCII, it should not have been encoded + // as punycode. + // https://github.com/whatwg/url/issues/760 + if (is_ascii(tmp_buffer)) { + return error; + } std::u32string post_map = ada::idna::map(tmp_buffer); if (tmp_buffer != post_map) { return error; @@ -9734,6 +9771,10 @@ std::string to_ascii(std::string_view ut8_string) { #include +#ifdef ADA_USE_SIMDUTF +#include "simdutf.h" +#endif + namespace ada::idna { std::string to_unicode(std::string_view input) { std::string output; @@ -9747,17 +9788,24 @@ std::string to_unicode(std::string_view input) { is_last_label ? input.size() - label_start : loc_dot - label_start; auto label_view = std::string_view(input.data() + label_start, label_size); - if (ada::idna::begins_with(label_view, "xn--") && - ada::idna::is_ascii(label_view)) { + if (label_view.starts_with("xn--") && ada::idna::is_ascii(label_view)) { label_view.remove_prefix(4); if (ada::idna::verify_punycode(label_view)) { std::u32string tmp_buffer; if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) { +#ifdef ADA_USE_SIMDUTF + auto utf8_size = simdutf::utf8_length_from_utf32(tmp_buffer.data(), + tmp_buffer.size()); + std::string final_utf8(utf8_size, '\0'); + simdutf::convert_utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(), + final_utf8.data()); +#else auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(), tmp_buffer.size()); std::string final_utf8(utf8_size, '\0'); ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(), final_utf8.data()); +#endif output.append(final_utf8); } else { // ToUnicode never fails. If any step fails, then the original input @@ -9783,6 +9831,613 @@ std::string to_unicode(std::string_view input) { } } // namespace ada::idna /* end file src/to_unicode.cpp */ +/* begin file src/identifier.cpp */ + +#include +#include +#include + +/* begin file src/id_tables.cpp */ +// IDNA 16.0.0 + +// clang-format off +#ifndef ADA_IDNA_IDENTIFIER_TABLES_H +#define ADA_IDNA_IDENTIFIER_TABLES_H +#include + +namespace ada::idna { + +const uint32_t id_continue[1393][2] = +{ + {48, 57}, {65, 90}, {95, 95}, {97, 122}, + {170, 170}, {181, 181}, {183, 183}, {186, 186}, + {192, 214}, {216, 246}, {248, 442}, {443, 443}, + {444, 447}, {448, 451}, {452, 659}, {660, 660}, + {661, 687}, {688, 705}, {710, 721}, {736, 740}, + {748, 748}, {750, 750}, {768, 879}, {880, 883}, + {884, 884}, {886, 887}, {890, 890}, {891, 893}, + {895, 895}, {902, 902}, {903, 903}, {904, 906}, + {908, 908}, {910, 929}, {931, 1013}, {1015, 1153}, + {1155, 1159}, {1162, 1327}, {1329, 1366}, {1369, 1369}, + {1376, 1416}, {1425, 1469}, {1471, 1471}, {1473, 1474}, + {1476, 1477}, {1479, 1479}, {1488, 1514}, {1519, 1522}, + {1552, 1562}, {1568, 1599}, {1600, 1600}, {1601, 1610}, + {1611, 1631}, {1632, 1641}, {1646, 1647}, {1648, 1648}, + {1649, 1747}, {1749, 1749}, {1750, 1756}, {1759, 1764}, + {1765, 1766}, {1767, 1768}, {1770, 1773}, {1774, 1775}, + {1776, 1785}, {1786, 1788}, {1791, 1791}, {1808, 1808}, + {1809, 1809}, {1810, 1839}, {1840, 1866}, {1869, 1957}, + {1958, 1968}, {1969, 1969}, {1984, 1993}, {1994, 2026}, + {2027, 2035}, {2036, 2037}, {2042, 2042}, {2045, 2045}, + {2048, 2069}, {2070, 2073}, {2074, 2074}, {2075, 2083}, + {2084, 2084}, {2085, 2087}, {2088, 2088}, {2089, 2093}, + {2112, 2136}, {2137, 2139}, {2144, 2154}, {2160, 2183}, + {2185, 2190}, {2199, 2207}, {2208, 2248}, {2249, 2249}, + {2250, 2273}, {2275, 2306}, {2307, 2307}, {2308, 2361}, + {2362, 2362}, {2363, 2363}, {2364, 2364}, {2365, 2365}, + {2366, 2368}, {2369, 2376}, {2377, 2380}, {2381, 2381}, + {2382, 2383}, {2384, 2384}, {2385, 2391}, {2392, 2401}, + {2402, 2403}, {2406, 2415}, {2417, 2417}, {2418, 2432}, + {2433, 2433}, {2434, 2435}, {2437, 2444}, {2447, 2448}, + {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489}, + {2492, 2492}, {2493, 2493}, {2494, 2496}, {2497, 2500}, + {2503, 2504}, {2507, 2508}, {2509, 2509}, {2510, 2510}, + {2519, 2519}, {2524, 2525}, {2527, 2529}, {2530, 2531}, + {2534, 2543}, {2544, 2545}, {2556, 2556}, {2558, 2558}, + {2561, 2562}, {2563, 2563}, {2565, 2570}, {2575, 2576}, + {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614}, + {2616, 2617}, {2620, 2620}, {2622, 2624}, {2625, 2626}, + {2631, 2632}, {2635, 2637}, {2641, 2641}, {2649, 2652}, + {2654, 2654}, {2662, 2671}, {2672, 2673}, {2674, 2676}, + {2677, 2677}, {2689, 2690}, {2691, 2691}, {2693, 2701}, + {2703, 2705}, {2707, 2728}, {2730, 2736}, {2738, 2739}, + {2741, 2745}, {2748, 2748}, {2749, 2749}, {2750, 2752}, + {2753, 2757}, {2759, 2760}, {2761, 2761}, {2763, 2764}, + {2765, 2765}, {2768, 2768}, {2784, 2785}, {2786, 2787}, + {2790, 2799}, {2809, 2809}, {2810, 2815}, {2817, 2817}, + {2818, 2819}, {2821, 2828}, {2831, 2832}, {2835, 2856}, + {2858, 2864}, {2866, 2867}, {2869, 2873}, {2876, 2876}, + {2877, 2877}, {2878, 2878}, {2879, 2879}, {2880, 2880}, + {2881, 2884}, {2887, 2888}, {2891, 2892}, {2893, 2893}, + {2901, 2902}, {2903, 2903}, {2908, 2909}, {2911, 2913}, + {2914, 2915}, {2918, 2927}, {2929, 2929}, {2946, 2946}, + {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965}, + {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980}, + {2984, 2986}, {2990, 3001}, {3006, 3007}, {3008, 3008}, + {3009, 3010}, {3014, 3016}, {3018, 3020}, {3021, 3021}, + {3024, 3024}, {3031, 3031}, {3046, 3055}, {3072, 3072}, + {3073, 3075}, {3076, 3076}, {3077, 3084}, {3086, 3088}, + {3090, 3112}, {3114, 3129}, {3132, 3132}, {3133, 3133}, + {3134, 3136}, {3137, 3140}, {3142, 3144}, {3146, 3149}, + {3157, 3158}, {3160, 3162}, {3165, 3165}, {3168, 3169}, + {3170, 3171}, {3174, 3183}, {3200, 3200}, {3201, 3201}, + {3202, 3203}, {3205, 3212}, {3214, 3216}, {3218, 3240}, + {3242, 3251}, {3253, 3257}, {3260, 3260}, {3261, 3261}, + {3262, 3262}, {3263, 3263}, {3264, 3268}, {3270, 3270}, + {3271, 3272}, {3274, 3275}, {3276, 3277}, {3285, 3286}, + {3293, 3294}, {3296, 3297}, {3298, 3299}, {3302, 3311}, + {3313, 3314}, {3315, 3315}, {3328, 3329}, {3330, 3331}, + {3332, 3340}, {3342, 3344}, {3346, 3386}, {3387, 3388}, + {3389, 3389}, {3390, 3392}, {3393, 3396}, {3398, 3400}, + {3402, 3404}, {3405, 3405}, {3406, 3406}, {3412, 3414}, + {3415, 3415}, {3423, 3425}, {3426, 3427}, {3430, 3439}, + {3450, 3455}, {3457, 3457}, {3458, 3459}, {3461, 3478}, + {3482, 3505}, {3507, 3515}, {3517, 3517}, {3520, 3526}, + {3530, 3530}, {3535, 3537}, {3538, 3540}, {3542, 3542}, + {3544, 3551}, {3558, 3567}, {3570, 3571}, {3585, 3632}, + {3633, 3633}, {3634, 3635}, {3636, 3642}, {3648, 3653}, + {3654, 3654}, {3655, 3662}, {3664, 3673}, {3713, 3714}, + {3716, 3716}, {3718, 3722}, {3724, 3747}, {3749, 3749}, + {3751, 3760}, {3761, 3761}, {3762, 3763}, {3764, 3772}, + {3773, 3773}, {3776, 3780}, {3782, 3782}, {3784, 3790}, + {3792, 3801}, {3804, 3807}, {3840, 3840}, {3864, 3865}, + {3872, 3881}, {3893, 3893}, {3895, 3895}, {3897, 3897}, + {3902, 3903}, {3904, 3911}, {3913, 3948}, {3953, 3966}, + {3967, 3967}, {3968, 3972}, {3974, 3975}, {3976, 3980}, + {3981, 3991}, {3993, 4028}, {4038, 4038}, {4096, 4138}, + {4139, 4140}, {4141, 4144}, {4145, 4145}, {4146, 4151}, + {4152, 4152}, {4153, 4154}, {4155, 4156}, {4157, 4158}, + {4159, 4159}, {4160, 4169}, {4176, 4181}, {4182, 4183}, + {4184, 4185}, {4186, 4189}, {4190, 4192}, {4193, 4193}, + {4194, 4196}, {4197, 4198}, {4199, 4205}, {4206, 4208}, + {4209, 4212}, {4213, 4225}, {4226, 4226}, {4227, 4228}, + {4229, 4230}, {4231, 4236}, {4237, 4237}, {4238, 4238}, + {4239, 4239}, {4240, 4249}, {4250, 4252}, {4253, 4253}, + {4256, 4293}, {4295, 4295}, {4301, 4301}, {4304, 4346}, + {4348, 4348}, {4349, 4351}, {4352, 4680}, {4682, 4685}, + {4688, 4694}, {4696, 4696}, {4698, 4701}, {4704, 4744}, + {4746, 4749}, {4752, 4784}, {4786, 4789}, {4792, 4798}, + {4800, 4800}, {4802, 4805}, {4808, 4822}, {4824, 4880}, + {4882, 4885}, {4888, 4954}, {4957, 4959}, {4969, 4977}, + {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740}, + {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872}, + {5873, 5880}, {5888, 5905}, {5906, 5908}, {5909, 5909}, + {5919, 5937}, {5938, 5939}, {5940, 5940}, {5952, 5969}, + {5970, 5971}, {5984, 5996}, {5998, 6000}, {6002, 6003}, + {6016, 6067}, {6068, 6069}, {6070, 6070}, {6071, 6077}, + {6078, 6085}, {6086, 6086}, {6087, 6088}, {6089, 6099}, + {6103, 6103}, {6108, 6108}, {6109, 6109}, {6112, 6121}, + {6155, 6157}, {6159, 6159}, {6160, 6169}, {6176, 6210}, + {6211, 6211}, {6212, 6264}, {6272, 6276}, {6277, 6278}, + {6279, 6312}, {6313, 6313}, {6314, 6314}, {6320, 6389}, + {6400, 6430}, {6432, 6434}, {6435, 6438}, {6439, 6440}, + {6441, 6443}, {6448, 6449}, {6450, 6450}, {6451, 6456}, + {6457, 6459}, {6470, 6479}, {6480, 6509}, {6512, 6516}, + {6528, 6571}, {6576, 6601}, {6608, 6617}, {6618, 6618}, + {6656, 6678}, {6679, 6680}, {6681, 6682}, {6683, 6683}, + {6688, 6740}, {6741, 6741}, {6742, 6742}, {6743, 6743}, + {6744, 6750}, {6752, 6752}, {6753, 6753}, {6754, 6754}, + {6755, 6756}, {6757, 6764}, {6765, 6770}, {6771, 6780}, + {6783, 6783}, {6784, 6793}, {6800, 6809}, {6823, 6823}, + {6832, 6845}, {6847, 6862}, {6912, 6915}, {6916, 6916}, + {6917, 6963}, {6964, 6964}, {6965, 6965}, {6966, 6970}, + {6971, 6971}, {6972, 6972}, {6973, 6977}, {6978, 6978}, + {6979, 6980}, {6981, 6988}, {6992, 7001}, {7019, 7027}, + {7040, 7041}, {7042, 7042}, {7043, 7072}, {7073, 7073}, + {7074, 7077}, {7078, 7079}, {7080, 7081}, {7082, 7082}, + {7083, 7085}, {7086, 7087}, {7088, 7097}, {7098, 7141}, + {7142, 7142}, {7143, 7143}, {7144, 7145}, {7146, 7148}, + {7149, 7149}, {7150, 7150}, {7151, 7153}, {7154, 7155}, + {7168, 7203}, {7204, 7211}, {7212, 7219}, {7220, 7221}, + {7222, 7223}, {7232, 7241}, {7245, 7247}, {7248, 7257}, + {7258, 7287}, {7288, 7293}, {7296, 7306}, {7312, 7354}, + {7357, 7359}, {7376, 7378}, {7380, 7392}, {7393, 7393}, + {7394, 7400}, {7401, 7404}, {7405, 7405}, {7406, 7411}, + {7412, 7412}, {7413, 7414}, {7415, 7415}, {7416, 7417}, + {7418, 7418}, {7424, 7467}, {7468, 7530}, {7531, 7543}, + {7544, 7544}, {7545, 7578}, {7579, 7615}, {7616, 7679}, + {7680, 7957}, {7960, 7965}, {7968, 8005}, {8008, 8013}, + {8016, 8023}, {8025, 8025}, {8027, 8027}, {8029, 8029}, + {8031, 8061}, {8064, 8116}, {8118, 8124}, {8126, 8126}, + {8130, 8132}, {8134, 8140}, {8144, 8147}, {8150, 8155}, + {8160, 8172}, {8178, 8180}, {8182, 8188}, {8204, 8205}, + {8255, 8256}, {8276, 8276}, {8305, 8305}, {8319, 8319}, + {8336, 8348}, {8400, 8412}, {8417, 8417}, {8421, 8432}, + {8450, 8450}, {8455, 8455}, {8458, 8467}, {8469, 8469}, + {8472, 8472}, {8473, 8477}, {8484, 8484}, {8486, 8486}, + {8488, 8488}, {8490, 8493}, {8494, 8494}, {8495, 8500}, + {8501, 8504}, {8505, 8505}, {8508, 8511}, {8517, 8521}, + {8526, 8526}, {8544, 8578}, {8579, 8580}, {8581, 8584}, + {11264, 11387}, {11388, 11389}, {11390, 11492}, {11499, 11502}, + {11503, 11505}, {11506, 11507}, {11520, 11557}, {11559, 11559}, + {11565, 11565}, {11568, 11623}, {11631, 11631}, {11647, 11647}, + {11648, 11670}, {11680, 11686}, {11688, 11694}, {11696, 11702}, + {11704, 11710}, {11712, 11718}, {11720, 11726}, {11728, 11734}, + {11736, 11742}, {11744, 11775}, {12293, 12293}, {12294, 12294}, + {12295, 12295}, {12321, 12329}, {12330, 12333}, {12334, 12335}, + {12337, 12341}, {12344, 12346}, {12347, 12347}, {12348, 12348}, + {12353, 12438}, {12441, 12442}, {12443, 12444}, {12445, 12446}, + {12447, 12447}, {12449, 12538}, {12539, 12539}, {12540, 12542}, + {12543, 12543}, {12549, 12591}, {12593, 12686}, {12704, 12735}, + {12784, 12799}, {13312, 19903}, {19968, 40980}, {40981, 40981}, + {40982, 42124}, {42192, 42231}, {42232, 42237}, {42240, 42507}, + {42508, 42508}, {42512, 42527}, {42528, 42537}, {42538, 42539}, + {42560, 42605}, {42606, 42606}, {42607, 42607}, {42612, 42621}, + {42623, 42623}, {42624, 42651}, {42652, 42653}, {42654, 42655}, + {42656, 42725}, {42726, 42735}, {42736, 42737}, {42775, 42783}, + {42786, 42863}, {42864, 42864}, {42865, 42887}, {42888, 42888}, + {42891, 42894}, {42895, 42895}, {42896, 42957}, {42960, 42961}, + {42963, 42963}, {42965, 42972}, {42994, 42996}, {42997, 42998}, + {42999, 42999}, {43000, 43001}, {43002, 43002}, {43003, 43009}, + {43010, 43010}, {43011, 43013}, {43014, 43014}, {43015, 43018}, + {43019, 43019}, {43020, 43042}, {43043, 43044}, {43045, 43046}, + {43047, 43047}, {43052, 43052}, {43072, 43123}, {43136, 43137}, + {43138, 43187}, {43188, 43203}, {43204, 43205}, {43216, 43225}, + {43232, 43249}, {43250, 43255}, {43259, 43259}, {43261, 43262}, + {43263, 43263}, {43264, 43273}, {43274, 43301}, {43302, 43309}, + {43312, 43334}, {43335, 43345}, {43346, 43347}, {43360, 43388}, + {43392, 43394}, {43395, 43395}, {43396, 43442}, {43443, 43443}, + {43444, 43445}, {43446, 43449}, {43450, 43451}, {43452, 43453}, + {43454, 43456}, {43471, 43471}, {43472, 43481}, {43488, 43492}, + {43493, 43493}, {43494, 43494}, {43495, 43503}, {43504, 43513}, + {43514, 43518}, {43520, 43560}, {43561, 43566}, {43567, 43568}, + {43569, 43570}, {43571, 43572}, {43573, 43574}, {43584, 43586}, + {43587, 43587}, {43588, 43595}, {43596, 43596}, {43597, 43597}, + {43600, 43609}, {43616, 43631}, {43632, 43632}, {43633, 43638}, + {43642, 43642}, {43643, 43643}, {43644, 43644}, {43645, 43645}, + {43646, 43695}, {43696, 43696}, {43697, 43697}, {43698, 43700}, + {43701, 43702}, {43703, 43704}, {43705, 43709}, {43710, 43711}, + {43712, 43712}, {43713, 43713}, {43714, 43714}, {43739, 43740}, + {43741, 43741}, {43744, 43754}, {43755, 43755}, {43756, 43757}, + {43758, 43759}, {43762, 43762}, {43763, 43764}, {43765, 43765}, + {43766, 43766}, {43777, 43782}, {43785, 43790}, {43793, 43798}, + {43808, 43814}, {43816, 43822}, {43824, 43866}, {43868, 43871}, + {43872, 43880}, {43881, 43881}, {43888, 43967}, {43968, 44002}, + {44003, 44004}, {44005, 44005}, {44006, 44007}, {44008, 44008}, + {44009, 44010}, {44012, 44012}, {44013, 44013}, {44016, 44025}, + {44032, 55203}, {55216, 55238}, {55243, 55291}, {63744, 64109}, + {64112, 64217}, {64256, 64262}, {64275, 64279}, {64285, 64285}, + {64286, 64286}, {64287, 64296}, {64298, 64310}, {64312, 64316}, + {64318, 64318}, {64320, 64321}, {64323, 64324}, {64326, 64433}, + {64467, 64829}, {64848, 64911}, {64914, 64967}, {65008, 65019}, + {65024, 65039}, {65056, 65071}, {65075, 65076}, {65101, 65103}, + {65136, 65140}, {65142, 65276}, {65296, 65305}, {65313, 65338}, + {65343, 65343}, {65345, 65370}, {65381, 65381}, {65382, 65391}, + {65392, 65392}, {65393, 65437}, {65438, 65439}, {65440, 65470}, + {65474, 65479}, {65482, 65487}, {65490, 65495}, {65498, 65500}, + {65536, 65547}, {65549, 65574}, {65576, 65594}, {65596, 65597}, + {65599, 65613}, {65616, 65629}, {65664, 65786}, {65856, 65908}, + {66045, 66045}, {66176, 66204}, {66208, 66256}, {66272, 66272}, + {66304, 66335}, {66349, 66368}, {66369, 66369}, {66370, 66377}, + {66378, 66378}, {66384, 66421}, {66422, 66426}, {66432, 66461}, + {66464, 66499}, {66504, 66511}, {66513, 66517}, {66560, 66639}, + {66640, 66717}, {66720, 66729}, {66736, 66771}, {66776, 66811}, + {66816, 66855}, {66864, 66915}, {66928, 66938}, {66940, 66954}, + {66956, 66962}, {66964, 66965}, {66967, 66977}, {66979, 66993}, + {66995, 67001}, {67003, 67004}, {67008, 67059}, {67072, 67382}, + {67392, 67413}, {67424, 67431}, {67456, 67461}, {67463, 67504}, + {67506, 67514}, {67584, 67589}, {67592, 67592}, {67594, 67637}, + {67639, 67640}, {67644, 67644}, {67647, 67669}, {67680, 67702}, + {67712, 67742}, {67808, 67826}, {67828, 67829}, {67840, 67861}, + {67872, 67897}, {67968, 68023}, {68030, 68031}, {68096, 68096}, + {68097, 68099}, {68101, 68102}, {68108, 68111}, {68112, 68115}, + {68117, 68119}, {68121, 68149}, {68152, 68154}, {68159, 68159}, + {68192, 68220}, {68224, 68252}, {68288, 68295}, {68297, 68324}, + {68325, 68326}, {68352, 68405}, {68416, 68437}, {68448, 68466}, + {68480, 68497}, {68608, 68680}, {68736, 68786}, {68800, 68850}, + {68864, 68899}, {68900, 68903}, {68912, 68921}, {68928, 68937}, + {68938, 68941}, {68942, 68942}, {68943, 68943}, {68944, 68965}, + {68969, 68973}, {68975, 68975}, {68976, 68997}, {69248, 69289}, + {69291, 69292}, {69296, 69297}, {69314, 69316}, {69372, 69375}, + {69376, 69404}, {69415, 69415}, {69424, 69445}, {69446, 69456}, + {69488, 69505}, {69506, 69509}, {69552, 69572}, {69600, 69622}, + {69632, 69632}, {69633, 69633}, {69634, 69634}, {69635, 69687}, + {69688, 69702}, {69734, 69743}, {69744, 69744}, {69745, 69746}, + {69747, 69748}, {69749, 69749}, {69759, 69761}, {69762, 69762}, + {69763, 69807}, {69808, 69810}, {69811, 69814}, {69815, 69816}, + {69817, 69818}, {69826, 69826}, {69840, 69864}, {69872, 69881}, + {69888, 69890}, {69891, 69926}, {69927, 69931}, {69932, 69932}, + {69933, 69940}, {69942, 69951}, {69956, 69956}, {69957, 69958}, + {69959, 69959}, {69968, 70002}, {70003, 70003}, {70006, 70006}, + {70016, 70017}, {70018, 70018}, {70019, 70066}, {70067, 70069}, + {70070, 70078}, {70079, 70080}, {70081, 70084}, {70089, 70092}, + {70094, 70094}, {70095, 70095}, {70096, 70105}, {70106, 70106}, + {70108, 70108}, {70144, 70161}, {70163, 70187}, {70188, 70190}, + {70191, 70193}, {70194, 70195}, {70196, 70196}, {70197, 70197}, + {70198, 70199}, {70206, 70206}, {70207, 70208}, {70209, 70209}, + {70272, 70278}, {70280, 70280}, {70282, 70285}, {70287, 70301}, + {70303, 70312}, {70320, 70366}, {70367, 70367}, {70368, 70370}, + {70371, 70378}, {70384, 70393}, {70400, 70401}, {70402, 70403}, + {70405, 70412}, {70415, 70416}, {70419, 70440}, {70442, 70448}, + {70450, 70451}, {70453, 70457}, {70459, 70460}, {70461, 70461}, + {70462, 70463}, {70464, 70464}, {70465, 70468}, {70471, 70472}, + {70475, 70477}, {70480, 70480}, {70487, 70487}, {70493, 70497}, + {70498, 70499}, {70502, 70508}, {70512, 70516}, {70528, 70537}, + {70539, 70539}, {70542, 70542}, {70544, 70581}, {70583, 70583}, + {70584, 70586}, {70587, 70592}, {70594, 70594}, {70597, 70597}, + {70599, 70602}, {70604, 70605}, {70606, 70606}, {70607, 70607}, + {70608, 70608}, {70609, 70609}, {70610, 70610}, {70611, 70611}, + {70625, 70626}, {70656, 70708}, {70709, 70711}, {70712, 70719}, + {70720, 70721}, {70722, 70724}, {70725, 70725}, {70726, 70726}, + {70727, 70730}, {70736, 70745}, {70750, 70750}, {70751, 70753}, + {70784, 70831}, {70832, 70834}, {70835, 70840}, {70841, 70841}, + {70842, 70842}, {70843, 70846}, {70847, 70848}, {70849, 70849}, + {70850, 70851}, {70852, 70853}, {70855, 70855}, {70864, 70873}, + {71040, 71086}, {71087, 71089}, {71090, 71093}, {71096, 71099}, + {71100, 71101}, {71102, 71102}, {71103, 71104}, {71128, 71131}, + {71132, 71133}, {71168, 71215}, {71216, 71218}, {71219, 71226}, + {71227, 71228}, {71229, 71229}, {71230, 71230}, {71231, 71232}, + {71236, 71236}, {71248, 71257}, {71296, 71338}, {71339, 71339}, + {71340, 71340}, {71341, 71341}, {71342, 71343}, {71344, 71349}, + {71350, 71350}, {71351, 71351}, {71352, 71352}, {71360, 71369}, + {71376, 71395}, {71424, 71450}, {71453, 71453}, {71454, 71454}, + {71455, 71455}, {71456, 71457}, {71458, 71461}, {71462, 71462}, + {71463, 71467}, {71472, 71481}, {71488, 71494}, {71680, 71723}, + {71724, 71726}, {71727, 71735}, {71736, 71736}, {71737, 71738}, + {71840, 71903}, {71904, 71913}, {71935, 71942}, {71945, 71945}, + {71948, 71955}, {71957, 71958}, {71960, 71983}, {71984, 71989}, + {71991, 71992}, {71995, 71996}, {71997, 71997}, {71998, 71998}, + {71999, 71999}, {72000, 72000}, {72001, 72001}, {72002, 72002}, + {72003, 72003}, {72016, 72025}, {72096, 72103}, {72106, 72144}, + {72145, 72147}, {72148, 72151}, {72154, 72155}, {72156, 72159}, + {72160, 72160}, {72161, 72161}, {72163, 72163}, {72164, 72164}, + {72192, 72192}, {72193, 72202}, {72203, 72242}, {72243, 72248}, + {72249, 72249}, {72250, 72250}, {72251, 72254}, {72263, 72263}, + {72272, 72272}, {72273, 72278}, {72279, 72280}, {72281, 72283}, + {72284, 72329}, {72330, 72342}, {72343, 72343}, {72344, 72345}, + {72349, 72349}, {72368, 72440}, {72640, 72672}, {72688, 72697}, + {72704, 72712}, {72714, 72750}, {72751, 72751}, {72752, 72758}, + {72760, 72765}, {72766, 72766}, {72767, 72767}, {72768, 72768}, + {72784, 72793}, {72818, 72847}, {72850, 72871}, {72873, 72873}, + {72874, 72880}, {72881, 72881}, {72882, 72883}, {72884, 72884}, + {72885, 72886}, {72960, 72966}, {72968, 72969}, {72971, 73008}, + {73009, 73014}, {73018, 73018}, {73020, 73021}, {73023, 73029}, + {73030, 73030}, {73031, 73031}, {73040, 73049}, {73056, 73061}, + {73063, 73064}, {73066, 73097}, {73098, 73102}, {73104, 73105}, + {73107, 73108}, {73109, 73109}, {73110, 73110}, {73111, 73111}, + {73112, 73112}, {73120, 73129}, {73440, 73458}, {73459, 73460}, + {73461, 73462}, {73472, 73473}, {73474, 73474}, {73475, 73475}, + {73476, 73488}, {73490, 73523}, {73524, 73525}, {73526, 73530}, + {73534, 73535}, {73536, 73536}, {73537, 73537}, {73538, 73538}, + {73552, 73561}, {73562, 73562}, {73648, 73648}, {73728, 74649}, + {74752, 74862}, {74880, 75075}, {77712, 77808}, {77824, 78895}, + {78912, 78912}, {78913, 78918}, {78919, 78933}, {78944, 82938}, + {82944, 83526}, {90368, 90397}, {90398, 90409}, {90410, 90412}, + {90413, 90415}, {90416, 90425}, {92160, 92728}, {92736, 92766}, + {92768, 92777}, {92784, 92862}, {92864, 92873}, {92880, 92909}, + {92912, 92916}, {92928, 92975}, {92976, 92982}, {92992, 92995}, + {93008, 93017}, {93027, 93047}, {93053, 93071}, {93504, 93506}, + {93507, 93546}, {93547, 93548}, {93552, 93561}, {93760, 93823}, + {93952, 94026}, {94031, 94031}, {94032, 94032}, {94033, 94087}, + {94095, 94098}, {94099, 94111}, {94176, 94177}, {94179, 94179}, + {94180, 94180}, {94192, 94193}, {94208, 100343}, {100352, 101589}, + {101631, 101640}, {110576, 110579}, {110581, 110587}, {110589, 110590}, + {110592, 110882}, {110898, 110898}, {110928, 110930}, {110933, 110933}, + {110948, 110951}, {110960, 111355}, {113664, 113770}, {113776, 113788}, + {113792, 113800}, {113808, 113817}, {113821, 113822}, {118000, 118009}, + {118528, 118573}, {118576, 118598}, {119141, 119142}, {119143, 119145}, + {119149, 119154}, {119163, 119170}, {119173, 119179}, {119210, 119213}, + {119362, 119364}, {119808, 119892}, {119894, 119964}, {119966, 119967}, + {119970, 119970}, {119973, 119974}, {119977, 119980}, {119982, 119993}, + {119995, 119995}, {119997, 120003}, {120005, 120069}, {120071, 120074}, + {120077, 120084}, {120086, 120092}, {120094, 120121}, {120123, 120126}, + {120128, 120132}, {120134, 120134}, {120138, 120144}, {120146, 120485}, + {120488, 120512}, {120514, 120538}, {120540, 120570}, {120572, 120596}, + {120598, 120628}, {120630, 120654}, {120656, 120686}, {120688, 120712}, + {120714, 120744}, {120746, 120770}, {120772, 120779}, {120782, 120831}, + {121344, 121398}, {121403, 121452}, {121461, 121461}, {121476, 121476}, + {121499, 121503}, {121505, 121519}, {122624, 122633}, {122634, 122634}, + {122635, 122654}, {122661, 122666}, {122880, 122886}, {122888, 122904}, + {122907, 122913}, {122915, 122916}, {122918, 122922}, {122928, 122989}, + {123023, 123023}, {123136, 123180}, {123184, 123190}, {123191, 123197}, + {123200, 123209}, {123214, 123214}, {123536, 123565}, {123566, 123566}, + {123584, 123627}, {123628, 123631}, {123632, 123641}, {124112, 124138}, + {124139, 124139}, {124140, 124143}, {124144, 124153}, {124368, 124397}, + {124398, 124399}, {124400, 124400}, {124401, 124410}, {124896, 124902}, + {124904, 124907}, {124909, 124910}, {124912, 124926}, {124928, 125124}, + {125136, 125142}, {125184, 125251}, {125252, 125258}, {125259, 125259}, + {125264, 125273}, {126464, 126467}, {126469, 126495}, {126497, 126498}, + {126500, 126500}, {126503, 126503}, {126505, 126514}, {126516, 126519}, + {126521, 126521}, {126523, 126523}, {126530, 126530}, {126535, 126535}, + {126537, 126537}, {126539, 126539}, {126541, 126543}, {126545, 126546}, + {126548, 126548}, {126551, 126551}, {126553, 126553}, {126555, 126555}, + {126557, 126557}, {126559, 126559}, {126561, 126562}, {126564, 126564}, + {126567, 126570}, {126572, 126578}, {126580, 126583}, {126585, 126588}, + {126590, 126590}, {126592, 126601}, {126603, 126619}, {126625, 126627}, + {126629, 126633}, {126635, 126651}, {130032, 130041}, {131072, 173791}, + {173824, 177977}, {177984, 178205}, {178208, 183969}, {183984, 191456}, + {191472, 192093}, {194560, 195101}, {196608, 201546}, {201552, 205743}, + {917760, 917999} +}; +const uint32_t id_start[763][2] = +{ + {65, 90}, {97, 122}, {170, 170}, {181, 181}, + {186, 186}, {192, 214}, {216, 246}, {248, 442}, + {443, 443}, {444, 447}, {448, 451}, {452, 659}, + {660, 660}, {661, 687}, {688, 705}, {710, 721}, + {736, 740}, {748, 748}, {750, 750}, {880, 883}, + {884, 884}, {886, 887}, {890, 890}, {891, 893}, + {895, 895}, {902, 902}, {904, 906}, {908, 908}, + {910, 929}, {931, 1013}, {1015, 1153}, {1162, 1327}, + {1329, 1366}, {1369, 1369}, {1376, 1416}, {1488, 1514}, + {1519, 1522}, {1568, 1599}, {1600, 1600}, {1601, 1610}, + {1646, 1647}, {1649, 1747}, {1749, 1749}, {1765, 1766}, + {1774, 1775}, {1786, 1788}, {1791, 1791}, {1808, 1808}, + {1810, 1839}, {1869, 1957}, {1969, 1969}, {1994, 2026}, + {2036, 2037}, {2042, 2042}, {2048, 2069}, {2074, 2074}, + {2084, 2084}, {2088, 2088}, {2112, 2136}, {2144, 2154}, + {2160, 2183}, {2185, 2190}, {2208, 2248}, {2249, 2249}, + {2308, 2361}, {2365, 2365}, {2384, 2384}, {2392, 2401}, + {2417, 2417}, {2418, 2432}, {2437, 2444}, {2447, 2448}, + {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489}, + {2493, 2493}, {2510, 2510}, {2524, 2525}, {2527, 2529}, + {2544, 2545}, {2556, 2556}, {2565, 2570}, {2575, 2576}, + {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614}, + {2616, 2617}, {2649, 2652}, {2654, 2654}, {2674, 2676}, + {2693, 2701}, {2703, 2705}, {2707, 2728}, {2730, 2736}, + {2738, 2739}, {2741, 2745}, {2749, 2749}, {2768, 2768}, + {2784, 2785}, {2809, 2809}, {2821, 2828}, {2831, 2832}, + {2835, 2856}, {2858, 2864}, {2866, 2867}, {2869, 2873}, + {2877, 2877}, {2908, 2909}, {2911, 2913}, {2929, 2929}, + {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965}, + {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980}, + {2984, 2986}, {2990, 3001}, {3024, 3024}, {3077, 3084}, + {3086, 3088}, {3090, 3112}, {3114, 3129}, {3133, 3133}, + {3160, 3162}, {3165, 3165}, {3168, 3169}, {3200, 3200}, + {3205, 3212}, {3214, 3216}, {3218, 3240}, {3242, 3251}, + {3253, 3257}, {3261, 3261}, {3293, 3294}, {3296, 3297}, + {3313, 3314}, {3332, 3340}, {3342, 3344}, {3346, 3386}, + {3389, 3389}, {3406, 3406}, {3412, 3414}, {3423, 3425}, + {3450, 3455}, {3461, 3478}, {3482, 3505}, {3507, 3515}, + {3517, 3517}, {3520, 3526}, {3585, 3632}, {3634, 3635}, + {3648, 3653}, {3654, 3654}, {3713, 3714}, {3716, 3716}, + {3718, 3722}, {3724, 3747}, {3749, 3749}, {3751, 3760}, + {3762, 3763}, {3773, 3773}, {3776, 3780}, {3782, 3782}, + {3804, 3807}, {3840, 3840}, {3904, 3911}, {3913, 3948}, + {3976, 3980}, {4096, 4138}, {4159, 4159}, {4176, 4181}, + {4186, 4189}, {4193, 4193}, {4197, 4198}, {4206, 4208}, + {4213, 4225}, {4238, 4238}, {4256, 4293}, {4295, 4295}, + {4301, 4301}, {4304, 4346}, {4348, 4348}, {4349, 4351}, + {4352, 4680}, {4682, 4685}, {4688, 4694}, {4696, 4696}, + {4698, 4701}, {4704, 4744}, {4746, 4749}, {4752, 4784}, + {4786, 4789}, {4792, 4798}, {4800, 4800}, {4802, 4805}, + {4808, 4822}, {4824, 4880}, {4882, 4885}, {4888, 4954}, + {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740}, + {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872}, + {5873, 5880}, {5888, 5905}, {5919, 5937}, {5952, 5969}, + {5984, 5996}, {5998, 6000}, {6016, 6067}, {6103, 6103}, + {6108, 6108}, {6176, 6210}, {6211, 6211}, {6212, 6264}, + {6272, 6276}, {6277, 6278}, {6279, 6312}, {6314, 6314}, + {6320, 6389}, {6400, 6430}, {6480, 6509}, {6512, 6516}, + {6528, 6571}, {6576, 6601}, {6656, 6678}, {6688, 6740}, + {6823, 6823}, {6917, 6963}, {6981, 6988}, {7043, 7072}, + {7086, 7087}, {7098, 7141}, {7168, 7203}, {7245, 7247}, + {7258, 7287}, {7288, 7293}, {7296, 7306}, {7312, 7354}, + {7357, 7359}, {7401, 7404}, {7406, 7411}, {7413, 7414}, + {7418, 7418}, {7424, 7467}, {7468, 7530}, {7531, 7543}, + {7544, 7544}, {7545, 7578}, {7579, 7615}, {7680, 7957}, + {7960, 7965}, {7968, 8005}, {8008, 8013}, {8016, 8023}, + {8025, 8025}, {8027, 8027}, {8029, 8029}, {8031, 8061}, + {8064, 8116}, {8118, 8124}, {8126, 8126}, {8130, 8132}, + {8134, 8140}, {8144, 8147}, {8150, 8155}, {8160, 8172}, + {8178, 8180}, {8182, 8188}, {8305, 8305}, {8319, 8319}, + {8336, 8348}, {8450, 8450}, {8455, 8455}, {8458, 8467}, + {8469, 8469}, {8472, 8472}, {8473, 8477}, {8484, 8484}, + {8486, 8486}, {8488, 8488}, {8490, 8493}, {8494, 8494}, + {8495, 8500}, {8501, 8504}, {8505, 8505}, {8508, 8511}, + {8517, 8521}, {8526, 8526}, {8544, 8578}, {8579, 8580}, + {8581, 8584}, {11264, 11387}, {11388, 11389}, {11390, 11492}, + {11499, 11502}, {11506, 11507}, {11520, 11557}, {11559, 11559}, + {11565, 11565}, {11568, 11623}, {11631, 11631}, {11648, 11670}, + {11680, 11686}, {11688, 11694}, {11696, 11702}, {11704, 11710}, + {11712, 11718}, {11720, 11726}, {11728, 11734}, {11736, 11742}, + {12293, 12293}, {12294, 12294}, {12295, 12295}, {12321, 12329}, + {12337, 12341}, {12344, 12346}, {12347, 12347}, {12348, 12348}, + {12353, 12438}, {12443, 12444}, {12445, 12446}, {12447, 12447}, + {12449, 12538}, {12540, 12542}, {12543, 12543}, {12549, 12591}, + {12593, 12686}, {12704, 12735}, {12784, 12799}, {13312, 19903}, + {19968, 40980}, {40981, 40981}, {40982, 42124}, {42192, 42231}, + {42232, 42237}, {42240, 42507}, {42508, 42508}, {42512, 42527}, + {42538, 42539}, {42560, 42605}, {42606, 42606}, {42623, 42623}, + {42624, 42651}, {42652, 42653}, {42656, 42725}, {42726, 42735}, + {42775, 42783}, {42786, 42863}, {42864, 42864}, {42865, 42887}, + {42888, 42888}, {42891, 42894}, {42895, 42895}, {42896, 42957}, + {42960, 42961}, {42963, 42963}, {42965, 42972}, {42994, 42996}, + {42997, 42998}, {42999, 42999}, {43000, 43001}, {43002, 43002}, + {43003, 43009}, {43011, 43013}, {43015, 43018}, {43020, 43042}, + {43072, 43123}, {43138, 43187}, {43250, 43255}, {43259, 43259}, + {43261, 43262}, {43274, 43301}, {43312, 43334}, {43360, 43388}, + {43396, 43442}, {43471, 43471}, {43488, 43492}, {43494, 43494}, + {43495, 43503}, {43514, 43518}, {43520, 43560}, {43584, 43586}, + {43588, 43595}, {43616, 43631}, {43632, 43632}, {43633, 43638}, + {43642, 43642}, {43646, 43695}, {43697, 43697}, {43701, 43702}, + {43705, 43709}, {43712, 43712}, {43714, 43714}, {43739, 43740}, + {43741, 43741}, {43744, 43754}, {43762, 43762}, {43763, 43764}, + {43777, 43782}, {43785, 43790}, {43793, 43798}, {43808, 43814}, + {43816, 43822}, {43824, 43866}, {43868, 43871}, {43872, 43880}, + {43881, 43881}, {43888, 43967}, {43968, 44002}, {44032, 55203}, + {55216, 55238}, {55243, 55291}, {63744, 64109}, {64112, 64217}, + {64256, 64262}, {64275, 64279}, {64285, 64285}, {64287, 64296}, + {64298, 64310}, {64312, 64316}, {64318, 64318}, {64320, 64321}, + {64323, 64324}, {64326, 64433}, {64467, 64829}, {64848, 64911}, + {64914, 64967}, {65008, 65019}, {65136, 65140}, {65142, 65276}, + {65313, 65338}, {65345, 65370}, {65382, 65391}, {65392, 65392}, + {65393, 65437}, {65438, 65439}, {65440, 65470}, {65474, 65479}, + {65482, 65487}, {65490, 65495}, {65498, 65500}, {65536, 65547}, + {65549, 65574}, {65576, 65594}, {65596, 65597}, {65599, 65613}, + {65616, 65629}, {65664, 65786}, {65856, 65908}, {66176, 66204}, + {66208, 66256}, {66304, 66335}, {66349, 66368}, {66369, 66369}, + {66370, 66377}, {66378, 66378}, {66384, 66421}, {66432, 66461}, + {66464, 66499}, {66504, 66511}, {66513, 66517}, {66560, 66639}, + {66640, 66717}, {66736, 66771}, {66776, 66811}, {66816, 66855}, + {66864, 66915}, {66928, 66938}, {66940, 66954}, {66956, 66962}, + {66964, 66965}, {66967, 66977}, {66979, 66993}, {66995, 67001}, + {67003, 67004}, {67008, 67059}, {67072, 67382}, {67392, 67413}, + {67424, 67431}, {67456, 67461}, {67463, 67504}, {67506, 67514}, + {67584, 67589}, {67592, 67592}, {67594, 67637}, {67639, 67640}, + {67644, 67644}, {67647, 67669}, {67680, 67702}, {67712, 67742}, + {67808, 67826}, {67828, 67829}, {67840, 67861}, {67872, 67897}, + {67968, 68023}, {68030, 68031}, {68096, 68096}, {68112, 68115}, + {68117, 68119}, {68121, 68149}, {68192, 68220}, {68224, 68252}, + {68288, 68295}, {68297, 68324}, {68352, 68405}, {68416, 68437}, + {68448, 68466}, {68480, 68497}, {68608, 68680}, {68736, 68786}, + {68800, 68850}, {68864, 68899}, {68938, 68941}, {68942, 68942}, + {68943, 68943}, {68944, 68965}, {68975, 68975}, {68976, 68997}, + {69248, 69289}, {69296, 69297}, {69314, 69316}, {69376, 69404}, + {69415, 69415}, {69424, 69445}, {69488, 69505}, {69552, 69572}, + {69600, 69622}, {69635, 69687}, {69745, 69746}, {69749, 69749}, + {69763, 69807}, {69840, 69864}, {69891, 69926}, {69956, 69956}, + {69959, 69959}, {69968, 70002}, {70006, 70006}, {70019, 70066}, + {70081, 70084}, {70106, 70106}, {70108, 70108}, {70144, 70161}, + {70163, 70187}, {70207, 70208}, {70272, 70278}, {70280, 70280}, + {70282, 70285}, {70287, 70301}, {70303, 70312}, {70320, 70366}, + {70405, 70412}, {70415, 70416}, {70419, 70440}, {70442, 70448}, + {70450, 70451}, {70453, 70457}, {70461, 70461}, {70480, 70480}, + {70493, 70497}, {70528, 70537}, {70539, 70539}, {70542, 70542}, + {70544, 70581}, {70583, 70583}, {70609, 70609}, {70611, 70611}, + {70656, 70708}, {70727, 70730}, {70751, 70753}, {70784, 70831}, + {70852, 70853}, {70855, 70855}, {71040, 71086}, {71128, 71131}, + {71168, 71215}, {71236, 71236}, {71296, 71338}, {71352, 71352}, + {71424, 71450}, {71488, 71494}, {71680, 71723}, {71840, 71903}, + {71935, 71942}, {71945, 71945}, {71948, 71955}, {71957, 71958}, + {71960, 71983}, {71999, 71999}, {72001, 72001}, {72096, 72103}, + {72106, 72144}, {72161, 72161}, {72163, 72163}, {72192, 72192}, + {72203, 72242}, {72250, 72250}, {72272, 72272}, {72284, 72329}, + {72349, 72349}, {72368, 72440}, {72640, 72672}, {72704, 72712}, + {72714, 72750}, {72768, 72768}, {72818, 72847}, {72960, 72966}, + {72968, 72969}, {72971, 73008}, {73030, 73030}, {73056, 73061}, + {73063, 73064}, {73066, 73097}, {73112, 73112}, {73440, 73458}, + {73474, 73474}, {73476, 73488}, {73490, 73523}, {73648, 73648}, + {73728, 74649}, {74752, 74862}, {74880, 75075}, {77712, 77808}, + {77824, 78895}, {78913, 78918}, {78944, 82938}, {82944, 83526}, + {90368, 90397}, {92160, 92728}, {92736, 92766}, {92784, 92862}, + {92880, 92909}, {92928, 92975}, {92992, 92995}, {93027, 93047}, + {93053, 93071}, {93504, 93506}, {93507, 93546}, {93547, 93548}, + {93760, 93823}, {93952, 94026}, {94032, 94032}, {94099, 94111}, + {94176, 94177}, {94179, 94179}, {94208, 100343}, {100352, 101589}, + {101631, 101640}, {110576, 110579}, {110581, 110587}, {110589, 110590}, + {110592, 110882}, {110898, 110898}, {110928, 110930}, {110933, 110933}, + {110948, 110951}, {110960, 111355}, {113664, 113770}, {113776, 113788}, + {113792, 113800}, {113808, 113817}, {119808, 119892}, {119894, 119964}, + {119966, 119967}, {119970, 119970}, {119973, 119974}, {119977, 119980}, + {119982, 119993}, {119995, 119995}, {119997, 120003}, {120005, 120069}, + {120071, 120074}, {120077, 120084}, {120086, 120092}, {120094, 120121}, + {120123, 120126}, {120128, 120132}, {120134, 120134}, {120138, 120144}, + {120146, 120485}, {120488, 120512}, {120514, 120538}, {120540, 120570}, + {120572, 120596}, {120598, 120628}, {120630, 120654}, {120656, 120686}, + {120688, 120712}, {120714, 120744}, {120746, 120770}, {120772, 120779}, + {122624, 122633}, {122634, 122634}, {122635, 122654}, {122661, 122666}, + {122928, 122989}, {123136, 123180}, {123191, 123197}, {123214, 123214}, + {123536, 123565}, {123584, 123627}, {124112, 124138}, {124139, 124139}, + {124368, 124397}, {124400, 124400}, {124896, 124902}, {124904, 124907}, + {124909, 124910}, {124912, 124926}, {124928, 125124}, {125184, 125251}, + {125259, 125259}, {126464, 126467}, {126469, 126495}, {126497, 126498}, + {126500, 126500}, {126503, 126503}, {126505, 126514}, {126516, 126519}, + {126521, 126521}, {126523, 126523}, {126530, 126530}, {126535, 126535}, + {126537, 126537}, {126539, 126539}, {126541, 126543}, {126545, 126546}, + {126548, 126548}, {126551, 126551}, {126553, 126553}, {126555, 126555}, + {126557, 126557}, {126559, 126559}, {126561, 126562}, {126564, 126564}, + {126567, 126570}, {126572, 126578}, {126580, 126583}, {126585, 126588}, + {126590, 126590}, {126592, 126601}, {126603, 126619}, {126625, 126627}, + {126629, 126633}, {126635, 126651}, {131072, 173791}, {173824, 177977}, + {177984, 178205}, {178208, 183969}, {183984, 191456}, {191472, 192093}, + {194560, 195101}, {196608, 201546}, {201552, 205743} +}; + + +} // namespace ada::idna +#endif // ADA_IDNA_IDENTIFIER_TABLES_H +/* end file src/id_tables.cpp */ + +namespace ada::idna { +constexpr bool is_ascii_letter(char32_t c) noexcept { + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); +} + +constexpr bool is_ascii_letter_or_digit(char32_t c) noexcept { + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9'); +} + +bool valid_name_code_point(char32_t code_point, bool first) { + // https://tc39.es/ecma262/#prod-IdentifierStart + // Fast paths: + if (first && + (code_point == '$' || code_point == '_' || is_ascii_letter(code_point))) { + return true; + } + if (!first && (code_point == '$' || is_ascii_letter_or_digit(code_point))) { + return true; + } + // Slow path... + if (code_point == 0xffffffff) { + return false; // minimal error handling + } + if (first) { + auto iter = std::lower_bound( + std::begin(ada::idna::id_start), std::end(ada::idna::id_start), + code_point, + [](const uint32_t* range, uint32_t cp) { return range[1] < cp; }); + return iter != std::end(id_start) && code_point >= (*iter)[0]; + } else { + auto iter = std::lower_bound( + std::begin(id_continue), std::end(id_continue), code_point, + [](const uint32_t* range, uint32_t cp) { return range[1] < cp; }); + return iter != std::end(id_start) && code_point >= (*iter)[0]; + } +} +} // namespace ada::idna +/* end file src/identifier.cpp */ /* end file src/idna.cpp */ /* end file src/ada_idna.cpp */ ADA_POP_DISABLE_WARNINGS @@ -9792,8 +10447,12 @@ ADA_POP_DISABLE_WARNINGS #include #elif ADA_SSE2 #include +#elif ADA_LSX +#include #endif +#include + namespace ada::unicode { constexpr bool is_tabs_or_newline(char c) noexcept { @@ -9834,8 +10493,7 @@ ada_really_inline bool has_tabs_or_newline( std::string_view user_input) noexcept { // first check for short strings in which case we do it naively. if (user_input.size() < 16) { // slow path - return std::any_of(user_input.begin(), user_input.end(), - is_tabs_or_newline); + return std::ranges::any_of(user_input, is_tabs_or_newline); } // fast path for long strings (expected to be common) size_t i = 0; @@ -9873,8 +10531,7 @@ ada_really_inline bool has_tabs_or_newline( std::string_view user_input) noexcept { // first check for short strings in which case we do it naively. if (user_input.size() < 16) { // slow path - return std::any_of(user_input.begin(), user_input.end(), - is_tabs_or_newline); + return std::ranges::any_of(user_input, is_tabs_or_newline); } // fast path for long strings (expected to be common) size_t i = 0; @@ -9900,6 +10557,38 @@ ada_really_inline bool has_tabs_or_newline( } return _mm_movemask_epi8(running) != 0; } +#elif ADA_LSX +ada_really_inline bool has_tabs_or_newline( + std::string_view user_input) noexcept { + // first check for short strings in which case we do it naively. + if (user_input.size() < 16) { // slow path + return std::ranges::any_of(user_input, is_tabs_or_newline); + } + // fast path for long strings (expected to be common) + size_t i = 0; + const __m128i mask1 = __lsx_vrepli_b('\r'); + const __m128i mask2 = __lsx_vrepli_b('\n'); + const __m128i mask3 = __lsx_vrepli_b('\t'); + // If we supported SSSE3, we could use the algorithm that we use for NEON. + __m128i running{0}; + for (; i + 15 < user_input.size(); i += 16) { + __m128i word = __lsx_vld((const __m128i*)(user_input.data() + i), 0); + running = __lsx_vor_v( + __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1), + __lsx_vseq_b(word, mask2))), + __lsx_vseq_b(word, mask3)); + } + if (i < user_input.size()) { + __m128i word = __lsx_vld( + (const __m128i*)(user_input.data() + user_input.length() - 16), 0); + running = __lsx_vor_v( + __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1), + __lsx_vseq_b(word, mask2))), + __lsx_vseq_b(word, mask3)); + } + if (__lsx_bz_v(running)) return false; + return true; +} #else ada_really_inline bool has_tabs_or_newline( std::string_view user_input) noexcept { @@ -9936,7 +10625,7 @@ ada_really_inline bool has_tabs_or_newline( // U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or // U+007C (|). constexpr static std::array is_forbidden_host_code_point_table = - []() constexpr { + []() consteval { std::array result{}; for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<', '>', '?', '@', '[', '\\', ']', '^', '|'}) { @@ -9951,7 +10640,7 @@ ada_really_inline constexpr bool is_forbidden_host_code_point( } constexpr static std::array is_forbidden_domain_code_point_table = - []() constexpr { + []() consteval { std::array result{}; for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<', '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) { @@ -9990,7 +10679,7 @@ ada_really_inline constexpr bool contains_forbidden_domain_code_point( } constexpr static std::array - is_forbidden_domain_code_point_table_or_upper = []() constexpr { + is_forbidden_domain_code_point_table_or_upper = []() consteval { std::array result{}; for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<', '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) { @@ -10031,7 +10720,7 @@ contains_forbidden_domain_code_point_or_upper(const char* input, } // std::isalnum(c) || c == '+' || c == '-' || c == '.') is true for -constexpr static std::array is_alnum_plus_table = []() constexpr { +constexpr static std::array is_alnum_plus_table = []() consteval { std::array result{}; for (size_t c = 0; c < 256; c++) { result[c] = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || @@ -10052,6 +10741,17 @@ ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept { (c >= 'a' && c <= 'f'); } +ada_really_inline constexpr bool is_ascii_digit(const char c) noexcept { + // An ASCII digit is a code point in the range U+0030 (0) to U+0039 (9), + // inclusive. + return (c >= '0' && c <= '9'); +} + +ada_really_inline constexpr bool is_ascii(const char32_t c) noexcept { + // If code point is between U+0000 and U+007F inclusive, then return true. + return c <= 0x7F; +} + ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept { return (unsigned char)c <= ' '; } @@ -10064,7 +10764,7 @@ ada_really_inline constexpr bool is_ascii_tab_or_newline( constexpr std::string_view table_is_double_dot_path_segment[] = { "..", "%2e.", ".%2e", "%2e%2e"}; -ada_really_inline ada_constexpr bool is_double_dot_path_segment( +ada_really_inline constexpr bool is_double_dot_path_segment( std::string_view input) noexcept { // This will catch most cases: // The length must be 2,4 or 6. @@ -10152,7 +10852,6 @@ std::string percent_decode(const std::string_view input, size_t first_percent) { !is_ascii_hex_digit(pointer[2])))) { dest += ch; pointer++; - continue; } else { unsigned a = convert_hex_to_binary(pointer[1]); unsigned b = convert_hex_to_binary(pointer[2]); @@ -10166,10 +10865,9 @@ std::string percent_decode(const std::string_view input, size_t first_percent) { std::string percent_encode(const std::string_view input, const uint8_t character_set[]) { - auto pointer = - std::find_if(input.begin(), input.end(), [character_set](const char c) { - return character_sets::bit_at(character_set, c); - }); + auto pointer = std::ranges::find_if(input, [character_set](const char c) { + return character_sets::bit_at(character_set, c); + }); // Optimization: Don't iterate if percent encode is not required if (pointer == input.end()) { return std::string(input); @@ -10196,10 +10894,9 @@ bool percent_encode(const std::string_view input, const uint8_t character_set[], std::string& out) { ada_log("percent_encode ", input, " to output string while ", append ? "appending" : "overwriting"); - auto pointer = - std::find_if(input.begin(), input.end(), [character_set](const char c) { - return character_sets::bit_at(character_set, c); - }); + auto pointer = std::ranges::find_if(input, [character_set](const char c) { + return character_sets::bit_at(character_set, c); + }); ada_log("percent_encode done checking, moved to ", std::distance(input.begin(), pointer)); @@ -10208,11 +10905,12 @@ bool percent_encode(const std::string_view input, const uint8_t character_set[], ada_log("percent_encode encoding not needed."); return false; } - if (!append) { + if constexpr (!append) { out.clear(); } ada_log("percent_encode appending ", std::distance(input.begin(), pointer), " bytes"); + // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage) out.append(input.data(), std::distance(input.begin(), pointer)); ada_log("percent_encode processing ", std::distance(pointer, input.end()), " bytes"); @@ -10247,6 +10945,7 @@ bool to_ascii(std::optional& out, const std::string_view plain, std::string percent_encode(const std::string_view input, const uint8_t character_set[], size_t index) { std::string out; + // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage) out.append(input.data(), index); auto pointer = input.begin() + index; for (; pointer != input.end(); pointer++) { @@ -10262,8 +10961,8 @@ std::string percent_encode(const std::string_view input, } // namespace ada::unicode /* end file src/unicode.cpp */ /* begin file src/serializers.cpp */ - #include +#include #include namespace ada::serializers { @@ -10343,18 +11042,19 @@ std::string ipv4(const uint64_t address) noexcept { } // namespace ada::serializers /* end file src/serializers.cpp */ /* begin file src/implementation.cpp */ + #include namespace ada { template -ada_warn_unused tl::expected parse( +ada_warn_unused tl::expected parse( std::string_view input, const result_type* base_url) { result_type u = ada::parser::parse_url_impl(input, base_url); if (!u.is_valid) { - return tl::unexpected(errors::generic_error); + return tl::unexpected(errors::type_error); } return u; } @@ -10406,7 +11106,7 @@ bool can_parse(std::string_view input, const std::string_view* base_input) { return result.is_valid; } -ada_warn_unused std::string to_string(ada::encoding_type type) { +ada_warn_unused std::string_view to_string(ada::encoding_type type) { switch (type) { case ada::encoding_type::UTF8: return "UTF-8"; @@ -10423,8 +11123,6 @@ ada_warn_unused std::string to_string(ada::encoding_type type) { /* end file src/implementation.cpp */ /* begin file src/helpers.cpp */ -#include -#include #include #include @@ -10518,13 +11216,11 @@ ada_really_inline std::optional prune_hash( ada_really_inline bool shorten_path(std::string& path, ada::scheme::type type) noexcept { - size_t first_delimiter = path.find_first_of('/', 1); - // Let path be url's path. // If url's scheme is "file", path's size is 1, and path[0] is a normalized // Windows drive letter, then return. if (type == ada::scheme::type::FILE && - first_delimiter == std::string_view::npos && !path.empty()) { + path.find('/', 1) == std::string_view::npos && !path.empty()) { if (checkers::is_normalized_windows_drive_letter( helpers::substring(path, 1))) { return false; @@ -10543,13 +11239,11 @@ ada_really_inline bool shorten_path(std::string& path, ada_really_inline bool shorten_path(std::string_view& path, ada::scheme::type type) noexcept { - size_t first_delimiter = path.find_first_of('/', 1); - // Let path be url's path. // If url's scheme is "file", path's size is 1, and path[0] is a normalized // Windows drive letter, then return. if (type == ada::scheme::type::FILE && - first_delimiter == std::string_view::npos && !path.empty()) { + path.find('/', 1) == std::string_view::npos && !path.empty()) { if (checkers::is_normalized_windows_drive_letter( helpers::substring(path, 1))) { return false; @@ -10572,15 +11266,11 @@ ada_really_inline void remove_ascii_tab_or_newline( std::string& input) noexcept { // if this ever becomes a performance issue, we could use an approach similar // to has_tabs_or_newline - input.erase(std::remove_if(input.begin(), input.end(), - [](char c) { - return ada::unicode::is_ascii_tab_or_newline(c); - }), - input.end()); + std::erase_if(input, ada::unicode::is_ascii_tab_or_newline); } -ada_really_inline std::string_view substring(std::string_view input, - size_t pos) noexcept { +ada_really_inline constexpr std::string_view substring(std::string_view input, + size_t pos) noexcept { ADA_ASSERT_TRUE(pos <= input.size()); // The following is safer but unneeded if we have the above line: // return pos > input.size() ? std::string_view() : input.substr(pos); @@ -10734,10 +11424,62 @@ ada_really_inline size_t find_next_host_delimiter_special( } return size_t(view.length()); } +#elif ADA_LSX +ada_really_inline size_t find_next_host_delimiter_special( + std::string_view view, size_t location) noexcept { + // first check for short strings in which case we do it naively. + if (view.size() - location < 16) { // slow path + for (size_t i = location; i < view.size(); i++) { + if (view[i] == ':' || view[i] == '/' || view[i] == '\\' || + view[i] == '?' || view[i] == '[') { + return i; + } + } + return size_t(view.size()); + } + // fast path for long strings (expected to be common) + size_t i = location; + const __m128i mask1 = __lsx_vrepli_b(':'); + const __m128i mask2 = __lsx_vrepli_b('/'); + const __m128i mask3 = __lsx_vrepli_b('\\'); + const __m128i mask4 = __lsx_vrepli_b('?'); + const __m128i mask5 = __lsx_vrepli_b('['); + + for (; i + 15 < view.size(); i += 16) { + __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0); + __m128i m1 = __lsx_vseq_b(word, mask1); + __m128i m2 = __lsx_vseq_b(word, mask2); + __m128i m3 = __lsx_vseq_b(word, mask3); + __m128i m4 = __lsx_vseq_b(word, mask4); + __m128i m5 = __lsx_vseq_b(word, mask5); + __m128i m = + __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5); + int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0); + if (mask != 0) { + return i + trailing_zeroes(mask); + } + } + if (i < view.size()) { + __m128i word = + __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0); + __m128i m1 = __lsx_vseq_b(word, mask1); + __m128i m2 = __lsx_vseq_b(word, mask2); + __m128i m3 = __lsx_vseq_b(word, mask3); + __m128i m4 = __lsx_vseq_b(word, mask4); + __m128i m5 = __lsx_vseq_b(word, mask5); + __m128i m = + __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5); + int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0); + if (mask != 0) { + return view.length() - 16 + trailing_zeroes(mask); + } + } + return size_t(view.length()); +} #else // : / [ \\ ? static constexpr std::array special_host_delimiters = - []() constexpr { + []() consteval { std::array result{}; for (int i : {':', '/', '[', '\\', '?'}) { result[i] = 1; @@ -10867,9 +11609,56 @@ ada_really_inline size_t find_next_host_delimiter(std::string_view view, } return size_t(view.length()); } +#elif ADA_LSX +ada_really_inline size_t find_next_host_delimiter(std::string_view view, + size_t location) noexcept { + // first check for short strings in which case we do it naively. + if (view.size() - location < 16) { // slow path + for (size_t i = location; i < view.size(); i++) { + if (view[i] == ':' || view[i] == '/' || view[i] == '?' || + view[i] == '[') { + return i; + } + } + return size_t(view.size()); + } + // fast path for long strings (expected to be common) + size_t i = location; + const __m128i mask1 = __lsx_vrepli_b(':'); + const __m128i mask2 = __lsx_vrepli_b('/'); + const __m128i mask4 = __lsx_vrepli_b('?'); + const __m128i mask5 = __lsx_vrepli_b('['); + + for (; i + 15 < view.size(); i += 16) { + __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0); + __m128i m1 = __lsx_vseq_b(word, mask1); + __m128i m2 = __lsx_vseq_b(word, mask2); + __m128i m4 = __lsx_vseq_b(word, mask4); + __m128i m5 = __lsx_vseq_b(word, mask5); + __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5)); + int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0); + if (mask != 0) { + return i + trailing_zeroes(mask); + } + } + if (i < view.size()) { + __m128i word = + __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0); + __m128i m1 = __lsx_vseq_b(word, mask1); + __m128i m2 = __lsx_vseq_b(word, mask2); + __m128i m4 = __lsx_vseq_b(word, mask4); + __m128i m5 = __lsx_vseq_b(word, mask5); + __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5)); + int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0); + if (mask != 0) { + return view.length() - 16 + trailing_zeroes(mask); + } + } + return size_t(view.length()); +} #else // : / [ ? -static constexpr std::array host_delimiters = []() constexpr { +static constexpr std::array host_delimiters = []() consteval { std::array result{}; for (int i : {':', '/', '?', '['}) { result[i] = 1; @@ -10969,7 +11758,7 @@ ada_really_inline std::pair get_host_delimiter_location( return {location, found_colon}; } -ada_really_inline void trim_c0_whitespace(std::string_view& input) noexcept { +void trim_c0_whitespace(std::string_view& input) noexcept { while (!input.empty() && ada::unicode::is_c0_control_or_space(input.front())) { input.remove_prefix(1); @@ -11009,15 +11798,20 @@ ada_really_inline void parse_prepared_path(std::string_view input, // Note: input cannot be empty, it must at least contain one character ('.') // Note: we know that '\' is not present. if (input[0] != '.') { - size_t slashdot = input.find("/."); - if (slashdot == std::string_view::npos) { // common case - trivial_path = true; - } else { // uncommon - // only three cases matter: /./, /.. or a final / - trivial_path = - !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' || - input[slashdot + 2] == '/'); + size_t slashdot = 0; + bool dot_is_file = true; + for (;;) { + slashdot = input.find("/.", slashdot); + if (slashdot == std::string_view::npos) { // common case + break; + } else { // uncommon + // only three cases matter: /./, /.. or a final / + slashdot += 2; + dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' || + input[slashdot] == '/'); + } } + trivial_path = dot_is_file; } } if (trivial_path) { @@ -11106,8 +11900,8 @@ ada_really_inline void parse_prepared_path(std::string_view input, ? path_buffer_tmp : path_view; if (unicode::is_double_dot_path_segment(path_buffer)) { - if ((helpers::shorten_path(path, type) || special) && - location == std::string_view::npos) { + helpers::shorten_path(path, type); + if (location == std::string_view::npos) { path += '/'; } } else if (unicode::is_single_dot_path_segment(path_buffer) && @@ -11164,7 +11958,7 @@ ada_really_inline void strip_trailing_spaces_from_opaque_path( // @ / \\ ? static constexpr std::array authority_delimiter_special = - []() constexpr { + []() consteval { std::array result{}; for (uint8_t i : {'@', '/', '\\', '?'}) { result[i] = 1; @@ -11185,7 +11979,7 @@ find_authority_delimiter_special(std::string_view view) noexcept { } // @ / ? -static constexpr std::array authority_delimiter = []() constexpr { +static constexpr std::array authority_delimiter = []() consteval { std::array result{}; for (uint8_t i : {'@', '/', '?'}) { result[i] = 1; @@ -11218,14 +12012,16 @@ ada_warn_unused std::string to_string(ada::state state) { #include #include +#include +#include #include +#include namespace ada { bool url::parse_opaque_host(std::string_view input) { ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]"); - if (std::any_of(input.begin(), input.end(), - ada::unicode::is_forbidden_host_code_point)) { + if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) { return is_valid = false; } @@ -11550,31 +12346,31 @@ ada_really_inline bool url::parse_scheme(const std::string_view input) { *http, https), in which case, we can go really fast. **/ if (is_input_special) { // fast path!!! - if (has_state_override) { + if constexpr (has_state_override) { // If url's scheme is not a special scheme and buffer is a special scheme, // then return. if (is_special() != is_input_special) { - return true; + return false; } // If url includes credentials or has a non-null port, and buffer is // "file", then return. if ((has_credentials() || port.has_value()) && parsed_type == ada::scheme::type::FILE) { - return true; + return false; } // If url's scheme is "file" and its host is an empty host, then return. // An empty host is the empty string. if (type == ada::scheme::type::FILE && host.has_value() && host.value().empty()) { - return true; + return false; } } type = parsed_type; - if (has_state_override) { + if constexpr (has_state_override) { // This is uncommon. uint16_t urls_scheme_port = get_special_port(); @@ -11594,7 +12390,7 @@ ada_really_inline bool url::parse_scheme(const std::string_view input) { // bool is_ascii = unicode::to_lower_ascii(_buffer.data(), _buffer.size()); - if (has_state_override) { + if constexpr (has_state_override) { // If url's scheme is a special scheme and buffer is not a special scheme, // then return. If url's scheme is not a special scheme and buffer is a // special scheme, then return. @@ -11618,7 +12414,7 @@ ada_really_inline bool url::parse_scheme(const std::string_view input) { set_scheme(std::move(_buffer)); - if (has_state_override) { + if constexpr (has_state_override) { // This is uncommon. uint16_t urls_scheme_port = get_special_port(); @@ -11727,18 +12523,14 @@ ada_really_inline void url::parse_path(std::string_view input) { path = "/"; } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) { helpers::parse_prepared_path(internal_input.substr(1), type, path); - return; } else { helpers::parse_prepared_path(internal_input, type, path); - return; } } else if (!internal_input.empty()) { if (internal_input[0] == '/') { helpers::parse_prepared_path(internal_input.substr(1), type, path); - return; } else { helpers::parse_prepared_path(internal_input, type, path); - return; } } else { if (!host.has_value()) { @@ -11783,6 +12575,7 @@ ada_really_inline void url::parse_path(std::string_view input) { if (has_search()) { answer.append(",\n"); answer.append("\t\"query\":\""); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) helpers::encode_json(query.value(), back); answer.append("\""); } @@ -11803,17 +12596,6 @@ ada_really_inline void url::parse_path(std::string_view input) { return checkers::verify_dns_length(host.value()); } -} // namespace ada -/* end file src/url.cpp */ -/* begin file src/url-getters.cpp */ -/** - * @file url-getters.cpp - * Includes all the getters of `ada::url` - */ - -#include - -namespace ada { [[nodiscard]] std::string url::get_origin() const noexcept { if (is_special()) { // Return a new opaque origin. @@ -11866,10 +12648,6 @@ namespace ada { return host.value_or(""); } -[[nodiscard]] std::string_view url::get_pathname() const noexcept { - return path; -} - [[nodiscard]] std::string url::get_search() const noexcept { // If this's URL's query is either null or the empty string, then return the // empty string. Return U+003F (?), followed by this's URL's query. @@ -11896,19 +12674,6 @@ namespace ada { : "#" + hash.value(); } -} // namespace ada -/* end file src/url-getters.cpp */ -/* begin file src/url-setters.cpp */ -/** - * @file url-setters.cpp - * Includes all the setters of `ada::url` - */ - -#include -#include - -namespace ada { - template bool url::set_host_or_hostname(const std::string_view input) { if (has_opaque_path) { @@ -11936,35 +12701,67 @@ bool url::set_host_or_hostname(const std::string_view input) { // Note: the 'found_colon' value is true if and only if a colon was // encountered while not inside brackets. if (found_colon) { - if (override_hostname) { + // If buffer is the empty string, host-missing validation error, return + // failure. + std::string_view buffer = host_view.substr(0, location); + if (buffer.empty()) { + return false; + } + + // If state override is given and state override is hostname state, then + // return failure. + if constexpr (override_hostname) { return false; } - std::string_view buffer = new_host.substr(location + 1); - if (!buffer.empty()) { - set_port(buffer); + + // Let host be the result of host parsing buffer with url is not special. + bool succeeded = parse_host(buffer); + if (!succeeded) { + host = std::move(previous_host); + update_base_port(previous_port); + return false; } - } - // If url is special and host_view is the empty string, validation error, - // return failure. Otherwise, if state override is given, host_view is the - // empty string, and either url includes credentials or url's port is - // non-null, return. - else if (host_view.empty() && - (is_special() || has_credentials() || port.has_value())) { - return false; - } - // Let host be the result of host parsing host_view with url is not special. - if (host_view.empty() && !is_special()) { - host = ""; + // Set url's host to host, buffer to the empty string, and state to port + // state. + std::string_view port_buffer = new_host.substr(location + 1); + if (!port_buffer.empty()) { + set_port(port_buffer); + } return true; } + // Otherwise, if one of the following is true: + // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#) + // - url is special and c is U+005C (\) + else { + // If url is special and host_view is the empty string, host-missing + // validation error, return failure. + if (host_view.empty() && is_special()) { + return false; + } - bool succeeded = parse_host(host_view); - if (!succeeded) { - host = previous_host; - update_base_port(previous_port); + // Otherwise, if state override is given, host_view is the empty string, + // and either url includes credentials or url's port is non-null, then + // return failure. + if (host_view.empty() && (has_credentials() || port.has_value())) { + return false; + } + + // Let host be the result of host parsing host_view with url is not + // special. + if (host_view.empty() && !is_special()) { + host = ""; + return true; + } + + bool succeeded = parse_host(host_view); + if (!succeeded) { + host = std::move(previous_host); + update_base_port(previous_port); + return false; + } + return true; } - return succeeded; } size_t location = new_host.find_first_of("/\\?"); @@ -11978,13 +12775,13 @@ bool url::set_host_or_hostname(const std::string_view input) { } else { // Let host be the result of host parsing buffer with url is not special. if (!parse_host(new_host)) { - host = previous_host; + host = std::move(previous_host); update_base_port(previous_port); return false; } // If host is "localhost", then set host to the empty string. - if (host.has_value() && host.value() == "localhost") { + if (host == "localhost") { host = ""; } } @@ -12021,28 +12818,37 @@ bool url::set_port(const std::string_view input) { if (cannot_have_credentials_or_port()) { return false; } + + if (input.empty()) { + port = std::nullopt; + return true; + } + std::string trimmed(input); helpers::remove_ascii_tab_or_newline(trimmed); + if (trimmed.empty()) { - port = std::nullopt; return true; } - // Input should not start with control characters. - if (ada::unicode::is_c0_control_or_space(trimmed.front())) { - return false; - } - // Input should contain at least one ascii digit. - if (input.find_first_of("0123456789") == std::string_view::npos) { + + // Input should not start with a non-digit character. + if (!ada::unicode::is_ascii_digit(trimmed.front())) { return false; } + // Find the first non-digit character to determine the length of digits + auto first_non_digit = + std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit); + std::string_view digits_to_parse = + std::string_view(trimmed.data(), first_non_digit - trimmed.begin()); + // Revert changes if parse_port fails. std::optional previous_port = port; - parse_port(trimmed); + parse_port(digits_to_parse); if (is_valid) { return true; } - port = previous_port; + port = std::move(previous_port); is_valid = true; return false; } @@ -12076,15 +12882,14 @@ void url::set_search(const std::string_view input) { is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE : ada::character_sets::QUERY_PERCENT_ENCODE; - query = ada::unicode::percent_encode(std::string_view(new_value), - query_percent_encode_set); + query = ada::unicode::percent_encode(new_value, query_percent_encode_set); } bool url::set_pathname(const std::string_view input) { if (has_opaque_path) { return false; } - path = ""; + path.clear(); parse_path(input); return true; } @@ -12104,7 +12909,7 @@ bool url::set_protocol(const std::string_view input) { view.append(":"); std::string::iterator pointer = - std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus); + std::ranges::find_if_not(view, unicode::is_alnum_plus); if (pointer != view.end() && *pointer == ':') { return parse_scheme( @@ -12117,26 +12922,18 @@ bool url::set_href(const std::string_view input) { ada::result out = ada::parse(input); if (out) { - username = out->username; - password = out->password; - host = out->host; - port = out->port; - path = out->path; - query = out->query; - hash = out->hash; - type = out->type; - non_special_scheme = out->non_special_scheme; - has_opaque_path = out->has_opaque_path; + *this = *out; } return out.has_value(); } } // namespace ada -/* end file src/url-setters.cpp */ +/* end file src/url.cpp */ /* begin file src/parser.cpp */ #include +#include namespace ada::parser { @@ -12149,10 +12946,9 @@ result_type parse_url_impl(std::string_view user_input, // means that doing if constexpr(result_type_is_ada_url) { something } else { // something else } is free (at runtime). This means that ada::url_aggregator // and ada::url **do not have to support the exact same API**. - constexpr bool result_type_is_ada_url = - std::is_same::value; + constexpr bool result_type_is_ada_url = std::is_same_v; constexpr bool result_type_is_ada_url_aggregator = - std::is_same::value; + std::is_same_v; static_assert(result_type_is_ada_url || result_type_is_ada_url_aggregator); // We don't support // anything else for now. @@ -12161,12 +12957,12 @@ result_type parse_url_impl(std::string_view user_input, " bytes],", (base_url != nullptr ? base_url->to_string() : "null"), ")"); - ada::state state = ada::state::SCHEME_START; + state state = state::SCHEME_START; result_type url{}; // We refuse to parse URL strings that exceed 4GB. Such strings are almost // surely the result of a bug or are otherwise a security concern. - if (user_input.size() > std::numeric_limits::max()) { + if (user_input.size() > std::numeric_limits::max()) [[unlikely]] { url.is_valid = false; } // Going forward, user_input.size() is in [0, @@ -12197,20 +12993,19 @@ result_type parse_url_impl(std::string_view user_input, url.reserve(reserve_capacity); } std::string tmp_buffer; - std::string_view internal_input; - if (unicode::has_tabs_or_newline(user_input)) { + std::string_view url_data; + if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] { tmp_buffer = user_input; // Optimization opportunity: Instead of copying and then pruning, we could // just directly build the string from user_input. helpers::remove_ascii_tab_or_newline(tmp_buffer); - internal_input = tmp_buffer; - } else { - internal_input = user_input; + url_data = tmp_buffer; + } else [[likely]] { + url_data = user_input; } // Leading and trailing control characters are uncommon and easy to deal with // (no performance concern). - std::string_view url_data = internal_input; helpers::trim_c0_whitespace(url_data); // Optimization opportunity. Most websites do not have fragment. @@ -12233,27 +13028,27 @@ result_type parse_url_impl(std::string_view user_input, ada_log("In parsing at ", input_position, " out of ", input_size, " in state ", ada::to_string(state)); switch (state) { - case ada::state::SCHEME_START: { + case state::SCHEME_START: { ada_log("SCHEME_START ", helpers::substring(url_data, input_position)); // If c is an ASCII alpha, append c, lowercased, to buffer, and set // state to scheme state. if ((input_position != input_size) && checkers::is_alpha(url_data[input_position])) { - state = ada::state::SCHEME; + state = state::SCHEME; input_position++; } else { // Otherwise, if state override is not given, set state to no scheme // state and decrease pointer by 1. - state = ada::state::NO_SCHEME; + state = state::NO_SCHEME; } break; } - case ada::state::SCHEME: { + case state::SCHEME: { ada_log("SCHEME ", helpers::substring(url_data, input_position)); // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.), // append c, lowercased, to buffer. while ((input_position != input_size) && - (ada::unicode::is_alnum_plus(url_data[input_position]))) { + (unicode::is_alnum_plus(url_data[input_position]))) { input_position++; } // Otherwise, if c is U+003A (:), then: @@ -12275,9 +13070,9 @@ result_type parse_url_impl(std::string_view user_input, ada_log("SCHEME the scheme is ", url.get_protocol()); // If url's scheme is "file", then: - if (url.type == ada::scheme::type::FILE) { + if (url.type == scheme::type::FILE) { // Set state to file state. - state = ada::state::FILE; + state = state::FILE; } // Otherwise, if url is special, base is non-null, and base's scheme // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url @@ -12285,38 +13080,38 @@ result_type parse_url_impl(std::string_view user_input, else if (url.is_special() && base_url != nullptr && base_url->type == url.type) { // Set state to special relative or authority state. - state = ada::state::SPECIAL_RELATIVE_OR_AUTHORITY; + state = state::SPECIAL_RELATIVE_OR_AUTHORITY; } // Otherwise, if url is special, set state to special authority // slashes state. else if (url.is_special()) { - state = ada::state::SPECIAL_AUTHORITY_SLASHES; + state = state::SPECIAL_AUTHORITY_SLASHES; } // Otherwise, if remaining starts with an U+002F (/), set state to // path or authority state and increase pointer by 1. else if (input_position + 1 < input_size && url_data[input_position + 1] == '/') { - state = ada::state::PATH_OR_AUTHORITY; + state = state::PATH_OR_AUTHORITY; input_position++; } // Otherwise, set url's path to the empty string and set state to // opaque path state. else { - state = ada::state::OPAQUE_PATH; + state = state::OPAQUE_PATH; } } // Otherwise, if state override is not given, set buffer to the empty // string, state to no scheme state, and start over (from the first code // point in input). else { - state = ada::state::NO_SCHEME; + state = state::NO_SCHEME; input_position = 0; break; } input_position++; break; } - case ada::state::NO_SCHEME: { + case state::NO_SCHEME: { ada_log("NO_SCHEME ", helpers::substring(url_data, input_position)); // If base is null, or base has an opaque path and c is not U+0023 (#), // validation error, return failure. @@ -12347,18 +13142,18 @@ result_type parse_url_impl(std::string_view user_input, } // Otherwise, if base's scheme is not "file", set state to relative // state and decrease pointer by 1. - else if (base_url->type != ada::scheme::type::FILE) { + else if (base_url->type != scheme::type::FILE) { ada_log("NO_SCHEME non-file relative path"); - state = ada::state::RELATIVE_SCHEME; + state = state::RELATIVE_SCHEME; } // Otherwise, set state to file state and decrease pointer by 1. else { ada_log("NO_SCHEME file base type"); - state = ada::state::FILE; + state = state::FILE; } break; } - case ada::state::AUTHORITY: { + case state::AUTHORITY: { ada_log("AUTHORITY ", helpers::substring(url_data, input_position)); // most URLs have no @. Having no @ tells us that we don't have to worry // about AUTHORITY. Of course, we could have @ and still not have to @@ -12368,11 +13163,10 @@ result_type parse_url_impl(std::string_view user_input, // TODO: We could do various processing early on, using a single pass // over the string to collect information about it, e.g., telling us // whether there is a @ and if so, where (or how many). - const bool contains_ampersand = - (url_data.find('@', input_position) != std::string_view::npos); - if (!contains_ampersand) { - state = ada::state::HOST; + // Check if url data contains an @. + if (url_data.find('@', input_position) == std::string_view::npos) { + state = state::HOST; break; } bool at_sign_seen{false}; @@ -12383,12 +13177,12 @@ result_type parse_url_impl(std::string_view user_input, * --------^ */ do { - std::string_view view = helpers::substring(url_data, input_position); + std::string_view view = url_data.substr(input_position); // The delimiters are @, /, ? \\. size_t location = url.is_special() ? helpers::find_authority_delimiter_special(view) : helpers::find_authority_delimiter(view); - std::string_view authority_view(view.data(), location); + std::string_view authority_view = view.substr(0, location); size_t end_of_authority = input_position + authority_view.size(); // If c is U+0040 (@), then: if ((end_of_authority != input_size) && @@ -12469,7 +13263,7 @@ result_type parse_url_impl(std::string_view user_input, url.is_valid = false; return url; } - state = ada::state::HOST; + state = state::HOST; break; } if (end_of_authority == input_size) { @@ -12485,42 +13279,41 @@ result_type parse_url_impl(std::string_view user_input, break; } - case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: { + case state::SPECIAL_RELATIVE_OR_AUTHORITY: { ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ", helpers::substring(url_data, input_position)); // If c is U+002F (/) and remaining starts with U+002F (/), // then set state to special authority ignore slashes state and increase // pointer by 1. - std::string_view view = helpers::substring(url_data, input_position); - if (ada::checkers::begins_with(view, "//")) { - state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES; + if (url_data.substr(input_position, 2) == "//") { + state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES; input_position += 2; } else { // Otherwise, validation error, set state to relative state and // decrease pointer by 1. - state = ada::state::RELATIVE_SCHEME; + state = state::RELATIVE_SCHEME; } break; } - case ada::state::PATH_OR_AUTHORITY: { + case state::PATH_OR_AUTHORITY: { ada_log("PATH_OR_AUTHORITY ", helpers::substring(url_data, input_position)); // If c is U+002F (/), then set state to authority state. if ((input_position != input_size) && (url_data[input_position] == '/')) { - state = ada::state::AUTHORITY; + state = state::AUTHORITY; input_position++; } else { // Otherwise, set state to path state, and decrease pointer by 1. - state = ada::state::PATH; + state = state::PATH; } break; } - case ada::state::RELATIVE_SCHEME: { + case state::RELATIVE_SCHEME: { ada_log("RELATIVE_SCHEME ", helpers::substring(url_data, input_position)); @@ -12529,11 +13322,12 @@ result_type parse_url_impl(std::string_view user_input, // If c is U+002F (/), then set state to relative slash state. if ((input_position != input_size) && + // NOLINTNEXTLINE(bugprone-branch-clone) (url_data[input_position] == '/')) { ada_log( "RELATIVE_SCHEME if c is U+002F (/), then set state to relative " "slash state"); - state = ada::state::RELATIVE_SLASH; + state = state::RELATIVE_SLASH; } else if (url.is_special() && (input_position != input_size) && (url_data[input_position] == '\\')) { // Otherwise, if url is special and c is U+005C (\), validation error, @@ -12541,7 +13335,7 @@ result_type parse_url_impl(std::string_view user_input, ada_log( "RELATIVE_SCHEME if url is special and c is U+005C, validation " "error, set state to relative slash state"); - state = ada::state::RELATIVE_SLASH; + state = state::RELATIVE_SLASH; } else { ada_log("RELATIVE_SCHEME otherwise"); // Set url's username to base's username, url's password to base's @@ -12560,9 +13354,7 @@ result_type parse_url_impl(std::string_view user_input, } else { url.update_base_authority(base_url->get_href(), base_url->get_components()); - // TODO: Get rid of set_hostname and replace it with - // update_base_hostname - url.set_hostname(base_url->get_hostname()); + url.update_host_to_base_host(base_url->get_hostname()); url.update_base_port(base_url->retrieve_base_port()); // cloning the base path includes cloning the has_opaque_path flag url.has_opaque_path = base_url->has_opaque_path; @@ -12576,7 +13368,7 @@ result_type parse_url_impl(std::string_view user_input, // state to query state. if ((input_position != input_size) && (url_data[input_position] == '?')) { - state = ada::state::QUERY; + state = state::QUERY; } // Otherwise, if c is not the EOF code point: else if (input_position != input_size) { @@ -12588,18 +13380,18 @@ result_type parse_url_impl(std::string_view user_input, } else { std::string_view path = url.get_pathname(); if (helpers::shorten_path(path, url.type)) { - url.update_base_pathname(std::string(path)); + url.update_base_pathname(std::move(std::string(path))); } } // Set state to path state and decrease pointer by 1. - state = ada::state::PATH; + state = state::PATH; break; } } input_position++; break; } - case ada::state::RELATIVE_SLASH: { + case state::RELATIVE_SLASH: { ada_log("RELATIVE_SLASH ", helpers::substring(url_data, input_position)); @@ -12608,12 +13400,12 @@ result_type parse_url_impl(std::string_view user_input, (url_data[input_position] == '/' || url_data[input_position] == '\\')) { // Set state to special authority ignore slashes state. - state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES; + state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES; } // Otherwise, if c is U+002F (/), then set state to authority state. else if ((input_position != input_size) && (url_data[input_position] == '/')) { - state = ada::state::AUTHORITY; + state = state::AUTHORITY; } // Otherwise, set // - url's username to base's username, @@ -12630,33 +13422,30 @@ result_type parse_url_impl(std::string_view user_input, } else { url.update_base_authority(base_url->get_href(), base_url->get_components()); - // TODO: Get rid of set_hostname and replace it with - // update_base_hostname - url.set_hostname(base_url->get_hostname()); + url.update_host_to_base_host(base_url->get_hostname()); url.update_base_port(base_url->retrieve_base_port()); } - state = ada::state::PATH; + state = state::PATH; break; } input_position++; break; } - case ada::state::SPECIAL_AUTHORITY_SLASHES: { + case state::SPECIAL_AUTHORITY_SLASHES: { ada_log("SPECIAL_AUTHORITY_SLASHES ", helpers::substring(url_data, input_position)); // If c is U+002F (/) and remaining starts with U+002F (/), // then set state to special authority ignore slashes state and increase // pointer by 1. - std::string_view view = helpers::substring(url_data, input_position); - if (ada::checkers::begins_with(view, "//")) { + if (url_data.substr(input_position, 2) == "//") { input_position += 2; } [[fallthrough]]; } - case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: { + case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: { ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ", helpers::substring(url_data, input_position)); @@ -12667,23 +13456,22 @@ result_type parse_url_impl(std::string_view user_input, (url_data[input_position] == '\\'))) { input_position++; } - state = ada::state::AUTHORITY; + state = state::AUTHORITY; break; } - case ada::state::QUERY: { + case state::QUERY: { ada_log("QUERY ", helpers::substring(url_data, input_position)); if constexpr (store_values) { // Let queryPercentEncodeSet be the special-query percent-encode set // if url is special; otherwise the query percent-encode set. const uint8_t* query_percent_encode_set = - url.is_special() - ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE - : ada::character_sets::QUERY_PERCENT_ENCODE; + url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE + : character_sets::QUERY_PERCENT_ENCODE; // Percent-encode after encoding, with encoding, buffer, and // queryPercentEncodeSet, and append the result to url's query. - url.update_base_search(helpers::substring(url_data, input_position), + url.update_base_search(url_data.substr(input_position), query_percent_encode_set); ada_log("QUERY update_base_search completed "); if (fragment.has_value()) { @@ -12692,11 +13480,10 @@ result_type parse_url_impl(std::string_view user_input, } return url; } - case ada::state::HOST: { + case state::HOST: { ada_log("HOST ", helpers::substring(url_data, input_position)); - std::string_view host_view = - helpers::substring(url_data, input_position); + std::string_view host_view = url_data.substr(input_position); auto [location, found_colon] = helpers::get_host_delimiter_location(url.is_special(), host_view); input_position = (location != std::string_view::npos) @@ -12716,7 +13503,7 @@ result_type parse_url_impl(std::string_view user_input, ada_log("HOST parsing results in ", url.get_hostname()); // Set url's host to host, buffer to the empty string, and state to // port state. - state = ada::state::PORT; + state = state::PORT; input_position++; } // Otherwise, if one of the following is true: @@ -12727,7 +13514,7 @@ result_type parse_url_impl(std::string_view user_input, else { // If url is special and host_view is the empty string, validation // error, return failure. - if (url.is_special() && host_view.empty()) { + if (host_view.empty() && url.is_special()) { url.is_valid = false; return url; } @@ -12743,50 +13530,56 @@ result_type parse_url_impl(std::string_view user_input, " href=", url.get_href()); // Set url's host to host, and state to path start state. - state = ada::state::PATH_START; + state = state::PATH_START; } break; } - case ada::state::OPAQUE_PATH: { + case state::OPAQUE_PATH: { ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position)); - std::string_view view = helpers::substring(url_data, input_position); + std::string_view view = url_data.substr(input_position); // If c is U+003F (?), then set url's query to the empty string and // state to query state. size_t location = view.find('?'); if (location != std::string_view::npos) { view.remove_suffix(view.size() - location); - state = ada::state::QUERY; + state = state::QUERY; input_position += location + 1; } else { input_position = input_size + 1; } url.has_opaque_path = true; + // This is a really unlikely scenario in real world. We should not seek // to optimize it. - url.update_base_pathname(unicode::percent_encode( - view, character_sets::C0_CONTROL_PERCENT_ENCODE)); + if (view.ends_with(' ')) { + std::string modified_view = + std::string(view.substr(0, view.size() - 1)) + "%20"; + url.update_base_pathname(unicode::percent_encode( + modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE)); + } else { + url.update_base_pathname(unicode::percent_encode( + view, character_sets::C0_CONTROL_PERCENT_ENCODE)); + } break; } - case ada::state::PORT: { + case state::PORT: { ada_log("PORT ", helpers::substring(url_data, input_position)); - std::string_view port_view = - helpers::substring(url_data, input_position); - size_t consumed_bytes = url.parse_port(port_view, true); - input_position += consumed_bytes; + std::string_view port_view = url_data.substr(input_position); + input_position += url.parse_port(port_view, true); if (!url.is_valid) { return url; } state = state::PATH_START; [[fallthrough]]; } - case ada::state::PATH_START: { + case state::PATH_START: { ada_log("PATH_START ", helpers::substring(url_data, input_position)); // If url is special, then: if (url.is_special()) { // Set state to path state. - state = ada::state::PATH; + state = state::PATH; // Optimization: Avoiding going into PATH state improves the // performance of urls ending with /. @@ -12811,12 +13604,12 @@ result_type parse_url_impl(std::string_view user_input, // set url's query to the empty string and state to query state. else if ((input_position != input_size) && (url_data[input_position] == '?')) { - state = ada::state::QUERY; + state = state::QUERY; } // Otherwise, if c is not the EOF code point: else if (input_position != input_size) { // Set state to path state. - state = ada::state::PATH; + state = state::PATH; // If c is not U+002F (/), then decrease pointer by 1. if (url_data[input_position] != '/') { @@ -12827,15 +13620,15 @@ result_type parse_url_impl(std::string_view user_input, input_position++; break; } - case ada::state::PATH: { - std::string_view view = helpers::substring(url_data, input_position); + case state::PATH: { ada_log("PATH ", helpers::substring(url_data, input_position)); + std::string_view view = url_data.substr(input_position); // Most time, we do not need percent encoding. // Furthermore, we can immediately locate the '?'. size_t locofquestionmark = view.find('?'); if (locofquestionmark != std::string_view::npos) { - state = ada::state::QUERY; + state = state::QUERY; view.remove_suffix(view.size() - locofquestionmark); input_position += locofquestionmark + 1; } else { @@ -12851,7 +13644,7 @@ result_type parse_url_impl(std::string_view user_input, } break; } - case ada::state::FILE_SLASH: { + case state::FILE_SLASH: { ada_log("FILE_SLASH ", helpers::substring(url_data, input_position)); // If c is U+002F (/) or U+005C (\), then: @@ -12860,21 +13653,19 @@ result_type parse_url_impl(std::string_view user_input, url_data[input_position] == '\\')) { ada_log("FILE_SLASH c is U+002F or U+005C"); // Set state to file host state. - state = ada::state::FILE_HOST; + state = state::FILE_HOST; input_position++; } else { ada_log("FILE_SLASH otherwise"); // If base is non-null and base's scheme is "file", then: // Note: it is unsafe to do base_url->scheme unless you know that // base_url_has_value() is true. - if (base_url != nullptr && - base_url->type == ada::scheme::type::FILE) { + if (base_url != nullptr && base_url->type == scheme::type::FILE) { // Set url's host to base's host. if constexpr (result_type_is_ada_url) { url.host = base_url->host; } else { - // TODO: Optimization opportunity. - url.set_host(base_url->get_host()); + url.update_host_to_base_host(base_url->get_host()); } // If the code point substring from pointer to the end of input does // not start with a Windows drive letter and base's path[0] is a @@ -12882,7 +13673,7 @@ result_type parse_url_impl(std::string_view user_input, // url's path. if (!base_url->get_pathname().empty()) { if (!checkers::is_windows_drive_letter( - helpers::substring(url_data, input_position))) { + url_data.substr(input_position))) { std::string_view first_base_url_path = base_url->get_pathname().substr(1); size_t loc = first_base_url_path.find('/'); @@ -12904,14 +13695,14 @@ result_type parse_url_impl(std::string_view user_input, } // Set state to path state, and decrease pointer by 1. - state = ada::state::PATH; + state = state::PATH; } break; } - case ada::state::FILE_HOST: { - std::string_view view = helpers::substring(url_data, input_position); + case state::FILE_HOST: { ada_log("FILE_HOST ", helpers::substring(url_data, input_position)); + std::string_view view = url_data.substr(input_position); size_t location = view.find_first_of("/\\?"); std::string_view file_host_buffer( @@ -12919,7 +13710,7 @@ result_type parse_url_impl(std::string_view user_input, (location != std::string_view::npos) ? location : view.size()); if (checkers::is_windows_drive_letter(file_host_buffer)) { - state = ada::state::PATH; + state = state::PATH; } else if (file_host_buffer.empty()) { // Set url's host to the empty string. if constexpr (result_type_is_ada_url) { @@ -12928,7 +13719,7 @@ result_type parse_url_impl(std::string_view user_input, url.update_base_hostname(""); } // Set state to path start state. - state = ada::state::PATH_START; + state = state::PATH_START; } else { size_t consumed_bytes = file_host_buffer.size(); input_position += consumed_bytes; @@ -12950,15 +13741,14 @@ result_type parse_url_impl(std::string_view user_input, } // Set buffer to the empty string and state to path start state. - state = ada::state::PATH_START; + state = state::PATH_START; } break; } - case ada::state::FILE: { + case state::FILE: { ada_log("FILE ", helpers::substring(url_data, input_position)); - std::string_view file_view = - helpers::substring(url_data, input_position); + std::string_view file_view = url_data.substr(input_position); url.set_protocol_as_file(); if constexpr (result_type_is_ada_url) { @@ -12973,11 +13763,10 @@ result_type parse_url_impl(std::string_view user_input, url_data[input_position] == '\\')) { ada_log("FILE c is U+002F or U+005C"); // Set state to file slash state. - state = ada::state::FILE_SLASH; + state = state::FILE_SLASH; } // Otherwise, if base is non-null and base's scheme is "file": - else if (base_url != nullptr && - base_url->type == ada::scheme::type::FILE) { + else if (base_url != nullptr && base_url->type == scheme::type::FILE) { // Set url's host to base's host, url's path to a clone of base's // path, and url's query to base's query. ada_log("FILE base non-null"); @@ -12986,9 +13775,7 @@ result_type parse_url_impl(std::string_view user_input, url.path = base_url->path; url.query = base_url->query; } else { - // TODO: Get rid of set_hostname and replace it with - // update_base_hostname - url.set_hostname(base_url->get_hostname()); + url.update_host_to_base_host(base_url->get_hostname()); url.update_base_pathname(base_url->get_pathname()); url.update_base_search(base_url->get_search()); } @@ -12997,7 +13784,7 @@ result_type parse_url_impl(std::string_view user_input, // If c is U+003F (?), then set url's query to the empty string and // state to query state. if (input_position != input_size && url_data[input_position] == '?') { - state = ada::state::QUERY; + state = state::QUERY; } // Otherwise, if c is not the EOF code point: else if (input_position != input_size) { @@ -13011,7 +13798,7 @@ result_type parse_url_impl(std::string_view user_input, } else { std::string_view path = url.get_pathname(); if (helpers::shorten_path(path, url.type)) { - url.update_base_pathname(std::string(path)); + url.update_base_pathname(std::move(std::string(path))); } } } @@ -13023,14 +13810,14 @@ result_type parse_url_impl(std::string_view user_input, } // Set state to path state and decrease pointer by 1. - state = ada::state::PATH; + state = state::PATH; break; } } // Otherwise, set state to path state, and decrease pointer by 1. else { ada_log("FILE go to path"); - state = ada::state::PATH; + state = state::PATH; break; } @@ -13038,7 +13825,7 @@ result_type parse_url_impl(std::string_view user_input, break; } default: - ada::unreachable(); + unreachable(); } } if constexpr (store_values) { @@ -13068,86 +13855,11 @@ template url_aggregator parse_url( /* end file src/parser.cpp */ /* begin file src/url_components.cpp */ -#include +#include #include namespace ada { -[[nodiscard]] bool url_components::check_offset_consistency() const noexcept { - /** - * https://user:pass@example.com:1234/foo/bar?baz#quux - * | | | | ^^^^| | | - * | | | | | | | `----- hash_start - * | | | | | | `--------- search_start - * | | | | | `----------------- pathname_start - * | | | | `--------------------- port - * | | | `----------------------- host_end - * | | `---------------------------------- host_start - * | `--------------------------------------- username_end - * `--------------------------------------------- protocol_end - */ - // These conditions can be made more strict. - uint32_t index = 0; - - if (protocol_end == url_components::omitted) { - return false; - } - if (protocol_end < index) { - return false; - } - index = protocol_end; - - if (username_end == url_components::omitted) { - return false; - } - if (username_end < index) { - return false; - } - index = username_end; - - if (host_start == url_components::omitted) { - return false; - } - if (host_start < index) { - return false; - } - index = host_start; - - if (port != url_components::omitted) { - if (port > 0xffff) { - return false; - } - uint32_t port_length = helpers::fast_digit_count(port) + 1; - if (index + port_length < index) { - return false; - } - index += port_length; - } - - if (pathname_start == url_components::omitted) { - return false; - } - if (pathname_start < index) { - return false; - } - index = pathname_start; - - if (search_start != url_components::omitted) { - if (search_start < index) { - return false; - } - index = search_start; - } - - if (hash_start != url_components::omitted) { - if (hash_start < index) { - return false; - } - } - - return true; -} - [[nodiscard]] std::string url_components::to_string() const { std::string answer; auto back = std::back_insert_iterator(answer); @@ -13193,6 +13905,8 @@ namespace ada { /* end file src/url_components.cpp */ /* begin file src/url_aggregator.cpp */ +#include +#include #include #include @@ -13206,38 +13920,38 @@ template std::string_view input{input_with_colon}; input.remove_suffix(1); auto parsed_type = ada::scheme::get_scheme_type(input); - bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL); + const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL); /** * In the common case, we will immediately recognize a special scheme (e.g., *http, https), in which case, we can go really fast. **/ if (is_input_special) { // fast path!!! - if (has_state_override) { + if constexpr (has_state_override) { // If url's scheme is not a special scheme and buffer is a special scheme, // then return. if (is_special() != is_input_special) { - return true; + return false; } // If url includes credentials or has a non-null port, and buffer is // "file", then return. if ((has_credentials() || components.port != url_components::omitted) && parsed_type == ada::scheme::type::FILE) { - return true; + return false; } // If url's scheme is "file" and its host is an empty host, then return. // An empty host is the empty string. if (type == ada::scheme::type::FILE && components.host_start == components.host_end) { - return true; + return false; } } type = parsed_type; set_scheme_from_view_with_colon(input_with_colon); - if (has_state_override) { + if constexpr (has_state_override) { // This is uncommon. uint16_t urls_scheme_port = get_special_port(); @@ -13254,7 +13968,7 @@ template // need to check the return value. unicode::to_lower_ascii(_buffer.data(), _buffer.size()); - if (has_state_override) { + if constexpr (has_state_override) { // If url's scheme is a special scheme and buffer is not a special scheme, // then return. If url's scheme is not a special scheme and buffer is a // special scheme, then return. @@ -13279,7 +13993,7 @@ template set_scheme(_buffer); - if (has_state_override) { + if constexpr (has_state_override) { // This is uncommon. uint16_t urls_scheme_port = get_special_port(); @@ -13408,11 +14122,11 @@ bool url_aggregator::set_protocol(const std::string_view input) { view.append(":"); std::string::iterator pointer = - std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus); + std::ranges::find_if_not(view, unicode::is_alnum_plus); if (pointer != view.end() && *pointer == ':') { return parse_scheme_with_colon( - std::string_view(view.data(), pointer - view.begin() + 1)); + view.substr(0, pointer - view.begin() + 1)); } return false; } @@ -13464,24 +14178,33 @@ bool url_aggregator::set_port(const std::string_view input) { if (cannot_have_credentials_or_port()) { return false; } + + if (input.empty()) { + clear_port(); + return true; + } + std::string trimmed(input); helpers::remove_ascii_tab_or_newline(trimmed); + if (trimmed.empty()) { - clear_port(); return true; } - // Input should not start with control characters. - if (ada::unicode::is_c0_control_or_space(trimmed.front())) { - return false; - } - // Input should contain at least one ascii digit. - if (input.find_first_of("0123456789") == std::string_view::npos) { + + // Input should not start with a non-digit character. + if (!ada::unicode::is_ascii_digit(trimmed.front())) { return false; } + // Find the first non-digit character to determine the length of digits + auto first_non_digit = + std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit); + std::string_view digits_to_parse = + std::string_view(trimmed.data(), first_non_digit - trimmed.begin()); + // Revert changes if parse_port fails. uint32_t previous_port = components.port; - parse_port(trimmed); + parse_port(digits_to_parse); if (is_valid) { return true; } @@ -13500,8 +14223,7 @@ bool url_aggregator::set_pathname(const std::string_view input) { } clear_pathname(); parse_path(input); - if (checkers::begins_with(get_pathname(), "//") && !has_authority() && - !has_dash_dot()) { + if (get_pathname().starts_with("//") && !has_authority() && !has_dash_dot()) { buffer.insert(components.pathname_start, "/."); components.pathname_start += 2; } @@ -13678,8 +14400,8 @@ ada_really_inline bool url_aggregator::parse_host(std::string_view input) { ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(), " bytes]"); - if (std::any_of(host.value().begin(), host.value().end(), - ada::unicode::is_forbidden_domain_code_point)) { + if (std::ranges::any_of(host.value(), + ada::unicode::is_forbidden_domain_code_point)) { return is_valid = false; } @@ -13725,43 +14447,75 @@ bool url_aggregator::set_host_or_hostname(const std::string_view input) { // Note: the 'found_colon' value is true if and only if a colon was // encountered while not inside brackets. if (found_colon) { - if (override_hostname) { + // If buffer is the empty string, host-missing validation error, return + // failure. + std::string_view host_buffer = host_view.substr(0, location); + if (host_buffer.empty()) { return false; } - std::string_view sub_buffer = new_host.substr(location + 1); - if (!sub_buffer.empty()) { - set_port(sub_buffer); + + // If state override is given and state override is hostname state, then + // return failure. + if constexpr (override_hostname) { + return false; } + + // Let host be the result of host parsing buffer with url is not special. + bool succeeded = parse_host(host_buffer); + if (!succeeded) { + update_base_hostname(previous_host); + update_base_port(previous_port); + return false; + } + + // Set url's host to host, buffer to the empty string, and state to port + // state. + std::string_view port_buffer = new_host.substr(location + 1); + if (!port_buffer.empty()) { + set_port(port_buffer); + } + return true; } - // If url is special and host_view is the empty string, validation error, - // return failure. Otherwise, if state override is given, host_view is the - // empty string, and either url includes credentials or url's port is - // non-null, return. - else if (host_view.empty() && - (is_special() || has_credentials() || has_port())) { - return false; - } + // Otherwise, if one of the following is true: + // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#) + // - url is special and c is U+005C (\) + else { + // If url is special and host_view is the empty string, host-missing + // validation error, return failure. + if (host_view.empty() && is_special()) { + return false; + } + + // Otherwise, if state override is given, host_view is the empty string, + // and either url includes credentials or url's port is non-null, then + // return failure. + if (host_view.empty() && (has_credentials() || has_port())) { + return false; + } + + // Let host be the result of host parsing host_view with url is not + // special. + if (host_view.empty() && !is_special()) { + if (has_hostname()) { + clear_hostname(); // easy! + } else if (has_dash_dot()) { + add_authority_slashes_if_needed(); + delete_dash_dot(); + } + return true; + } - // Let host be the result of host parsing host_view with url is not special. - if (host_view.empty() && !is_special()) { - if (has_hostname()) { - clear_hostname(); // easy! + bool succeeded = parse_host(host_view); + if (!succeeded) { + update_base_hostname(previous_host); + update_base_port(previous_port); + return false; } else if (has_dash_dot()) { - add_authority_slashes_if_needed(); + // Should remove dash_dot from pathname delete_dash_dot(); } return true; } - - bool succeeded = parse_host(host_view); - if (!succeeded) { - update_base_hostname(previous_host); - update_base_port(previous_port); - } else if (has_dash_dot()) { - // Should remove dash_dot from pathname - delete_dash_dot(); - } - return succeeded; } size_t location = new_host.find_first_of("/\\?"); @@ -13831,7 +14585,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return "null"; } -[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_username"); if (has_non_empty_username()) { return helpers::substring(buffer, components.protocol_end + 2, @@ -13840,7 +14595,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return ""; } -[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_password"); if (has_non_empty_password()) { return helpers::substring(buffer, components.username_end + 1, @@ -13849,7 +14605,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return ""; } -[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_port"); if (components.port == url_components::omitted) { return ""; @@ -13858,7 +14615,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { components.pathname_start); } -[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_hash"); // If this's URL's fragment is either null or the empty string, then return // the empty string. Return U+0023 (#), followed by this's URL's fragment. @@ -13871,7 +14629,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, components.hash_start); } -[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_host"); // Technically, we should check if there is a hostname, but // the code below works even if there isn't. @@ -13889,7 +14648,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, start, components.pathname_start); } -[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_hostname"); // Technically, we should check if there is a hostname, but // the code below works even if there isn't. @@ -13903,21 +14663,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, start, components.host_end); } -[[nodiscard]] std::string_view url_aggregator::get_pathname() const noexcept { - ada_log("url_aggregator::get_pathname pathname_start = ", - components.pathname_start, " buffer.size() = ", buffer.size(), - " components.search_start = ", components.search_start, - " components.hash_start = ", components.hash_start); - auto ending_index = uint32_t(buffer.size()); - if (components.search_start != url_components::omitted) { - ending_index = components.search_start; - } else if (components.hash_start != url_components::omitted) { - ending_index = components.hash_start; - } - return helpers::substring(buffer, components.pathname_start, ending_index); -} - -[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_search"); // If this's URL's query is either null or the empty string, then return the // empty string. Return U+003F (?), followed by this's URL's query. @@ -13934,7 +14681,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return helpers::substring(buffer, components.search_start, ending_index); } -[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept { +[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept + ada_lifetime_bound { ada_log("url_aggregator::get_protocol"); return helpers::substring(buffer, 0, components.protocol_end); } @@ -14377,8 +15125,7 @@ bool url_aggregator::parse_opaque_host(std::string_view input) { ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]"); ADA_ASSERT_TRUE(validate()); ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); - if (std::any_of(input.begin(), input.end(), - ada::unicode::is_forbidden_host_code_point)) { + if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) { return is_valid = false; } @@ -14554,176 +15301,6 @@ bool url_aggregator::parse_opaque_host(std::string_view input) { return answer; } -[[nodiscard]] bool url_aggregator::validate() const noexcept { - if (!is_valid) { - return true; - } - if (!components.check_offset_consistency()) { - ada_log("url_aggregator::validate inconsistent components \n", - to_diagram()); - return false; - } - // We have a credible components struct, but let us investivate more - // carefully: - /** - * https://user:pass@example.com:1234/foo/bar?baz#quux - * | | | | ^^^^| | | - * | | | | | | | `----- hash_start - * | | | | | | `--------- search_start - * | | | | | `----------------- pathname_start - * | | | | `--------------------- port - * | | | `----------------------- host_end - * | | `---------------------------------- host_start - * | `--------------------------------------- username_end - * `--------------------------------------------- protocol_end - */ - if (components.protocol_end == url_components::omitted) { - ada_log("url_aggregator::validate omitted protocol_end \n", to_diagram()); - return false; - } - if (components.username_end == url_components::omitted) { - ada_log("url_aggregator::validate omitted username_end \n", to_diagram()); - return false; - } - if (components.host_start == url_components::omitted) { - ada_log("url_aggregator::validate omitted host_start \n", to_diagram()); - return false; - } - if (components.host_end == url_components::omitted) { - ada_log("url_aggregator::validate omitted host_end \n", to_diagram()); - return false; - } - if (components.pathname_start == url_components::omitted) { - ada_log("url_aggregator::validate omitted pathname_start \n", to_diagram()); - return false; - } - - if (components.protocol_end > buffer.size()) { - ada_log("url_aggregator::validate protocol_end overflow \n", to_diagram()); - return false; - } - if (components.username_end > buffer.size()) { - ada_log("url_aggregator::validate username_end overflow \n", to_diagram()); - return false; - } - if (components.host_start > buffer.size()) { - ada_log("url_aggregator::validate host_start overflow \n", to_diagram()); - return false; - } - if (components.host_end > buffer.size()) { - ada_log("url_aggregator::validate host_end overflow \n", to_diagram()); - return false; - } - if (components.pathname_start > buffer.size()) { - ada_log("url_aggregator::validate pathname_start overflow \n", - to_diagram()); - return false; - } - - if (components.protocol_end > 0) { - if (buffer[components.protocol_end - 1] != ':') { - ada_log( - "url_aggregator::validate missing : at the end of the protocol \n", - to_diagram()); - return false; - } - } - - if (components.username_end != buffer.size() && - components.username_end > components.protocol_end + 2) { - if (buffer[components.username_end] != ':' && - buffer[components.username_end] != '@') { - ada_log( - "url_aggregator::validate missing : or @ at the end of the username " - "\n", - to_diagram()); - return false; - } - } - - if (components.host_start != buffer.size()) { - if (components.host_start > components.username_end) { - if (buffer[components.host_start] != '@') { - ada_log( - "url_aggregator::validate missing @ at the end of the password \n", - to_diagram()); - return false; - } - } else if (components.host_start == components.username_end && - components.host_end > components.host_start) { - if (components.host_start == components.protocol_end + 2) { - if (buffer[components.protocol_end] != '/' || - buffer[components.protocol_end + 1] != '/') { - ada_log( - "url_aggregator::validate missing // between protocol and host " - "\n", - to_diagram()); - return false; - } - } else { - if (components.host_start > components.protocol_end && - buffer[components.host_start] != '@') { - ada_log( - "url_aggregator::validate missing @ at the end of the username " - "\n", - to_diagram()); - return false; - } - } - } else { - if (components.host_end != components.host_start) { - ada_log("url_aggregator::validate expected omitted host \n", - to_diagram()); - return false; - } - } - } - if (components.host_end != buffer.size() && - components.pathname_start > components.host_end) { - if (components.pathname_start == components.host_end + 2 && - buffer[components.host_end] == '/' && - buffer[components.host_end + 1] == '.') { - if (components.pathname_start + 1 >= buffer.size() || - buffer[components.pathname_start] != '/' || - buffer[components.pathname_start + 1] != '/') { - ada_log( - "url_aggregator::validate expected the path to begin with // \n", - to_diagram()); - return false; - } - } else if (buffer[components.host_end] != ':') { - ada_log("url_aggregator::validate missing : at the port \n", - to_diagram()); - return false; - } - } - if (components.pathname_start != buffer.size() && - components.pathname_start < components.search_start && - components.pathname_start < components.hash_start && !has_opaque_path) { - if (buffer[components.pathname_start] != '/') { - ada_log("url_aggregator::validate missing / at the path \n", - to_diagram()); - return false; - } - } - if (components.search_start != url_components::omitted) { - if (buffer[components.search_start] != '?') { - ada_log("url_aggregator::validate missing ? at the search \n", - to_diagram()); - return false; - } - } - if (components.hash_start != url_components::omitted) { - if (buffer[components.hash_start] != '#') { - ada_log("url_aggregator::validate missing # at the hash \n", - to_diagram()); - return false; - } - } - - return true; -} - void url_aggregator::delete_dash_dot() { ada_log("url_aggregator::delete_dash_dot"); ADA_ASSERT_TRUE(validate()); @@ -14777,15 +15354,20 @@ inline void url_aggregator::consume_prepared_path(std::string_view input) { // Note: input cannot be empty, it must at least contain one character ('.') // Note: we know that '\' is not present. if (input[0] != '.') { - size_t slashdot = input.find("/."); - if (slashdot == std::string_view::npos) { // common case - trivial_path = true; - } else { // uncommon - // only three cases matter: /./, /.. or a final / - trivial_path = - !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' || - input[slashdot + 2] == '/'); + size_t slashdot = 0; + bool dot_is_file = true; + for (;;) { + slashdot = input.find("/.", slashdot); + if (slashdot == std::string_view::npos) { // common case + break; + } else { // uncommon + // only three cases matter: /./, /.. or a final / + slashdot += 2; + dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' || + input[slashdot] == '/'); + } } + trivial_path = dot_is_file; } } if (trivial_path && is_at_path()) { @@ -14879,8 +15461,8 @@ inline void url_aggregator::consume_prepared_path(std::string_view input) { ? path_buffer_tmp : path_view; if (unicode::is_double_dot_path_segment(path_buffer)) { - if ((helpers::shorten_path(path, type) || special) && - location == std::string_view::npos) { + helpers::shorten_path(path, type); + if (location == std::string_view::npos) { path += '/'; } } else if (unicode::is_single_dot_path_segment(path_buffer) && @@ -14914,6 +15496,1470 @@ inline void url_aggregator::consume_prepared_path(std::string_view input) { } } // namespace ada /* end file src/url_aggregator.cpp */ + +#if ADA_INCLUDE_URL_PATTERN +/* begin file src/url_pattern.cpp */ +#if ADA_INCLUDE_URL_PATTERN + + +#include +#include +#include + +namespace ada { + +tl::expected url_pattern_init::process( + const url_pattern_init& init, url_pattern_init::process_type type, + std::optional protocol, + std::optional username, + std::optional password, + std::optional hostname, + std::optional port, + std::optional pathname, + std::optional search, + std::optional hash) { + // Let result be the result of creating a new URLPatternInit. + auto result = url_pattern_init{}; + + // If protocol is not null, set result["protocol"] to protocol. + if (protocol.has_value()) result.protocol = *protocol; + + // If username is not null, set result["username"] to username. + if (username.has_value()) result.username = *username; + + // If password is not null, set result["password"] to password. + if (password.has_value()) result.password = *password; + + // If hostname is not null, set result["hostname"] to hostname. + if (hostname.has_value()) result.hostname = *hostname; + + // If port is not null, set result["port"] to port. + if (port.has_value()) result.port = *port; + + // If pathname is not null, set result["pathname"] to pathname. + if (pathname.has_value()) result.pathname = *pathname; + + // If search is not null, set result["search"] to search. + if (search.has_value()) result.search = *search; + + // If hash is not null, set result["hash"] to hash. + if (hash.has_value()) result.hash = *hash; + + // Let baseURL be null. + std::optional base_url{}; + + // If init["baseURL"] exists: + if (init.base_url.has_value()) { + // Set baseURL to the result of parsing init["baseURL"]. + auto parsing_result = ada::parse(*init.base_url); + // If baseURL is failure, then throw a TypeError. + if (!parsing_result) { + return tl::unexpected(errors::type_error); + } + base_url = std::move(*parsing_result); + + // If init["protocol"] does not exist, then set result["protocol"] to the + // result of processing a base URL string given baseURL's scheme and type. + if (!init.protocol.has_value()) { + ADA_ASSERT_TRUE(base_url.has_value()); + std::string_view base_url_protocol = base_url->get_protocol(); + if (base_url_protocol.ends_with(":")) base_url_protocol.remove_suffix(1); + result.protocol = + url_pattern_helpers::process_base_url_string(base_url_protocol, type); + } + + // If type is not "pattern" and init contains none of "protocol", + // "hostname", "port" and "username", then set result["username"] to the + // result of processing a base URL string given baseURL's username and type. + if (type != process_type::pattern && !init.protocol && !init.hostname && + !init.port && !init.username) { + result.username = url_pattern_helpers::process_base_url_string( + base_url->get_username(), type); + } + + // TODO: Optimization opportunity: Merge this with the previous check. + // If type is not "pattern" and init contains none of "protocol", + // "hostname", "port", "username" and "password", then set + // result["password"] to the result of processing a base URL string given + // baseURL's password and type. + if (type != process_type::pattern && !init.protocol && !init.hostname && + !init.port && !init.username && !init.password) { + result.password = url_pattern_helpers::process_base_url_string( + base_url->get_password(), type); + } + + // If init contains neither "protocol" nor "hostname", then: + if (!init.protocol && !init.hostname) { + // Let baseHost be baseURL's host. + // If baseHost is null, then set baseHost to the empty string. + auto base_host = base_url->get_hostname(); + // Set result["hostname"] to the result of processing a base URL string + // given baseHost and type. + result.hostname = + url_pattern_helpers::process_base_url_string(base_host, type); + } + + // If init contains none of "protocol", "hostname", and "port", then: + if (!init.protocol && !init.hostname && !init.port) { + // If baseURL's port is null, then set result["port"] to the empty string. + // Otherwise, set result["port"] to baseURL's port, serialized. + result.port = base_url->get_port(); + } + + // If init contains none of "protocol", "hostname", "port", and "pathname", + // then set result["pathname"] to the result of processing a base URL string + // given the result of URL path serializing baseURL and type. + if (!init.protocol && !init.hostname && !init.port && !init.pathname) { + result.pathname = url_pattern_helpers::process_base_url_string( + base_url->get_pathname(), type); + } + + // If init contains none of "protocol", "hostname", "port", "pathname", and + // "search", then: + if (!init.protocol && !init.hostname && !init.port && !init.pathname && + !init.search) { + // Let baseQuery be baseURL's query. + // Set result["search"] to the result of processing a base URL string + // given baseQuery and type. + result.search = url_pattern_helpers::process_base_url_string( + base_url->get_search(), type); + } + + // If init contains none of "protocol", "hostname", "port", "pathname", + // "search", and "hash", then: + if (!init.protocol && !init.hostname && !init.port && !init.pathname && + !init.search && !init.hash) { + // Let baseFragment be baseURL's fragment. + // Set result["hash"] to the result of processing a base URL string given + // baseFragment and type. + result.hash = url_pattern_helpers::process_base_url_string( + base_url->get_hash(), type); + } + } + + // If init["protocol"] exists, then set result["protocol"] to the result of + // process protocol for init given init["protocol"] and type. + if (init.protocol) { + auto process_result = process_protocol(*init.protocol, type); + if (!process_result) { + return tl::unexpected(process_result.error()); + } + result.protocol = std::move(*process_result); + } + + // If init["username"] exists, then set result["username"] to the result of + // process username for init given init["username"] and type. + if (init.username.has_value()) { + auto process_result = process_username(*init.username, type); + if (!process_result) { + return tl::unexpected(process_result.error()); + } + result.username = std::move(*process_result); + } + + // If init["password"] exists, then set result["password"] to the result of + // process password for init given init["password"] and type. + if (init.password.has_value()) { + auto process_result = process_password(*init.password, type); + if (!process_result) { + return tl::unexpected(process_result.error()); + } + result.password = std::move(*process_result); + } + + // If init["hostname"] exists, then set result["hostname"] to the result of + // process hostname for init given init["hostname"] and type. + if (init.hostname.has_value()) { + auto process_result = process_hostname(*init.hostname, type); + if (!process_result) { + return tl::unexpected(process_result.error()); + } + result.hostname = std::move(*process_result); + } + + // If init["port"] exists, then set result["port"] to the result of process + // port for init given init["port"], result["protocol"], and type. + if (init.port) { + auto process_result = + process_port(*init.port, result.protocol.value_or("fake"), type); + if (!process_result) { + return tl::unexpected(process_result.error()); + } + result.port = std::move(*process_result); + } + + // If init["pathname"] exists: + if (init.pathname.has_value()) { + // Set result["pathname"] to init["pathname"]. + result.pathname = init.pathname; + + // If the following are all true: + // - baseURL is not null; + // - baseURL has an opaque path; and + // - the result of running is an absolute pathname given result["pathname"] + // and type is false, + if (base_url && !base_url->has_opaque_path && + !url_pattern_helpers::is_absolute_pathname(*result.pathname, type)) { + // Let baseURLPath be the result of running process a base URL string + // given the result of URL path serializing baseURL and type. + // TODO: Optimization opportunity: Avoid returning a string if no slash + // exist. + std::string base_url_path = url_pattern_helpers::process_base_url_string( + base_url->get_pathname(), type); + + // Let slash index be the index of the last U+002F (/) code point found in + // baseURLPath, interpreted as a sequence of code points, or null if there + // are no instances of the code point. + auto slash_index = base_url_path.find_last_of('/'); + + // If slash index is not null: + if (slash_index != std::string::npos) { + // Let new pathname be the code point substring from 0 to slash index + + // 1 within baseURLPath. + base_url_path.resize(slash_index + 1); + // Append result["pathname"] to the end of new pathname. + ADA_ASSERT_TRUE(result.pathname.has_value()); + base_url_path.append(std::move(*result.pathname)); + // Set result["pathname"] to new pathname. + result.pathname = std::move(base_url_path); + } + } + + // Set result["pathname"] to the result of process pathname for init given + // result["pathname"], result["protocol"], and type. + auto pathname_processing_result = + process_pathname(*result.pathname, result.protocol.value_or(""), type); + if (!pathname_processing_result) { + return tl::unexpected(pathname_processing_result.error()); + } + result.pathname = std::move(*pathname_processing_result); + } + + // If init["search"] exists then set result["search"] to the result of process + // search for init given init["search"] and type. + if (init.search) { + auto process_result = process_search(*init.search, type); + if (!process_result) { + return tl::unexpected(process_result.error()); + } + result.search = std::move(*process_result); + } + + // If init["hash"] exists then set result["hash"] to the result of process + // hash for init given init["hash"] and type. + if (init.hash) { + auto process_result = process_hash(*init.hash, type); + if (!process_result) { + return tl::unexpected(process_result.error()); + } + result.hash = std::move(*process_result); + } + // Return result. + return result; +} + +tl::expected url_pattern_init::process_protocol( + std::string_view value, process_type type) { + ada_log("process_protocol=", value, " [", type, "]"); + // Let strippedValue be the given value with a single trailing U+003A (:) + // removed, if any. + if (value.ends_with(":")) { + value.remove_suffix(1); + } + // If type is "pattern" then return strippedValue. + if (type == process_type::pattern) { + return std::string(value); + } + // Return the result of running canonicalize a protocol given strippedValue. + return url_pattern_helpers::canonicalize_protocol(value); +} + +tl::expected url_pattern_init::process_username( + std::string_view value, process_type type) { + // If type is "pattern" then return value. + if (type == process_type::pattern) { + return std::string(value); + } + // Return the result of running canonicalize a username given value. + return url_pattern_helpers::canonicalize_username(value); +} + +tl::expected url_pattern_init::process_password( + std::string_view value, process_type type) { + // If type is "pattern" then return value. + if (type == process_type::pattern) { + return std::string(value); + } + // Return the result of running canonicalize a password given value. + return url_pattern_helpers::canonicalize_password(value); +} + +tl::expected url_pattern_init::process_hostname( + std::string_view value, process_type type) { + ada_log("process_hostname value=", value, " type=", type); + // If type is "pattern" then return value. + if (type == process_type::pattern) { + return std::string(value); + } + // Return the result of running canonicalize a hostname given value. + return url_pattern_helpers::canonicalize_hostname(value); +} + +tl::expected url_pattern_init::process_port( + std::string_view port, std::string_view protocol, process_type type) { + // If type is "pattern" then return portValue. + if (type == process_type::pattern) { + return std::string(port); + } + // Return the result of running canonicalize a port given portValue and + // protocolValue. + return url_pattern_helpers::canonicalize_port_with_protocol(port, protocol); +} + +tl::expected url_pattern_init::process_pathname( + std::string_view value, std::string_view protocol, process_type type) { + // If type is "pattern" then return pathnameValue. + if (type == process_type::pattern) { + return std::string(value); + } + + // If protocolValue is a special scheme or the empty string, then return the + // result of running canonicalize a pathname given pathnameValue. + if (protocol.empty() || scheme::is_special(protocol)) { + return url_pattern_helpers::canonicalize_pathname(value); + } + + // Return the result of running canonicalize an opaque pathname given + // pathnameValue. + return url_pattern_helpers::canonicalize_opaque_pathname(value); +} + +tl::expected url_pattern_init::process_search( + std::string_view value, process_type type) { + // Let strippedValue be the given value with a single leading U+003F (?) + // removed, if any. + if (value.starts_with("?")) { + value.remove_prefix(1); + } + // We cannot assert that the value is no longer starting with a single + // question mark because technically it can start. The question is whether or + // not we should remove the first question mark. Ref: + // https://github.com/ada-url/ada/pull/992 The spec is not clear on this. + + // If type is "pattern" then return strippedValue. + if (type == process_type::pattern) { + return std::string(value); + } + // Return the result of running canonicalize a search given strippedValue. + return url_pattern_helpers::canonicalize_search(value); +} + +tl::expected url_pattern_init::process_hash( + std::string_view value, process_type type) { + // Let strippedValue be the given value with a single leading U+0023 (#) + // removed, if any. + if (value.starts_with("#")) { + value.remove_prefix(1); + } + ADA_ASSERT_TRUE(!value.starts_with("#")); + // If type is "pattern" then return strippedValue. + if (type == process_type::pattern) { + return std::string(value); + } + // Return the result of running canonicalize a hash given strippedValue. + return url_pattern_helpers::canonicalize_hash(value); +} + +} // namespace ada + +#endif // ADA_INCLUDE_URL_PATTERN +/* end file src/url_pattern.cpp */ +/* begin file src/url_pattern_helpers.cpp */ +#if ADA_INCLUDE_URL_PATTERN + +#include +#include +#include + +namespace ada::url_pattern_helpers { + +std::tuple> +generate_regular_expression_and_name_list( + const std::vector& part_list, + url_pattern_compile_component_options options) { + // Let result be "^" + std::string result = "^"; + + // Let name list be a new list + std::vector name_list{}; + + // For each part of part list: + for (const url_pattern_part& part : part_list) { + // If part's type is "fixed-text": + if (part.type == url_pattern_part_type::FIXED_TEXT) { + // If part's modifier is "none" + if (part.modifier == url_pattern_part_modifier::none) { + // Append the result of running escape a regexp string given part's + // value + result += escape_regexp_string(part.value); + } else { + // A "fixed-text" part with a modifier uses a non capturing group + // (?:) + // Append "(?:" to the end of result. + result.append("(?:"); + // Append the result of running escape a regexp string given part's + // value to the end of result. + result.append(escape_regexp_string(part.value)); + // Append ")" to the end of result. + result.append(")"); + // Append the result of running convert a modifier to a string given + // part's modifier to the end of result. + result.append(convert_modifier_to_string(part.modifier)); + } + continue; + } + + // Assert: part's name is not the empty string + ADA_ASSERT_TRUE(!part.name.empty()); + + // Append part's name to name list + name_list.push_back(part.name); + + // Let regexp value be part's value + std::string regexp_value = part.value; + + // If part's type is "segment-wildcard" + if (part.type == url_pattern_part_type::SEGMENT_WILDCARD) { + // then set regexp value to the result of running generate a segment + // wildcard regexp given options. + regexp_value = generate_segment_wildcard_regexp(options); + } + // Otherwise if part's type is "full-wildcard" + else if (part.type == url_pattern_part_type::FULL_WILDCARD) { + // then set regexp value to full wildcard regexp value. + regexp_value = ".*"; + } + + // If part's prefix is the empty string and part's suffix is the empty + // string + if (part.prefix.empty() && part.suffix.empty()) { + // If part's modifier is "none" or "optional" + if (part.modifier == url_pattern_part_modifier::none || + part.modifier == url_pattern_part_modifier::optional) { + // () + result += "(" + regexp_value + ")" + + convert_modifier_to_string(part.modifier); + } else { + // ((?:)) + result += "((?:" + regexp_value + ")" + + convert_modifier_to_string(part.modifier) + ")"; + } + continue; + } + + // If part's modifier is "none" or "optional" + if (part.modifier == url_pattern_part_modifier::none || + part.modifier == url_pattern_part_modifier::optional) { + // (?:()) + result += "(?:" + escape_regexp_string(part.prefix) + "(" + regexp_value + + ")" + escape_regexp_string(part.suffix) + ")" + + convert_modifier_to_string(part.modifier); + continue; + } + + // Assert: part's modifier is "zero-or-more" or "one-or-more" + ADA_ASSERT_TRUE(part.modifier == url_pattern_part_modifier::zero_or_more || + part.modifier == url_pattern_part_modifier::one_or_more); + + // Assert: part's prefix is not the empty string or part's suffix is not the + // empty string + ADA_ASSERT_TRUE(!part.prefix.empty() || !part.suffix.empty()); + + // (?:((?:)(?:(?:))*))? + // Append "(?:" to the end of result. + result.append("(?:"); + // Append the result of running escape a regexp string given part's prefix + // to the end of result. + result.append(escape_regexp_string(part.prefix)); + // Append "((?:" to the end of result. + result.append("((?:"); + // Append regexp value to the end of result. + result.append(regexp_value); + // Append ")(?:" to the end of result. + result.append(")(?:"); + // Append the result of running escape a regexp string given part's suffix + // to the end of result. + result.append(escape_regexp_string(part.suffix)); + // Append the result of running escape a regexp string given part's prefix + // to the end of result. + result.append(escape_regexp_string(part.prefix)); + // Append "(?:" to the end of result. + result.append("(?:"); + // Append regexp value to the end of result. + result.append(regexp_value); + // Append "))*)" to the end of result. + result.append("))*)"); + // Append the result of running escape a regexp string given part's suffix + // to the end of result. + result.append(escape_regexp_string(part.suffix)); + // Append ")" to the end of result. + result.append(")"); + + // If part's modifier is "zero-or-more" then append "?" to the end of result + if (part.modifier == url_pattern_part_modifier::zero_or_more) { + result += "?"; + } + } + + // Append "$" to the end of result + result += "$"; + + // Return (result, name list) + return {std::move(result), std::move(name_list)}; +} + +bool is_ipv6_address(std::string_view input) noexcept { + // If input's code point length is less than 2, then return false. + if (input.size() < 2) return false; + + // Let input code points be input interpreted as a list of code points. + // If input code points[0] is U+005B ([), then return true. + if (input.front() == '[') return true; + // If input code points[0] is U+007B ({) and input code points[1] is U+005B + // ([), then return true. + if (input.starts_with("{[")) return true; + // If input code points[0] is U+005C (\) and input code points[1] is U+005B + // ([), then return true. + return input.starts_with("\\["); +} + +std::string convert_modifier_to_string(url_pattern_part_modifier modifier) { + // TODO: Optimize this. + switch (modifier) { + // If modifier is "zero-or-more", then return "*". + case url_pattern_part_modifier::zero_or_more: + return "*"; + // If modifier is "optional", then return "?". + case url_pattern_part_modifier::optional: + return "?"; + // If modifier is "one-or-more", then return "+". + case url_pattern_part_modifier::one_or_more: + return "+"; + // Return the empty string. + default: + return ""; + } +} + +std::string generate_segment_wildcard_regexp( + url_pattern_compile_component_options options) { + // Let result be "[^". + std::string result = "[^"; + // Append the result of running escape a regexp string given options's + // delimiter code point to the end of result. + result.append(escape_regexp_string(options.get_delimiter())); + // Append "]+?" to the end of result. + result.append("]+?"); + // Return result. + ada_log("generate_segment_wildcard_regexp result: ", result); + return result; +} + +tl::expected canonicalize_protocol( + std::string_view input) { + ada_log("canonicalize_protocol called with input=", input); + // If value is the empty string, return value. + if (input.empty()) [[unlikely]] { + return ""; + } + + // IMPORTANT: Deviation from the spec. We remove the trailing ':' here. + if (input.ends_with(":")) { + input.remove_suffix(1); + } + + // Let dummyURL be a new URL record. + // Let parseResult be the result of running the basic URL parser given value + // followed by "://dummy.test", with dummyURL as url. + if (auto dummy_url = ada::parse( + std::string(input) + "://dummy.test", nullptr)) { + // IMPORTANT: Deviation from the spec. We remove the trailing ':' here. + // Since URL parser always return protocols ending with `:` + auto protocol = dummy_url->get_protocol(); + protocol.remove_suffix(1); + return std::string(protocol); + } + // If parseResult is failure, then throw a TypeError. + return tl::unexpected(errors::type_error); +} + +tl::expected canonicalize_username( + std::string_view input) { + // If value is the empty string, return value. + if (input.empty()) [[unlikely]] { + return ""; + } + // Let dummyURL be a new URL record. + auto url = ada::parse("fake://dummy.test", nullptr); + ADA_ASSERT_TRUE(url.has_value()); + // Set the username given dummyURL and value. + if (!url->set_username(input)) { + return tl::unexpected(errors::type_error); + } + // Return dummyURL's username. + return std::string(url->get_username()); +} + +tl::expected canonicalize_password( + std::string_view input) { + // If value is the empty string, return value. + if (input.empty()) [[unlikely]] { + return ""; + } + // Let dummyURL be a new URL record. + // Set the password given dummyURL and value. + auto url = ada::parse("fake://dummy.test", nullptr); + + ADA_ASSERT_TRUE(url.has_value()); + if (!url->set_password(input)) { + return tl::unexpected(errors::type_error); + } + // Return dummyURL's password. + return std::string(url->get_password()); +} + +tl::expected canonicalize_hostname( + std::string_view input) { + ada_log("canonicalize_hostname input=", input); + // If value is the empty string, return value. + if (input.empty()) [[unlikely]] { + return ""; + } + // Let dummyURL be a new URL record. + // Let parseResult be the result of running the basic URL parser given value + // with dummyURL as url and hostname state as state override. + + // IMPORTANT: The protocol needs to be a special protocol, otherwise the + // hostname will not be converted using IDNA. + auto url = ada::parse("https://dummy.test", nullptr); + ADA_ASSERT_TRUE(url); + // if (!isValidHostnameInput(hostname)) return kj::none; + if (!url->set_hostname(input)) { + // If parseResult is failure, then throw a TypeError. + return tl::unexpected(errors::type_error); + } + // Return dummyURL's host, serialized, or empty string if it is null. + return std::string(url->get_hostname()); +} + +tl::expected canonicalize_ipv6_hostname( + std::string_view input) { + ada_log("canonicalize_ipv6_hostname input=", input); + // TODO: Optimization opportunity: Use lookup table to speed up checking + if (std::ranges::any_of(input, [](char c) { + return c != '[' && c != ']' && c != ':' && + !unicode::is_ascii_hex_digit(c); + })) { + return tl::unexpected(errors::type_error); + } + // Append the result of running ASCII lowercase given code point to the end of + // result. + auto hostname = std::string(input); + unicode::to_lower_ascii(hostname.data(), hostname.size()); + return hostname; +} + +tl::expected canonicalize_port( + std::string_view port_value) { + // If portValue is the empty string, return portValue. + if (port_value.empty()) [[unlikely]] { + return ""; + } + // Let dummyURL be a new URL record. + // If protocolValue was given, then set dummyURL's scheme to protocolValue. + // Let parseResult be the result of running basic URL parser given portValue + // with dummyURL as url and port state as state override. + auto url = ada::parse("fake://dummy.test", nullptr); + ADA_ASSERT_TRUE(url); + if (url->set_port(port_value)) { + // Return dummyURL's port, serialized, or empty string if it is null. + return std::string(url->get_port()); + } + // If parseResult is failure, then throw a TypeError. + return tl::unexpected(errors::type_error); +} + +tl::expected canonicalize_port_with_protocol( + std::string_view port_value, std::string_view protocol) { + // If portValue is the empty string, return portValue. + if (port_value.empty()) [[unlikely]] { + return ""; + } + + // TODO: Remove this + // We have an empty protocol because get_protocol() returns an empty string + // We should handle this in the caller rather than here. + if (protocol.empty()) { + protocol = "fake"; + } else if (protocol.ends_with(":")) { + protocol.remove_suffix(1); + } + // Let dummyURL be a new URL record. + // If protocolValue was given, then set dummyURL's scheme to protocolValue. + // Let parseResult be the result of running basic URL parser given portValue + // with dummyURL as url and port state as state override. + auto url = ada::parse(std::string(protocol) + "://dummy.test", + nullptr); + // TODO: Remove has_port() check. + // This is actually a bug with url parser where set_port() returns true for + // "invalid80" port value. + if (url && url->set_port(port_value) && url->has_port()) { + // Return dummyURL's port, serialized, or empty string if it is null. + return std::string(url->get_port()); + } + // TODO: Remove this once the previous has_port() check is removed. + if (url) { + if (scheme::is_special(protocol) && url->get_port().empty()) { + return ""; + } + } + // If parseResult is failure, then throw a TypeError. + return tl::unexpected(errors::type_error); +} + +tl::expected canonicalize_pathname( + std::string_view input) { + // If value is the empty string, then return value. + if (input.empty()) [[unlikely]] { + return ""; + } + // Let leading slash be true if the first code point in value is U+002F (/) + // and otherwise false. + const bool leading_slash = input.starts_with("/"); + // Let modified value be "/-" if leading slash is false and otherwise the + // empty string. + const auto modified_value = leading_slash ? "" : "/-"; + const auto full_url = + std::string("fake://fake-url") + modified_value + std::string(input); + if (auto url = ada::parse(full_url, nullptr)) { + const auto pathname = url->get_pathname(); + // If leading slash is false, then set result to the code point substring + // from 2 to the end of the string within result. + return leading_slash ? std::string(pathname) + : std::string(pathname.substr(2)); + } + // If parseResult is failure, then throw a TypeError. + return tl::unexpected(errors::type_error); +} + +tl::expected canonicalize_opaque_pathname( + std::string_view input) { + // If value is the empty string, return value. + if (input.empty()) [[unlikely]] { + return ""; + } + // Let dummyURL be a new URL record. + // Set dummyURL's path to the empty string. + // Let parseResult be the result of running URL parsing given value with + // dummyURL as url and opaque path state as state override. + if (auto url = + ada::parse("fake:" + std::string(input), nullptr)) { + // Return the result of URL path serializing dummyURL. + return std::string(url->get_pathname()); + } + // If parseResult is failure, then throw a TypeError. + return tl::unexpected(errors::type_error); +} + +tl::expected canonicalize_search(std::string_view input) { + // If value is the empty string, return value. + if (input.empty()) [[unlikely]] { + return ""; + } + // Let dummyURL be a new URL record. + // Set dummyURL's query to the empty string. + // Let parseResult be the result of running basic URL parser given value with + // dummyURL as url and query state as state override. + auto url = ada::parse("fake://dummy.test", nullptr); + ADA_ASSERT_TRUE(url.has_value()); + url->set_search(input); + if (url->has_search()) { + const auto search = url->get_search(); + if (!search.empty()) { + return std::string(search.substr(1)); + } + return ""; + } + return tl::unexpected(errors::type_error); +} + +tl::expected canonicalize_hash(std::string_view input) { + // If value is the empty string, return value. + if (input.empty()) [[unlikely]] { + return ""; + } + // Let dummyURL be a new URL record. + // Set dummyURL's fragment to the empty string. + // Let parseResult be the result of running basic URL parser given value with + // dummyURL as url and fragment state as state override. + auto url = ada::parse("fake://dummy.test", nullptr); + ADA_ASSERT_TRUE(url.has_value()); + url->set_hash(input); + // Return dummyURL's fragment. + if (url->has_hash()) { + const auto hash = url->get_hash(); + if (!hash.empty()) { + return std::string(hash.substr(1)); + } + return ""; + } + return tl::unexpected(errors::type_error); +} + +tl::expected, errors> tokenize(std::string_view input, + token_policy policy) { + ada_log("tokenize input: ", input); + // Let tokenizer be a new tokenizer. + // Set tokenizer's input to input. + // Set tokenizer's policy to policy. + auto tokenizer = Tokenizer(input, policy); + // While tokenizer's index is less than tokenizer's input's code point length: + while (tokenizer.index < tokenizer.input.size()) { + // Run seek and get the next code point given tokenizer and tokenizer's + // index. + tokenizer.seek_and_get_next_code_point(tokenizer.index); + + // If tokenizer's code point is U+002A (*): + if (tokenizer.code_point == '*') { + // Run add a token with default position and length given tokenizer and + // "asterisk". + tokenizer.add_token_with_defaults(token_type::ASTERISK); + ada_log("add ASTERISK token"); + // Continue. + continue; + } + + // If tokenizer's code point is U+002B (+) or U+003F (?): + if (tokenizer.code_point == '+' || tokenizer.code_point == '?') { + // Run add a token with default position and length given tokenizer and + // "other-modifier". + tokenizer.add_token_with_defaults(token_type::OTHER_MODIFIER); + // Continue. + continue; + } + + // If tokenizer's code point is U+005C (\): + if (tokenizer.code_point == '\\') { + // If tokenizer's index is equal to tokenizer's input's code point length + // - 1: + if (tokenizer.index == tokenizer.input.size() - 1) { + // Run process a tokenizing error given tokenizer, tokenizer's next + // index, and tokenizer's index. + if (auto error = tokenizer.process_tokenizing_error( + tokenizer.next_index, tokenizer.index)) { + ada_log("process_tokenizing_error failed"); + return tl::unexpected(*error); + } + continue; + } + + // Let escaped index be tokenizer's next index. + auto escaped_index = tokenizer.next_index; + // Run get the next code point given tokenizer. + tokenizer.get_next_code_point(); + // Run add a token with default length given tokenizer, "escaped-char", + // tokenizer's next index, and escaped index. + tokenizer.add_token_with_default_length( + token_type::ESCAPED_CHAR, tokenizer.next_index, escaped_index); + ada_log("add ESCAPED_CHAR token on next_index ", tokenizer.next_index, + " with escaped index ", escaped_index); + // Continue. + continue; + } + + // If tokenizer's code point is U+007B ({): + if (tokenizer.code_point == '{') { + // Run add a token with default position and length given tokenizer and + // "open". + tokenizer.add_token_with_defaults(token_type::OPEN); + ada_log("add OPEN token"); + continue; + } + + // If tokenizer's code point is U+007D (}): + if (tokenizer.code_point == '}') { + // Run add a token with default position and length given tokenizer and + // "close". + tokenizer.add_token_with_defaults(token_type::CLOSE); + ada_log("add CLOSE token"); + continue; + } + + // If tokenizer's code point is U+003A (:): + if (tokenizer.code_point == ':') { + // Let name position be tokenizer's next index. + auto name_position = tokenizer.next_index; + // Let name start be name position. + auto name_start = name_position; + // While name position is less than tokenizer's input's code point length: + while (name_position < tokenizer.input.size()) { + // Run seek and get the next code point given tokenizer and name + // position. + tokenizer.seek_and_get_next_code_point(name_position); + // Let first code point be true if name position equals name start and + // false otherwise. + bool first_code_point = name_position == name_start; + // Let valid code point be the result of running is a valid name code + // point given tokenizer's code point and first code point. + auto valid_code_point = + idna::valid_name_code_point(tokenizer.code_point, first_code_point); + ada_log("tokenizer.code_point=", uint32_t(tokenizer.code_point), + " first_code_point=", first_code_point, + " valid_code_point=", valid_code_point); + // If valid code point is false break. + if (!valid_code_point) break; + // Set name position to tokenizer's next index. + name_position = tokenizer.next_index; + } + + // If name position is less than or equal to name start: + if (name_position <= name_start) { + // Run process a tokenizing error given tokenizer, name start, and + // tokenizer's index. + if (auto error = tokenizer.process_tokenizing_error(name_start, + tokenizer.index)) { + ada_log("process_tokenizing_error failed"); + return tl::unexpected(*error); + } + // Continue + continue; + } + + // Run add a token with default length given tokenizer, "name", name + // position, and name start. + tokenizer.add_token_with_default_length(token_type::NAME, name_position, + name_start); + continue; + } + + // If tokenizer's code point is U+0028 ((): + if (tokenizer.code_point == '(') { + // Let depth be 1. + size_t depth = 1; + // Let regexp position be tokenizer's next index. + auto regexp_position = tokenizer.next_index; + // Let regexp start be regexp position. + auto regexp_start = regexp_position; + // Let error be false. + bool error = false; + + // While regexp position is less than tokenizer's input's code point + // length: + while (regexp_position < tokenizer.input.size()) { + // Run seek and get the next code point given tokenizer and regexp + // position. + tokenizer.seek_and_get_next_code_point(regexp_position); + + // TODO: Optimization opportunity: The next 2 if statements can be + // merged. If the result of running is ASCII given tokenizer's code + // point is false: + if (!unicode::is_ascii(tokenizer.code_point)) { + // Run process a tokenizing error given tokenizer, regexp start, and + // tokenizer's index. + if (auto process_error = tokenizer.process_tokenizing_error( + regexp_start, tokenizer.index)) { + return tl::unexpected(*process_error); + } + // Set error to true. + error = true; + break; + } + + // If regexp position equals regexp start and tokenizer's code point is + // U+003F (?): + if (regexp_position == regexp_start && tokenizer.code_point == '?') { + // Run process a tokenizing error given tokenizer, regexp start, and + // tokenizer's index. + if (auto process_error = tokenizer.process_tokenizing_error( + regexp_start, tokenizer.index)) { + return tl::unexpected(*process_error); + } + // Set error to true; + error = true; + break; + } + + // If tokenizer's code point is U+005C (\): + if (tokenizer.code_point == '\\') { + // If regexp position equals tokenizer's input's code point length - 1 + if (regexp_position == tokenizer.input.size() - 1) { + // Run process a tokenizing error given tokenizer, regexp start, and + // tokenizer's index. + if (auto process_error = tokenizer.process_tokenizing_error( + regexp_start, tokenizer.index)) { + return tl::unexpected(*process_error); + } + // Set error to true. + error = true; + break; + } + // Run get the next code point given tokenizer. + tokenizer.get_next_code_point(); + // If the result of running is ASCII given tokenizer's code point is + // false: + if (!unicode::is_ascii(tokenizer.code_point)) { + // Run process a tokenizing error given tokenizer, regexp start, and + // tokenizer's index. + if (auto process_error = tokenizer.process_tokenizing_error( + regexp_start, tokenizer.index); + process_error.has_value()) { + return tl::unexpected(*process_error); + } + // Set error to true. + error = true; + break; + } + // Set regexp position to tokenizer's next index. + regexp_position = tokenizer.next_index; + continue; + } + + // If tokenizer's code point is U+0029 ()): + if (tokenizer.code_point == ')') { + // Decrement depth by 1. + depth--; + // If depth is 0: + if (depth == 0) { + // Set regexp position to tokenizer's next index. + regexp_position = tokenizer.next_index; + // Break. + break; + } + } else if (tokenizer.code_point == '(') { + // Otherwise if tokenizer's code point is U+0028 ((): + // Increment depth by 1. + depth++; + // If regexp position equals tokenizer's input's code point length - + // 1: + if (regexp_position == tokenizer.input.size() - 1) { + // Run process a tokenizing error given tokenizer, regexp start, and + // tokenizer's index. + if (auto process_error = tokenizer.process_tokenizing_error( + regexp_start, tokenizer.index)) { + return tl::unexpected(*process_error); + } + // Set error to true. + error = true; + break; + } + // Let temporary position be tokenizer's next index. + auto temporary_position = tokenizer.next_index; + // Run get the next code point given tokenizer. + tokenizer.get_next_code_point(); + // If tokenizer's code point is not U+003F (?): + if (tokenizer.code_point != '?') { + // Run process a tokenizing error given tokenizer, regexp start, and + // tokenizer's index. + if (auto process_error = tokenizer.process_tokenizing_error( + regexp_start, tokenizer.index)) { + return tl::unexpected(*process_error); + } + // Set error to true. + error = true; + break; + } + // Set tokenizer's next index to temporary position. + tokenizer.next_index = temporary_position; + } + // Set regexp position to tokenizer's next index. + regexp_position = tokenizer.next_index; + } + + // If error is true continue. + if (error) continue; + // If depth is not zero: + if (depth != 0) { + // Run process a tokenizing error given tokenizer, regexp start, and + // tokenizer's index. + if (auto process_error = tokenizer.process_tokenizing_error( + regexp_start, tokenizer.index)) { + return tl::unexpected(*process_error); + } + continue; + } + // Let regexp length be regexp position - regexp start - 1. + auto regexp_length = regexp_position - regexp_start - 1; + // If regexp length is zero: + if (regexp_length == 0) { + // Run process a tokenizing error given tokenizer, regexp start, and + // tokenizer's index. + if (auto process_error = tokenizer.process_tokenizing_error( + regexp_start, tokenizer.index)) { + ada_log("process_tokenizing_error failed"); + return tl::unexpected(*process_error); + } + continue; + } + // Run add a token given tokenizer, "regexp", regexp position, regexp + // start, and regexp length. + tokenizer.add_token(token_type::REGEXP, regexp_position, regexp_start, + regexp_length); + continue; + } + // Run add a token with default position and length given tokenizer and + // "char". + tokenizer.add_token_with_defaults(token_type::CHAR); + } + // Run add a token with default length given tokenizer, "end", tokenizer's + // index, and tokenizer's index. + tokenizer.add_token_with_default_length(token_type::END, tokenizer.index, + tokenizer.index); + + ada_log("tokenizer.token_list size is: ", tokenizer.token_list.size()); + // Return tokenizer's token list. + return tokenizer.token_list; +} + +std::string escape_pattern_string(std::string_view input) { + ada_log("escape_pattern_string called with input=", input); + if (input.empty()) [[unlikely]] { + return ""; + } + // Assert: input is an ASCII string. + ADA_ASSERT_TRUE(ada::idna::is_ascii(input)); + // Let result be the empty string. + std::string result{}; + result.reserve(input.size()); + + // TODO: Optimization opportunity: Use a lookup table + constexpr auto should_escape = [](const char c) { + return c == '+' || c == '*' || c == '?' || c == ':' || c == '{' || + c == '}' || c == '(' || c == ')' || c == '\\'; + }; + + // While index is less than input's length: + for (const auto& c : input) { + if (should_escape(c)) { + // then append U+005C (\) to the end of result. + result.append("\\"); + } + + // Append c to the end of result. + result += c; + } + // Return result. + return result; +} + +namespace { +constexpr std::array escape_regexp_table = []() consteval { + std::array out{}; + for (auto& c : {'.', '+', '*', '?', '^', '$', '{', '}', '(', ')', '[', ']', + '|', '/', '\\'}) { + out[c] = 1; + } + return out; +}(); + +constexpr bool should_escape_regexp_char(char c) { + return escape_regexp_table[(uint8_t)c]; +} +} // namespace + +std::string escape_regexp_string(std::string_view input) { + // Assert: input is an ASCII string. + ADA_ASSERT_TRUE(idna::is_ascii(input)); + // Let result be the empty string. + std::string result{}; + result.reserve(input.size()); + for (const auto& c : input) { + // TODO: Optimize this even further + if (should_escape_regexp_char(c)) { + result.append(std::string("\\") + c); + } else { + result.push_back(c); + } + } + return result; +} + +std::string process_base_url_string(std::string_view input, + url_pattern_init::process_type type) { + // If type is not "pattern" return input. + if (type != url_pattern_init::process_type::pattern) { + return std::string(input); + } + // Return the result of escaping a pattern string given input. + return escape_pattern_string(input); +} + +constexpr bool is_absolute_pathname( + std::string_view input, url_pattern_init::process_type type) noexcept { + // If input is the empty string, then return false. + if (input.empty()) [[unlikely]] { + return false; + } + // If input[0] is U+002F (/), then return true. + if (input.starts_with("/")) return true; + // If type is "url", then return false. + if (type == url_pattern_init::process_type::url) return false; + // If input's code point length is less than 2, then return false. + if (input.size() < 2) return false; + // If input[0] is U+005C (\) and input[1] is U+002F (/), then return true. + // If input[0] is U+007B ({) and input[1] is U+002F (/), then return true. + // Return false. + return input[1] == '/' && (input[0] == '\\' || input[0] == '{'); +} + +std::string generate_pattern_string( + std::vector& part_list, + url_pattern_compile_component_options& options) { + // Let result be the empty string. + std::string result{}; + // Let index list be the result of getting the indices for part list. + // For each index of index list: + for (size_t index = 0; index < part_list.size(); index++) { + // Let part be part list[index]. + auto part = part_list[index]; + // Let previous part be part list[index - 1] if index is greater than 0, + // otherwise let it be null. + // TODO: Optimization opportunity. Find a way to avoid making a copy here. + std::optional previous_part = + index == 0 ? std::nullopt : std::optional(part_list[index - 1]); + // Let next part be part list[index + 1] if index is less than index list's + // size - 1, otherwise let it be null. + std::optional next_part = + index < part_list.size() - 1 ? std::optional(part_list[index + 1]) + : std::nullopt; + // If part's type is "fixed-text" then: + if (part.type == url_pattern_part_type::FIXED_TEXT) { + // If part's modifier is "none" then: + if (part.modifier == url_pattern_part_modifier::none) { + // Append the result of running escape a pattern string given part's + // value to the end of result. + result.append(escape_pattern_string(part.value)); + continue; + } + // Append "{" to the end of result. + result += "{"; + // Append the result of running escape a pattern string given part's value + // to the end of result. + result.append(escape_pattern_string(part.value)); + // Append "}" to the end of result. + result += "}"; + // Append the result of running convert a modifier to a string given + // part's modifier to the end of result. + result.append(convert_modifier_to_string(part.modifier)); + continue; + } + // Let custom name be true if part's name[0] is not an ASCII digit; + // otherwise false. + bool custom_name = !unicode::is_ascii_digit(part.name[0]); + // Let needs grouping be true if at least one of the following are true, + // otherwise let it be false: + // - part's suffix is not the empty string. + // - part's prefix is not the empty string and is not options's prefix code + // point. + bool needs_grouping = + !part.suffix.empty() || + (!part.prefix.empty() && part.prefix[0] != options.get_prefix()[0]); + + // If all of the following are true: + // - needs grouping is false; and + // - custom name is true; and + // - part's type is "segment-wildcard"; and + // - part's modifier is "none"; and + // - next part is not null; and + // - next part's prefix is the empty string; and + // - next part's suffix is the empty string + if (!needs_grouping && custom_name && + part.type == url_pattern_part_type::SEGMENT_WILDCARD && + part.modifier == url_pattern_part_modifier::none && + next_part.has_value() && next_part->prefix.empty() && + next_part->suffix.empty()) { + // If next part's type is "fixed-text": + if (next_part->type == url_pattern_part_type::FIXED_TEXT) { + // Set needs grouping to true if the result of running is a valid name + // code point given next part's value's first code point and the boolean + // false is true. + if (idna::valid_name_code_point(next_part->value[0], false)) { + needs_grouping = true; + } + } else { + // Set needs grouping to true if next part's name[0] is an ASCII digit. + needs_grouping = !next_part->name.empty() && + unicode::is_ascii_digit(next_part->name[0]); + } + } + + // If all of the following are true: + // - needs grouping is false; and + // - part's prefix is the empty string; and + // - previous part is not null; and + // - previous part's type is "fixed-text"; and + // - previous part's value's last code point is options's prefix code point. + // then set needs grouping to true. + if (!needs_grouping && part.prefix.empty() && previous_part.has_value() && + previous_part->type == url_pattern_part_type::FIXED_TEXT && + !options.get_prefix().empty() && + previous_part->value.at(previous_part->value.size() - 1) == + options.get_prefix()[0]) { + needs_grouping = true; + } + + // Assert: part's name is not the empty string or null. + ADA_ASSERT_TRUE(!part.name.empty()); + + // If needs grouping is true, then append "{" to the end of result. + if (needs_grouping) { + result.append("{"); + } + + // Append the result of running escape a pattern string given part's prefix + // to the end of result. + result.append(escape_pattern_string(part.prefix)); + + // If custom name is true: + if (custom_name) { + // Append ":" to the end of result. + result.append(":"); + // Append part's name to the end of result. + result.append(part.name); + } + + // If part's type is "regexp" then: + if (part.type == url_pattern_part_type::REGEXP) { + // Append "(" to the end of result. + result.append("("); + // Append part's value to the end of result. + result.append(part.value); + // Append ")" to the end of result. + result.append(")"); + } else if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && + !custom_name) { + // Otherwise if part's type is "segment-wildcard" and custom name is + // false: Append "(" to the end of result. + result.append("("); + // Append the result of running generate a segment wildcard regexp given + // options to the end of result. + result.append(generate_segment_wildcard_regexp(options)); + // Append ")" to the end of result. + result.append(")"); + } else if (part.type == url_pattern_part_type::FULL_WILDCARD) { + // Otherwise if part's type is "full-wildcard": + // If custom name is false and one of the following is true: + // - previous part is null; or + // - previous part's type is "fixed-text"; or + // - previous part's modifier is not "none"; or + // - needs grouping is true; or + // - part's prefix is not the empty string + // - then append "*" to the end of result. + if (!custom_name && + (!previous_part.has_value() || + previous_part->type == url_pattern_part_type::FIXED_TEXT || + previous_part->modifier != url_pattern_part_modifier::none || + needs_grouping || !part.prefix.empty())) { + result.append("*"); + } else { + // Append "(" to the end of result. + // Append full wildcard regexp value to the end of result. + // Append ")" to the end of result. + result.append("(.*)"); + } + } + + // If all of the following are true: + // - part's type is "segment-wildcard"; and + // - custom name is true; and + // - part's suffix is not the empty string; and + // - The result of running is a valid name code point given part's suffix's + // first code point and the boolean false is true then append U+005C (\) to + // the end of result. + if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && custom_name && + !part.suffix.empty() && + idna::valid_name_code_point(part.suffix[0], false)) { + result.append("\\"); + } + + // Append the result of running escape a pattern string given part's suffix + // to the end of result. + result.append(escape_pattern_string(part.suffix)); + // If needs grouping is true, then append "}" to the end of result. + if (needs_grouping) result.append("}"); + // Append the result of running convert a modifier to a string given part's + // modifier to the end of result. + result.append(convert_modifier_to_string(part.modifier)); + } + // Return result. + return result; +} +} // namespace ada::url_pattern_helpers + +#endif // ADA_INCLUDE_URL_PATTERN +/* end file src/url_pattern_helpers.cpp */ +/* begin file src/url_pattern_regex.cpp */ +#if ADA_INCLUDE_URL_PATTERN + + +namespace ada::url_pattern_regex { + +#ifdef ADA_USE_UNSAFE_STD_REGEX_PROVIDER +std::optional std_regex_provider::create_instance( + std::string_view pattern, bool ignore_case) { + // Let flags be an empty string. + // If options's ignore case is true then set flags to "vi". + // Otherwise set flags to "v" + auto flags = ignore_case + ? std::regex::icase | std::regex_constants::ECMAScript + : std::regex_constants::ECMAScript; + try { + return std::regex(pattern.data(), pattern.size(), flags); + } catch (const std::regex_error& e) { + (void)e; + ada_log("std_regex_provider::create_instance failed:", e.what()); + return std::nullopt; + } +} + +std::optional>> +std_regex_provider::regex_search(std::string_view input, + const std::regex& pattern) { + std::string input_str( + input.begin(), + input.end()); // Convert string_view to string for regex_search + std::smatch match_result; + if (!std::regex_search(input_str, match_result, pattern, + std::regex_constants::match_any)) { + return std::nullopt; + } + std::vector> matches; + // If input is empty, let's assume the result will be empty as well. + if (input.empty() || match_result.empty()) { + return matches; + } + matches.reserve(match_result.size()); + for (size_t i = 1; i < match_result.size(); ++i) { + if (auto entry = match_result[i]; entry.matched) { + matches.emplace_back(entry.str()); + } + } + return matches; +} + +bool std_regex_provider::regex_match(std::string_view input, + const std::regex& pattern) { + return std::regex_match(input.begin(), input.end(), pattern); +} + +#endif // ADA_USE_UNSAFE_STD_REGEX_PROVIDER + +} // namespace ada::url_pattern_regex + +#endif // ADA_INCLUDE_URL_PATTERN +/* end file src/url_pattern_regex.cpp */ +#endif // ADA_INCLUDE_URL_PATTERN + /* begin file src/ada_c.cpp */ ada::result& get_instance(void* result) noexcept { diff --git a/test-app/runtime/src/main/cpp/modules/url/ada/ada.h b/test-app/runtime/src/main/cpp/modules/url/ada/ada.h index a42ed6ef..db2803c8 100644 --- a/test-app/runtime/src/main/cpp/modules/url/ada/ada.h +++ b/test-app/runtime/src/main/cpp/modules/url/ada/ada.h @@ -1,4 +1,4 @@ -/* auto-generated on 2024-07-06 17:38:56 -0400. Do not edit! */ +/* auto-generated on 2025-09-23 12:57:35 -0400. Do not edit! */ /* begin file include/ada.h */ /** * @file ada.h @@ -8,7 +8,7 @@ #define ADA_H /* begin file include/ada/ada_idna.h */ -/* auto-generated on 2023-09-19 15:58:51 -0400. Do not edit! */ +/* auto-generated on 2025-03-08 13:17:11 -0500. Do not edit! */ /* begin file include/idna.h */ #ifndef ADA_IDNA_H #define ADA_IDNA_H @@ -45,8 +45,6 @@ namespace ada::idna { // If the input is ascii, then the mapping is just -> lower case. void ascii_map(char* input, size_t length); -// check whether an ascii string needs mapping -bool ascii_has_upper_case(char* input, size_t length); // Map the characters according to IDNA, returning the empty string on error. std::u32string map(std::u32string_view input); @@ -129,9 +127,6 @@ std::string to_ascii(std::string_view ut8_string); // https://url.spec.whatwg.org/#forbidden-domain-code-point bool contains_forbidden_domain_code_point(std::string_view ascii_string); -bool begins_with(std::u32string_view view, std::u32string_view prefix); -bool begins_with(std::string_view view, std::string_view prefix); - bool constexpr is_ascii(std::u32string_view view); bool constexpr is_ascii(std::string_view view); @@ -154,20 +149,32 @@ std::string to_unicode(std::string_view input); #endif // ADA_IDNA_TO_UNICODE_H /* end file include/ada/idna/to_unicode.h */ +/* begin file include/ada/idna/identifier.h */ +#ifndef ADA_IDNA_IDENTIFIER_H +#define ADA_IDNA_IDENTIFIER_H + +#include +#include + +namespace ada::idna { + +// Verify if it is valid name code point given a Unicode code point and a +// boolean first: If first is true return the result of checking if code point +// is contained in the IdentifierStart set of code points. Otherwise return the +// result of checking if code point is contained in the IdentifierPart set of +// code points. Returns false if the input is empty or the code point is not +// valid. There is minimal Unicode error handling: the input should be valid +// UTF-8. https://urlpattern.spec.whatwg.org/#is-a-valid-name-code-point +bool valid_name_code_point(char32_t code_point, bool first); + +} // namespace ada::idna + +#endif +/* end file include/ada/idna/identifier.h */ #endif /* end file include/idna.h */ /* end file include/ada/ada_idna.h */ -/* begin file include/ada/character_sets-inl.h */ -/** - * @file character_sets-inl.h - * @brief Definitions of the character sets used by unicode functions. - * @author Node.js - * @see https://github.com/nodejs/node/blob/main/src/node_url_tables.cc - */ -#ifndef ADA_CHARACTER_SETS_INL_H -#define ADA_CHARACTER_SETS_INL_H - /* begin file include/ada/character_sets.h */ /** * @file character_sets.h @@ -186,6 +193,10 @@ std::string to_unicode(std::string_view input); #ifndef ADA_COMMON_DEFS_H #define ADA_COMMON_DEFS_H +// https://en.cppreference.com/w/cpp/feature_test#Library_features +// detect C++20 features +#include + #ifdef _MSC_VER #define ADA_VISUAL_STUDIO 1 /** @@ -230,13 +241,6 @@ std::string to_unicode(std::string_view input); #define ada_unused #define ada_warn_unused -#ifndef ada_likely -#define ada_likely(x) x -#endif -#ifndef ada_unlikely -#define ada_unlikely(x) x -#endif - #define ADA_PUSH_DISABLE_WARNINGS __pragma(warning(push)) #define ADA_PUSH_DISABLE_ALL_WARNINGS __pragma(warning(push, 0)) #define ADA_DISABLE_VS_WARNING(WARNING_NUMBER) \ @@ -268,13 +272,6 @@ std::string to_unicode(std::string_view input); #define ada_unused __attribute__((unused)) #define ada_warn_unused __attribute__((warn_unused_result)) -#ifndef ada_likely -#define ada_likely(x) __builtin_expect(!!(x), 1) -#endif -#ifndef ada_unlikely -#define ada_unlikely(x) __builtin_expect(!!(x), 0) -#endif - #define ADA_PUSH_DISABLE_WARNINGS _Pragma("GCC diagnostic push") // gcc doesn't seem to disable all warnings with all and extra, add warnings // here as necessary @@ -290,7 +287,8 @@ std::string to_unicode(std::string_view input); ADA_DISABLE_GCC_WARNING("-Wreturn-type") \ ADA_DISABLE_GCC_WARNING("-Wshadow") \ ADA_DISABLE_GCC_WARNING("-Wunused-parameter") \ - ADA_DISABLE_GCC_WARNING("-Wunused-variable") + ADA_DISABLE_GCC_WARNING("-Wunused-variable") \ + ADA_DISABLE_GCC_WARNING("-Wsign-compare") #define ADA_PRAGMA(P) _Pragma(#P) #define ADA_DISABLE_GCC_WARNING(WARNING) \ ADA_PRAGMA(GCC diagnostic ignored WARNING) @@ -354,52 +352,6 @@ namespace ada { } } // namespace ada -#if defined(__GNUC__) && !defined(__clang__) -#if __GNUC__ <= 8 -#define ADA_OLD_GCC 1 -#endif // __GNUC__ <= 8 -#endif // defined(__GNUC__) && !defined(__clang__) - -#if ADA_OLD_GCC -#define ada_constexpr -#else -#define ada_constexpr constexpr -#endif - -#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) -#define ADA_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) -#elif defined(_WIN32) -#define ADA_IS_BIG_ENDIAN 0 -#else -#if defined(__APPLE__) || \ - defined(__FreeBSD__) // defined __BYTE_ORDER__ && defined - // __ORDER_BIG_ENDIAN__ -#include -#elif defined(sun) || \ - defined(__sun) // defined(__APPLE__) || defined(__FreeBSD__) -#include -#else // defined(__APPLE__) || defined(__FreeBSD__) - -#ifdef __has_include -#if __has_include() -#include -#endif //__has_include() -#endif //__has_include - -#endif // defined(__APPLE__) || defined(__FreeBSD__) - -#ifndef !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) -#define ADA_IS_BIG_ENDIAN 0 -#endif - -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define ADA_IS_BIG_ENDIAN 0 -#else // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define ADA_IS_BIG_ENDIAN 1 -#endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - -#endif // defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__ - // Unless the programmer has already set ADA_DEVELOPMENT_CHECKS, // we want to set it under debug builds. We detect a debug build // under Visual Studio when the _DEBUG macro is set. Under the other @@ -479,6 +431,33 @@ namespace ada { #define ADA_NEON 1 #endif +#if defined(__loongarch_sx) +#define ADA_LSX 1 +#endif + +#ifndef __has_cpp_attribute +#define ada_lifetime_bound +#elif __has_cpp_attribute(msvc::lifetimebound) +#define ada_lifetime_bound [[msvc::lifetimebound]] +#elif __has_cpp_attribute(clang::lifetimebound) +#define ada_lifetime_bound [[clang::lifetimebound]] +#elif __has_cpp_attribute(lifetimebound) +#define ada_lifetime_bound [[lifetimebound]] +#else +#define ada_lifetime_bound +#endif + +#ifdef __cpp_lib_format +#if __cpp_lib_format >= 202110L +#include +#define ADA_HAS_FORMAT 1 +#endif +#endif + +#ifndef ADA_INCLUDE_URL_PATTERN +#define ADA_INCLUDE_URL_PATTERN 1 +#endif // ADA_INCLUDE_URL_PATTERN + #endif // ADA_COMMON_DEFS_H /* end file include/ada/common_defs.h */ #include @@ -491,11 +470,21 @@ namespace ada { * @brief Includes the definitions for unicode character sets. */ namespace ada::character_sets { -ada_really_inline bool bit_at(const uint8_t a[], uint8_t i); +ada_really_inline constexpr bool bit_at(const uint8_t a[], uint8_t i); } // namespace ada::character_sets #endif // ADA_CHARACTER_SETS_H /* end file include/ada/character_sets.h */ +/* begin file include/ada/character_sets-inl.h */ +/** + * @file character_sets-inl.h + * @brief Definitions of the character sets used by unicode functions. + * @author Node.js + * @see https://github.com/nodejs/node/blob/main/src/node_url_tables.cc + */ +#ifndef ADA_CHARACTER_SETS_INL_H +#define ADA_CHARACTER_SETS_INL_H + /** * These functions are not part of our public API and may @@ -892,7 +881,7 @@ constexpr uint8_t PATH_PERCENT_ENCODE[32] = { // 50 51 52 53 54 55 56 57 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, // 58 59 5A 5B 5C 5D 5E 5F - 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x40 | 0x00, // 60 61 62 63 64 65 66 67 0x01 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, // 68 69 6A 6B 6C 6D 6E 6F @@ -958,7 +947,7 @@ constexpr uint8_t WWW_FORM_URLENCODED_PERCENT_ENCODE[32] = { // 50 51 52 53 54 55 56 57 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, // 58 59 5A 5B 5C 5D 5E 5F - 0x00 | 0x00 | 0x00 | 0x08 | 0x00 | 0x20 | 0x40 | 0x00, + 0x00 | 0x00 | 0x00 | 0x08 | 0x10 | 0x20 | 0x40 | 0x00, // 60 61 62 63 64 65 66 67 0x01 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, // 68 69 6A 6B 6C 6D 6E 6F @@ -1000,7 +989,7 @@ constexpr uint8_t WWW_FORM_URLENCODED_PERCENT_ENCODE[32] = { // F8 F9 FA FB FC FD FE FF 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80}; -ada_really_inline bool bit_at(const uint8_t a[], const uint8_t i) { +ada_really_inline constexpr bool bit_at(const uint8_t a[], const uint8_t i) { return !!(a[i >> 3] & (1 << (i & 7))); } @@ -1016,22 +1005,19 @@ ada_really_inline bool bit_at(const uint8_t a[], const uint8_t i) { #ifndef ADA_CHECKERS_INL_H #define ADA_CHECKERS_INL_H -#include -#include +#include #include namespace ada::checkers { -inline bool has_hex_prefix_unsafe(std::string_view input) { +constexpr bool has_hex_prefix_unsafe(std::string_view input) { // This is actually efficient code, see has_hex_prefix for the assembly. - uint32_t value_one = 1; - bool is_little_endian = (reinterpret_cast(&value_one)[0] == 1); - uint16_t word0x{}; - std::memcpy(&word0x, "0x", 2); // we would use bit_cast in C++20 and the - // function could be constexpr. - uint16_t two_first_bytes{}; - std::memcpy(&two_first_bytes, input.data(), 2); - if (is_little_endian) { + constexpr bool is_little_endian = std::endian::native == std::endian::little; + constexpr uint16_t word0x = 0x7830; + uint16_t two_first_bytes = + static_cast(input[0]) | + static_cast((static_cast(input[1]) << 8)); + if constexpr (is_little_endian) { two_first_bytes |= 0x2000; } else { two_first_bytes |= 0x020; @@ -1039,7 +1025,7 @@ inline bool has_hex_prefix_unsafe(std::string_view input) { return two_first_bytes == word0x; } -inline bool has_hex_prefix(std::string_view input) { +constexpr bool has_hex_prefix(std::string_view input) { return input.size() >= 2 && has_hex_prefix_unsafe(input); } @@ -1051,26 +1037,18 @@ constexpr bool is_alpha(char x) noexcept { return (to_lower(x) >= 'a') && (to_lower(x) <= 'z'); } -inline constexpr bool is_windows_drive_letter(std::string_view input) noexcept { +constexpr bool is_windows_drive_letter(std::string_view input) noexcept { return input.size() >= 2 && (is_alpha(input[0]) && ((input[1] == ':') || (input[1] == '|'))) && ((input.size() == 2) || (input[2] == '/' || input[2] == '\\' || input[2] == '?' || input[2] == '#')); } -inline constexpr bool is_normalized_windows_drive_letter( +constexpr bool is_normalized_windows_drive_letter( std::string_view input) noexcept { return input.size() >= 2 && (is_alpha(input[0]) && (input[1] == ':')); } -ada_really_inline bool begins_with(std::string_view view, - std::string_view prefix) { - // in C++20, you have view.begins_with(prefix) - // std::equal is constexpr in C++20 - return view.size() >= prefix.size() && - std::equal(prefix.begin(), prefix.end(), view.begin()); -} - } // namespace ada::checkers #endif // ADA_CHECKERS_INL_H @@ -1084,65 +1062,31 @@ ada_really_inline bool begins_with(std::string_view view, #ifndef ADA_LOG_H #define ADA_LOG_H -#include // To enable logging, set ADA_LOGGING to 1: #ifndef ADA_LOGGING #define ADA_LOGGING 0 #endif -namespace ada { - -/** - * Private function used for logging messages. - * @private - */ -template -ada_really_inline void inner_log([[maybe_unused]] T t) { -#if ADA_LOGGING - std::cout << t << std::endl; -#endif -} - -/** - * Private function used for logging messages. - * @private - */ -template -ada_really_inline void inner_log([[maybe_unused]] T t, - [[maybe_unused]] Args... args) { #if ADA_LOGGING - std::cout << t; - inner_log(args...); -#endif -} +#include +#endif // ADA_LOGGING -/** - * Log a message. - * @private - */ -template -ada_really_inline void log([[maybe_unused]] T t, - [[maybe_unused]] Args... args) { -#if ADA_LOGGING - std::cout << "ADA_LOG: " << t; - inner_log(args...); -#endif -} +namespace ada { /** - * Log a message. + * Log a message. If you want to have no overhead when logging is disabled, use + * the ada_log macro. * @private */ -template -ada_really_inline void log([[maybe_unused]] T t) { +template +constexpr ada_really_inline void log([[maybe_unused]] Args... args) { #if ADA_LOGGING - std::cout << "ADA_LOG: " << t << std::endl; -#endif + ((std::cout << "ADA_LOG: ") << ... << args) << std::endl; +#endif // ADA_LOGGING } } // namespace ada #if ADA_LOGGING - #ifndef ada_log #define ada_log(...) \ do { \ @@ -1182,7 +1126,7 @@ enum class encoding_type { /** * Convert a encoding_type to string. */ -ada_warn_unused std::string to_string(encoding_type type); +ada_warn_unused std::string_view to_string(encoding_type type); } // namespace ada @@ -1196,512 +1140,311 @@ ada_warn_unused std::string to_string(encoding_type type); #ifndef ADA_HELPERS_H #define ADA_HELPERS_H -/* begin file include/ada/state.h */ +/* begin file include/ada/url_base.h */ /** - * @file state.h - * @brief Definitions for the states of the URL state machine. + * @file url_base.h + * @brief Declaration for the basic URL definitions */ -#ifndef ADA_STATE_H -#define ADA_STATE_H +#ifndef ADA_URL_BASE_H +#define ADA_URL_BASE_H + +/* begin file include/ada/scheme.h */ +/** + * @file scheme.h + * @brief Declarations for the URL scheme. + */ +#ifndef ADA_SCHEME_H +#define ADA_SCHEME_H + + +#include + +/** + * @namespace ada::scheme + * @brief Includes the scheme declarations + */ +namespace ada::scheme { + +/** + * Type of the scheme as an enum. + * Using strings to represent a scheme type is not ideal because + * checking for types involves string comparisons. It is faster to use + * a simple integer. + * In C++11, we are allowed to specify the underlying type of the enum. + * We pick an 8-bit integer (which allows up to 256 types). Specifying the + * type of the enum may help integration with other systems if the type + * variable is exposed (since its value will not depend on the compiler). + */ +enum type : uint8_t { + HTTP = 0, + NOT_SPECIAL = 1, + HTTPS = 2, + WS = 3, + FTP = 4, + WSS = 5, + FILE = 6 +}; + +/** + * A special scheme is an ASCII string that is listed in the first column of the + * following table. The default port for a special scheme is listed in the + * second column on the same row. The default port for any other ASCII string is + * null. + * + * @see https://url.spec.whatwg.org/#url-miscellaneous + * @param scheme + * @return If scheme is a special scheme + */ +ada_really_inline constexpr bool is_special(std::string_view scheme); + +/** + * A special scheme is an ASCII string that is listed in the first column of the + * following table. The default port for a special scheme is listed in the + * second column on the same row. The default port for any other ASCII string is + * null. + * + * @see https://url.spec.whatwg.org/#url-miscellaneous + * @param scheme + * @return The special port + */ +constexpr uint16_t get_special_port(std::string_view scheme) noexcept; + +/** + * Returns the port number of a special scheme. + * @see https://url.spec.whatwg.org/#special-scheme + */ +constexpr uint16_t get_special_port(ada::scheme::type type) noexcept; +/** + * Returns the scheme of an input, or NOT_SPECIAL if it's not a special scheme + * defined by the spec. + */ +constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept; + +} // namespace ada::scheme + +#endif // ADA_SCHEME_H +/* end file include/ada/scheme.h */ #include +#include namespace ada { /** - * @see https://url.spec.whatwg.org/#url-parsing + * Type of URL host as an enum. */ -enum class state { +enum url_host_type : uint8_t { /** - * @see https://url.spec.whatwg.org/#authority-state + * Represents common URLs such as "https://www.google.com" */ - AUTHORITY, - + DEFAULT = 0, /** - * @see https://url.spec.whatwg.org/#scheme-start-state + * Represents ipv4 addresses such as "http://127.0.0.1" */ - SCHEME_START, - + IPV4 = 1, /** - * @see https://url.spec.whatwg.org/#scheme-state + * Represents ipv6 addresses such as + * "http://[2001:db8:3333:4444:5555:6666:7777:8888]" */ - SCHEME, + IPV6 = 2, +}; - /** - * @see https://url.spec.whatwg.org/#host-state - */ - HOST, +/** + * @brief Base class of URL implementations + * + * @details A url_base contains a few attributes: is_valid, has_opaque_path and + * type. All non-trivial implementation details are in derived classes such as + * ada::url and ada::url_aggregator. + * + * It is an abstract class that cannot be instantiated directly. + */ +struct url_base { + virtual ~url_base() = default; /** - * @see https://url.spec.whatwg.org/#no-scheme-state + * Used for returning the validity from the result of the URL parser. */ - NO_SCHEME, + bool is_valid{true}; /** - * @see https://url.spec.whatwg.org/#fragment-state + * A URL has an opaque path if its path is a string. */ - FRAGMENT, + bool has_opaque_path{false}; /** - * @see https://url.spec.whatwg.org/#relative-state + * URL hosts type */ - RELATIVE_SCHEME, + url_host_type host_type = url_host_type::DEFAULT; /** - * @see https://url.spec.whatwg.org/#relative-slash-state + * @private */ - RELATIVE_SLASH, + ada::scheme::type type{ada::scheme::type::NOT_SPECIAL}; /** - * @see https://url.spec.whatwg.org/#file-state + * A URL is special if its scheme is a special scheme. A URL is not special if + * its scheme is not a special scheme. */ - FILE, + [[nodiscard]] ada_really_inline constexpr bool is_special() const noexcept; /** - * @see https://url.spec.whatwg.org/#file-host-state + * The origin getter steps are to return the serialization of this's URL's + * origin. [HTML] + * @return a newly allocated string. + * @see https://url.spec.whatwg.org/#concept-url-origin */ - FILE_HOST, + [[nodiscard]] virtual std::string get_origin() const noexcept = 0; /** - * @see https://url.spec.whatwg.org/#file-slash-state + * Returns true if this URL has a valid domain as per RFC 1034 and + * corresponding specifications. Among other things, it requires + * that the domain string has fewer than 255 octets. */ - FILE_SLASH, + [[nodiscard]] virtual bool has_valid_domain() const noexcept = 0; /** - * @see https://url.spec.whatwg.org/#path-or-authority-state + * @private + * + * Return the 'special port' if the URL is special and not 'file'. + * Returns 0 otherwise. */ - PATH_OR_AUTHORITY, + [[nodiscard]] inline uint16_t get_special_port() const noexcept; /** - * @see https://url.spec.whatwg.org/#special-authority-ignore-slashes-state + * @private + * + * Get the default port if the url's scheme has one, returns 0 otherwise. */ - SPECIAL_AUTHORITY_IGNORE_SLASHES, + [[nodiscard]] ada_really_inline uint16_t scheme_default_port() const noexcept; /** - * @see https://url.spec.whatwg.org/#special-authority-slashes-state + * @private + * + * Parse a port (16-bit decimal digit) from the provided input. + * We assume that the input does not contain spaces or tabs + * within the ASCII digits. + * It returns how many bytes were consumed when a number is successfully + * parsed. + * @return On failure, it returns zero. + * @see https://url.spec.whatwg.org/#host-parsing */ - SPECIAL_AUTHORITY_SLASHES, + virtual size_t parse_port(std::string_view view, + bool check_trailing_content) noexcept = 0; - /** - * @see https://url.spec.whatwg.org/#special-relative-or-authority-state - */ - SPECIAL_RELATIVE_OR_AUTHORITY, + virtual ada_really_inline size_t parse_port(std::string_view view) noexcept { + return this->parse_port(view, false); + } /** - * @see https://url.spec.whatwg.org/#query-state + * Returns a JSON string representation of this URL. */ - QUERY, + [[nodiscard]] virtual std::string to_string() const = 0; - /** - * @see https://url.spec.whatwg.org/#path-state - */ - PATH, + /** @private */ + virtual inline void clear_pathname() = 0; - /** - * @see https://url.spec.whatwg.org/#path-start-state - */ - PATH_START, + /** @private */ + virtual inline void clear_search() = 0; - /** - * @see https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state - */ - OPAQUE_PATH, + /** @private */ + [[nodiscard]] virtual inline bool has_hash() const noexcept = 0; - /** - * @see https://url.spec.whatwg.org/#port-state - */ - PORT, -}; + /** @private */ + [[nodiscard]] virtual inline bool has_search() const noexcept = 0; -/** - * Stringify a URL state machine state. - */ -ada_warn_unused std::string to_string(ada::state s); +}; // url_base } // namespace ada -#endif // ADA_STATE_H -/* end file include/ada/state.h */ -/* begin file include/ada/url_base.h */ -/** - * @file url_base.h - * @brief Declaration for the basic URL definitions - */ -#ifndef ADA_URL_BASE_H -#define ADA_URL_BASE_H - -/* begin file include/ada/url_components.h */ -/** - * @file url_components.h - * @brief Declaration for the URL Components - */ -#ifndef ADA_URL_COMPONENTS_H -#define ADA_URL_COMPONENTS_H +#endif +/* end file include/ada/url_base.h */ -#include +#include #include +#include -namespace ada { +#if ADA_DEVELOPMENT_CHECKS +#include +#endif // ADA_DEVELOPMENT_CHECKS /** - * @brief URL Component representations using offsets. - * - * @details We design the url_components struct so that it is as small - * and simple as possible. This version uses 32 bytes. + * These functions are not part of our public API and may + * change at any time. * - * This struct is used to extract components from a single 'href'. + * @private + * @namespace ada::helpers + * @brief Includes the definitions for helper functions */ -struct url_components { - constexpr static uint32_t omitted = uint32_t(-1); - - url_components() = default; - url_components(const url_components& u) = default; - url_components(url_components&& u) noexcept = default; - url_components& operator=(url_components&& u) noexcept = default; - url_components& operator=(const url_components& u) = default; - ~url_components() = default; - - /* - * By using 32-bit integers, we implicitly assume that the URL string - * cannot exceed 4 GB. - * - * https://user:pass@example.com:1234/foo/bar?baz#quux - * | | | | ^^^^| | | - * | | | | | | | `----- hash_start - * | | | | | | `--------- search_start - * | | | | | `----------------- pathname_start - * | | | | `--------------------- port - * | | | `----------------------- host_end - * | | `---------------------------------- host_start - * | `--------------------------------------- username_end - * `--------------------------------------------- protocol_end - */ - uint32_t protocol_end{0}; - /** - * Username end is not `omitted` by default to make username and password - * getters less costly to implement. - */ - uint32_t username_end{0}; - uint32_t host_start{0}; - uint32_t host_end{0}; - uint32_t port{omitted}; - uint32_t pathname_start{0}; - uint32_t search_start{omitted}; - uint32_t hash_start{omitted}; - - /** - * Check the following conditions: - * protocol_end < username_end < ... < hash_start, - * expect when a value is omitted. It also computes - * a lower bound on the possible string length that may match these - * offsets. - * @return true if the offset values are - * consistent with a possible URL string - */ - [[nodiscard]] bool check_offset_consistency() const noexcept; - - /** - * Converts a url_components to JSON stringified version. - */ - [[nodiscard]] std::string to_string() const; - -}; // struct url_components +namespace ada::helpers { -} // namespace ada -#endif -/* end file include/ada/url_components.h */ -/* begin file include/ada/scheme.h */ /** - * @file scheme.h - * @brief Declarations for the URL scheme. + * @private */ -#ifndef ADA_SCHEME_H -#define ADA_SCHEME_H - -#include -#include -#include +template +void encode_json(std::string_view view, out_iter out); /** - * @namespace ada::scheme - * @brief Includes the scheme declarations + * @private + * This function is used to prune a fragment from a url, and returning the + * removed string if input has fragment. + * + * @details prune_hash seeks the first '#' and returns everything after it + * as a string_view, and modifies (in place) the input so that it points at + * everything before the '#'. If no '#' is found, the input is left unchanged + * and std::nullopt is returned. + * + * @attention The function is non-allocating and it does not throw. + * @returns Note that the returned string_view might be empty! */ -namespace ada::scheme { +ada_really_inline std::optional prune_hash( + std::string_view& input) noexcept; /** - * Type of the scheme as an enum. - * Using strings to represent a scheme type is not ideal because - * checking for types involves string comparisons. It is faster to use - * a simple integer. - * In C++11, we are allowed to specify the underlying type of the enum. - * We pick an 8-bit integer (which allows up to 256 types). Specifying the - * type of the enum may help integration with other systems if the type - * variable is exposed (since its value will not depend on the compiler). + * @private + * Defined by the URL specification, shorten a URLs paths. + * @see https://url.spec.whatwg.org/#shorten-a-urls-path + * @returns Returns true if path is shortened. */ -enum type : uint8_t { - HTTP = 0, - NOT_SPECIAL = 1, - HTTPS = 2, - WS = 3, - FTP = 4, - WSS = 5, - FILE = 6 -}; +ada_really_inline bool shorten_path(std::string& path, + ada::scheme::type type) noexcept; /** - * A special scheme is an ASCII string that is listed in the first column of the - * following table. The default port for a special scheme is listed in the - * second column on the same row. The default port for any other ASCII string is - * null. - * - * @see https://url.spec.whatwg.org/#url-miscellaneous - * @param scheme - * @return If scheme is a special scheme + * @private + * Defined by the URL specification, shorten a URLs paths. + * @see https://url.spec.whatwg.org/#shorten-a-urls-path + * @returns Returns true if path is shortened. */ -ada_really_inline constexpr bool is_special(std::string_view scheme); +ada_really_inline bool shorten_path(std::string_view& path, + ada::scheme::type type) noexcept; /** - * A special scheme is an ASCII string that is listed in the first column of the - * following table. The default port for a special scheme is listed in the - * second column on the same row. The default port for any other ASCII string is - * null. + * @private * - * @see https://url.spec.whatwg.org/#url-miscellaneous - * @param scheme - * @return The special port + * Parse the path from the provided input and append to the existing + * (possibly empty) path. The input cannot contain tabs and spaces: it + * is the user's responsibility to check. + * + * The input is expected to be UTF-8. + * + * @see https://url.spec.whatwg.org/ */ -constexpr uint16_t get_special_port(std::string_view scheme) noexcept; +ada_really_inline void parse_prepared_path(std::string_view input, + ada::scheme::type type, + std::string& path); /** - * Returns the port number of a special scheme. - * @see https://url.spec.whatwg.org/#special-scheme + * @private + * Remove and mutate all ASCII tab or newline characters from an input. */ -constexpr uint16_t get_special_port(ada::scheme::type type) noexcept; +ada_really_inline void remove_ascii_tab_or_newline(std::string& input) noexcept; + /** - * Returns the scheme of an input, or NOT_SPECIAL if it's not a special scheme - * defined by the spec. + * @private + * Return the substring from input going from index pos to the end. + * This function cannot throw. */ -constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept; - -} // namespace ada::scheme - -#endif // ADA_SCHEME_H -/* end file include/ada/scheme.h */ - -#include - -namespace ada { - -/** - * Type of URL host as an enum. - */ -enum url_host_type : uint8_t { - /** - * Represents common URLs such as "https://www.google.com" - */ - DEFAULT = 0, - /** - * Represents ipv4 addresses such as "http://127.0.0.1" - */ - IPV4 = 1, - /** - * Represents ipv6 addresses such as - * "http://[2001:db8:3333:4444:5555:6666:7777:8888]" - */ - IPV6 = 2, -}; - -/** - * @brief Base class of URL implementations - * - * @details A url_base contains a few attributes: is_valid, has_opaque_path and - * type. All non-trivial implementation details are in derived classes such as - * ada::url and ada::url_aggregator. - * - * It is an abstract class that cannot be instantiated directly. - */ -struct url_base { - virtual ~url_base() = default; - - /** - * Used for returning the validity from the result of the URL parser. - */ - bool is_valid{true}; - - /** - * A URL has an opaque path if its path is a string. - */ - bool has_opaque_path{false}; - - /** - * URL hosts type - */ - url_host_type host_type = url_host_type::DEFAULT; - - /** - * @private - */ - ada::scheme::type type{ada::scheme::type::NOT_SPECIAL}; - - /** - * A URL is special if its scheme is a special scheme. A URL is not special if - * its scheme is not a special scheme. - */ - [[nodiscard]] ada_really_inline bool is_special() const noexcept; - - /** - * The origin getter steps are to return the serialization of this's URL's - * origin. [HTML] - * @return a newly allocated string. - * @see https://url.spec.whatwg.org/#concept-url-origin - */ - [[nodiscard]] virtual std::string get_origin() const noexcept = 0; - - /** - * Returns true if this URL has a valid domain as per RFC 1034 and - * corresponding specifications. Among other things, it requires - * that the domain string has fewer than 255 octets. - */ - [[nodiscard]] virtual bool has_valid_domain() const noexcept = 0; - - /** - * @private - * - * Return the 'special port' if the URL is special and not 'file'. - * Returns 0 otherwise. - */ - [[nodiscard]] inline uint16_t get_special_port() const noexcept; - - /** - * @private - * - * Get the default port if the url's scheme has one, returns 0 otherwise. - */ - [[nodiscard]] ada_really_inline uint16_t scheme_default_port() const noexcept; - - /** - * @private - * - * Parse a port (16-bit decimal digit) from the provided input. - * We assume that the input does not contain spaces or tabs - * within the ASCII digits. - * It returns how many bytes were consumed when a number is successfully - * parsed. - * @return On failure, it returns zero. - * @see https://url.spec.whatwg.org/#host-parsing - */ - virtual size_t parse_port(std::string_view view, - bool check_trailing_content) noexcept = 0; - - virtual ada_really_inline size_t parse_port(std::string_view view) noexcept { - return this->parse_port(view, false); - } - - /** - * Returns a JSON string representation of this URL. - */ - [[nodiscard]] virtual std::string to_string() const = 0; - - /** @private */ - virtual inline void clear_pathname() = 0; - - /** @private */ - virtual inline void clear_search() = 0; - - /** @private */ - [[nodiscard]] virtual inline bool has_hash() const noexcept = 0; - - /** @private */ - [[nodiscard]] virtual inline bool has_search() const noexcept = 0; - -}; // url_base - -} // namespace ada - -#endif -/* end file include/ada/url_base.h */ - -#include -#include - -/** - * These functions are not part of our public API and may - * change at any time. - * - * @private - * @namespace ada::helpers - * @brief Includes the definitions for helper functions - */ -namespace ada::helpers { - -/** - * @private - */ -template -void encode_json(std::string_view view, out_iter out); - -/** - * @private - * This function is used to prune a fragment from a url, and returning the - * removed string if input has fragment. - * - * @details prune_hash seeks the first '#' and returns everything after it - * as a string_view, and modifies (in place) the input so that it points at - * everything before the '#'. If no '#' is found, the input is left unchanged - * and std::nullopt is returned. - * - * @attention The function is non-allocating and it does not throw. - * @returns Note that the returned string_view might be empty! - */ -ada_really_inline std::optional prune_hash( - std::string_view& input) noexcept; - -/** - * @private - * Defined by the URL specification, shorten a URLs paths. - * @see https://url.spec.whatwg.org/#shorten-a-urls-path - * @returns Returns true if path is shortened. - */ -ada_really_inline bool shorten_path(std::string& path, - ada::scheme::type type) noexcept; - -/** - * @private - * Defined by the URL specification, shorten a URLs paths. - * @see https://url.spec.whatwg.org/#shorten-a-urls-path - * @returns Returns true if path is shortened. - */ -ada_really_inline bool shorten_path(std::string_view& path, - ada::scheme::type type) noexcept; - -/** - * @private - * - * Parse the path from the provided input and append to the existing - * (possibly empty) path. The input cannot contain tabs and spaces: it - * is the user's responsibility to check. - * - * The input is expected to be UTF-8. - * - * @see https://url.spec.whatwg.org/ - */ -ada_really_inline void parse_prepared_path(std::string_view input, - ada::scheme::type type, - std::string& path); - -/** - * @private - * Remove and mutate all ASCII tab or newline characters from an input. - */ -ada_really_inline void remove_ascii_tab_or_newline(std::string& input) noexcept; - -/** - * @private - * Return the substring from input going from index pos to the end. - * This function cannot throw. - */ -ada_really_inline std::string_view substring(std::string_view input, - size_t pos) noexcept; +ada_really_inline constexpr std::string_view substring(std::string_view input, + size_t pos) noexcept; /** * @private @@ -1714,9 +1457,9 @@ bool overlaps(std::string_view input1, const std::string& input2) noexcept; * Return the substring from input going from index pos1 to the pos2 (non * included). The length of the substring is pos2 - pos1. */ -ada_really_inline std::string_view substring(const std::string& input, - size_t pos1, - size_t pos2) noexcept { +ada_really_inline constexpr std::string_view substring(std::string_view input, + size_t pos1, + size_t pos2) noexcept { #if ADA_DEVELOPMENT_CHECKS if (pos2 < pos1) { std::cerr << "Negative-length substring: [" << pos1 << " to " << pos2 << ")" @@ -1724,7 +1467,7 @@ ada_really_inline std::string_view substring(const std::string& input, abort(); } #endif - return std::string_view(input.data() + pos1, pos2 - pos1); + return input.substr(pos1, pos2 - pos1); } /** @@ -1740,14 +1483,14 @@ ada_really_inline void resize(std::string_view& input, size_t pos) noexcept; * and whether a colon was found outside brackets. Used by the host parser. */ ada_really_inline std::pair get_host_delimiter_location( - const bool is_special, std::string_view& view) noexcept; + bool is_special, std::string_view& view) noexcept; /** * @private * Removes leading and trailing C0 control and whitespace characters from * string. */ -ada_really_inline void trim_c0_whitespace(std::string_view& input) noexcept; +void trim_c0_whitespace(std::string_view& input) noexcept; /** * @private @@ -1851,8 +1594,8 @@ inline int fast_digit_count(uint32_t x) noexcept { #ifndef ADA_PARSER_H #define ADA_PARSER_H -#include #include +#include /* begin file include/ada/expected.h */ /** @@ -2008,25 +1751,25 @@ class unexpected { static_assert(!std::is_same::value, "E must not be void"); unexpected() = delete; - constexpr explicit unexpected(const E& e) : m_val(e) {} + constexpr explicit unexpected(const E &e) : m_val(e) {} - constexpr explicit unexpected(E&& e) : m_val(std::move(e)) {} + constexpr explicit unexpected(E &&e) : m_val(std::move(e)) {} template ::value>::type* = nullptr> - constexpr explicit unexpected(Args&&... args) + E, Args &&...>::value>::type * = nullptr> + constexpr explicit unexpected(Args &&...args) : m_val(std::forward(args)...) {} template < class U, class... Args, typename std::enable_if&, Args&&...>::value>::type* = nullptr> - constexpr explicit unexpected(std::initializer_list l, Args&&... args) + E, std::initializer_list &, Args &&...>::value>::type * = nullptr> + constexpr explicit unexpected(std::initializer_list l, Args &&...args) : m_val(l, std::forward(args)...) {} - constexpr const E& value() const& { return m_val; } - TL_EXPECTED_11_CONSTEXPR E& value() & { return m_val; } - TL_EXPECTED_11_CONSTEXPR E&& value() && { return std::move(m_val); } - constexpr const E&& value() const&& { return std::move(m_val); } + constexpr const E &value() const & { return m_val; } + TL_EXPECTED_11_CONSTEXPR E &value() & { return m_val; } + TL_EXPECTED_11_CONSTEXPR E &&value() && { return std::move(m_val); } + constexpr const E &&value() const && { return std::move(m_val); } private: E m_val; @@ -2038,32 +1781,32 @@ unexpected(E) -> unexpected; #endif template -constexpr bool operator==(const unexpected& lhs, const unexpected& rhs) { +constexpr bool operator==(const unexpected &lhs, const unexpected &rhs) { return lhs.value() == rhs.value(); } template -constexpr bool operator!=(const unexpected& lhs, const unexpected& rhs) { +constexpr bool operator!=(const unexpected &lhs, const unexpected &rhs) { return lhs.value() != rhs.value(); } template -constexpr bool operator<(const unexpected& lhs, const unexpected& rhs) { +constexpr bool operator<(const unexpected &lhs, const unexpected &rhs) { return lhs.value() < rhs.value(); } template -constexpr bool operator<=(const unexpected& lhs, const unexpected& rhs) { +constexpr bool operator<=(const unexpected &lhs, const unexpected &rhs) { return lhs.value() <= rhs.value(); } template -constexpr bool operator>(const unexpected& lhs, const unexpected& rhs) { +constexpr bool operator>(const unexpected &lhs, const unexpected &rhs) { return lhs.value() > rhs.value(); } template -constexpr bool operator>=(const unexpected& lhs, const unexpected& rhs) { +constexpr bool operator>=(const unexpected &lhs, const unexpected &rhs) { return lhs.value() >= rhs.value(); } template -unexpected::type> make_unexpected(E&& e) { +unexpected::type> make_unexpected(E &&e) { return unexpected::type>(std::forward(e)); } @@ -2074,7 +1817,7 @@ static constexpr unexpect_t unexpect{}; namespace detail { template -[[noreturn]] TL_EXPECTED_11_CONSTEXPR void throw_exception(E&& e) { +[[noreturn]] TL_EXPECTED_11_CONSTEXPR void throw_exception(E &&e) { #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED throw std::forward(e); #else @@ -2124,7 +1867,7 @@ template struct is_pointer_to_non_const_member_func : std::true_type {}; template -struct is_pointer_to_non_const_member_func +struct is_pointer_to_non_const_member_func : std::true_type {}; template struct is_pointer_to_non_const_member_func @@ -2133,16 +1876,16 @@ template struct is_pointer_to_non_const_member_func : std::true_type {}; template -struct is_pointer_to_non_const_member_func +struct is_pointer_to_non_const_member_func : std::true_type {}; template -struct is_pointer_to_non_const_member_func +struct is_pointer_to_non_const_member_func : std::true_type {}; template struct is_const_or_const_ref : std::false_type {}; template -struct is_const_or_const_ref : std::true_type {}; +struct is_const_or_const_ref : std::true_type {}; template struct is_const_or_const_ref : std::true_type {}; #endif @@ -2156,7 +1899,7 @@ template < is_const_or_const_ref::value)>, #endif typename = enable_if_t>::value>, int = 0> -constexpr auto invoke(Fn&& f, Args&&... args) noexcept( +constexpr auto invoke(Fn &&f, Args &&...args) noexcept( noexcept(std::mem_fn(f)(std::forward(args)...))) -> decltype(std::mem_fn(f)(std::forward(args)...)) { return std::mem_fn(f)(std::forward(args)...); @@ -2164,7 +1907,7 @@ constexpr auto invoke(Fn&& f, Args&&... args) noexcept( template >::value>> -constexpr auto invoke(Fn&& f, Args&&... args) noexcept( +constexpr auto invoke(Fn &&f, Args &&...args) noexcept( noexcept(std::forward(f)(std::forward(args)...))) -> decltype(std::forward(f)(std::forward(args)...)) { return std::forward(f)(std::forward(args)...); @@ -2204,7 +1947,7 @@ namespace swap_adl_tests { struct tag {}; template -tag swap(T&, T&); +tag swap(T &, T &); template tag swap(T (&a)[N], T (&b)[N]); @@ -2213,14 +1956,14 @@ tag swap(T (&a)[N], T (&b)[N]); template std::false_type can_swap(...) noexcept(false); template (), std::declval()))> -std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(), - std::declval()))); + class = decltype(swap(std::declval(), std::declval()))> +std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(), + std::declval()))); template std::false_type uses_std(...); template -std::is_same(), std::declval())), tag> +std::is_same(), std::declval())), tag> uses_std(int); template @@ -2251,8 +1994,8 @@ struct is_swappable : std::integral_constant< bool, decltype(detail::swap_adl_tests::can_swap(0))::value && - (!decltype( - detail::swap_adl_tests::uses_std(0))::value || + (!decltype(detail::swap_adl_tests::uses_std( + 0))::value || is_swappable::value)> {}; template @@ -2260,12 +2003,10 @@ struct is_nothrow_swappable : std::integral_constant< bool, is_swappable::value && - ((decltype(detail::swap_adl_tests::uses_std(0))::value&& - detail::swap_adl_tests::is_std_swap_noexcept::value) || - (!decltype(detail::swap_adl_tests::uses_std(0))::value&& - detail::swap_adl_tests::is_adl_swap_noexcept::value))> { -}; + ((decltype(detail::swap_adl_tests::uses_std(0))::value && + detail::swap_adl_tests::is_std_swap_noexcept::value) || + (!decltype(detail::swap_adl_tests::uses_std(0))::value && + detail::swap_adl_tests::is_adl_swap_noexcept::value))> {}; #endif #endif @@ -2279,7 +2020,7 @@ using is_expected = is_expected_impl>; template using expected_enable_forward_value = detail::enable_if_t< - std::is_constructible::value && + std::is_constructible::value && !std::is_same, in_place_t>::value && !std::is_same, detail::decay_t>::value && !std::is_same, detail::decay_t>::value>; @@ -2288,14 +2029,14 @@ template using expected_enable_from_other = detail::enable_if_t< std::is_constructible::value && std::is_constructible::value && - !std::is_constructible&>::value && - !std::is_constructible&&>::value && - !std::is_constructible&>::value && - !std::is_constructible&&>::value && - !std::is_convertible&, T>::value && - !std::is_convertible&&, T>::value && - !std::is_convertible&, T>::value && - !std::is_convertible&&, T>::value>; + !std::is_constructible &>::value && + !std::is_constructible &&>::value && + !std::is_constructible &>::value && + !std::is_constructible &&>::value && + !std::is_convertible &, T>::value && + !std::is_convertible &&, T>::value && + !std::is_convertible &, T>::value && + !std::is_convertible &&, T>::value>; template using is_void_or = conditional_t::value, std::true_type, U>; @@ -2333,29 +2074,29 @@ struct expected_storage_base { constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} template ::value>* = + detail::enable_if_t::value> * = nullptr> - constexpr expected_storage_base(in_place_t, Args&&... args) + constexpr expected_storage_base(in_place_t, Args &&...args) : m_val(std::forward(args)...), m_has_val(true) {} template &, Args&&...>::value>* = nullptr> + T, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args&&... args) + Args &&...args) : m_val(il, std::forward(args)...), m_has_val(true) {} template ::value>* = + detail::enable_if_t::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args&&... args) + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template &, Args&&...>::value>* = nullptr> + E, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args&&... args) + Args &&...args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() { @@ -2381,29 +2122,29 @@ struct expected_storage_base { constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} template ::value>* = + detail::enable_if_t::value> * = nullptr> - constexpr expected_storage_base(in_place_t, Args&&... args) + constexpr expected_storage_base(in_place_t, Args &&...args) : m_val(std::forward(args)...), m_has_val(true) {} template &, Args&&...>::value>* = nullptr> + T, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args&&... args) + Args &&...args) : m_val(il, std::forward(args)...), m_has_val(true) {} template ::value>* = + detail::enable_if_t::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args&&... args) + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template &, Args&&...>::value>* = nullptr> + E, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args&&... args) + Args &&...args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() = default; @@ -2423,29 +2164,29 @@ struct expected_storage_base { : m_no_init(), m_has_val(false) {} template ::value>* = + detail::enable_if_t::value> * = nullptr> - constexpr expected_storage_base(in_place_t, Args&&... args) + constexpr expected_storage_base(in_place_t, Args &&...args) : m_val(std::forward(args)...), m_has_val(true) {} template &, Args&&...>::value>* = nullptr> + T, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args&&... args) + Args &&...args) : m_val(il, std::forward(args)...), m_has_val(true) {} template ::value>* = + detail::enable_if_t::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args&&... args) + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template &, Args&&...>::value>* = nullptr> + E, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args&&... args) + Args &&...args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() { @@ -2469,29 +2210,29 @@ struct expected_storage_base { constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} template ::value>* = + detail::enable_if_t::value> * = nullptr> - constexpr expected_storage_base(in_place_t, Args&&... args) + constexpr expected_storage_base(in_place_t, Args &&...args) : m_val(std::forward(args)...), m_has_val(true) {} template &, Args&&...>::value>* = nullptr> + T, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args&&... args) + Args &&...args) : m_val(il, std::forward(args)...), m_has_val(true) {} template ::value>* = + detail::enable_if_t::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args&&... args) + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template &, Args&&...>::value>* = nullptr> + E, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args&&... args) + Args &&...args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() { @@ -2522,17 +2263,17 @@ struct expected_storage_base { constexpr expected_storage_base(in_place_t) : m_has_val(true) {} template ::value>* = + detail::enable_if_t::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args&&... args) + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template &, Args&&...>::value>* = nullptr> + E, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args&&... args) + Args &&...args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() = default; @@ -2553,17 +2294,17 @@ struct expected_storage_base { constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {} template ::value>* = + detail::enable_if_t::value> * = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args&&... args) + constexpr explicit expected_storage_base(unexpect_t, Args &&...args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template &, Args&&...>::value>* = nullptr> + E, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args&&... args) + Args &&...args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() { @@ -2586,19 +2327,19 @@ struct expected_operations_base : expected_storage_base { using expected_storage_base::expected_storage_base; template - void construct(Args&&... args) noexcept { + void construct(Args &&...args) noexcept { new (std::addressof(this->m_val)) T(std::forward(args)...); this->m_has_val = true; } template - void construct_with(Rhs&& rhs) noexcept { + void construct_with(Rhs &&rhs) noexcept { new (std::addressof(this->m_val)) T(std::forward(rhs).get()); this->m_has_val = true; } template - void construct_error(Args&&... args) noexcept { + void construct_error(Args &&...args) noexcept { new (std::addressof(this->m_unexpect)) unexpected(std::forward(args)...); this->m_has_val = false; @@ -2613,9 +2354,9 @@ struct expected_operations_base : expected_storage_base { // This overload handles the case where we can just copy-construct `T` // directly into place without throwing. template ::value>* = - nullptr> - void assign(const expected_operations_base& rhs) noexcept { + detail::enable_if_t::value> + * = nullptr> + void assign(const expected_operations_base &rhs) noexcept { if (!this->m_has_val && rhs.m_has_val) { geterr().~unexpected(); construct(rhs.get()); @@ -2628,9 +2369,9 @@ struct expected_operations_base : expected_storage_base { // `T`, then no-throw move it into place if the copy was successful. template ::value && - std::is_nothrow_move_constructible::value>* = - nullptr> - void assign(const expected_operations_base& rhs) noexcept { + std::is_nothrow_move_constructible::value> + * = nullptr> + void assign(const expected_operations_base &rhs) noexcept { if (!this->m_has_val && rhs.m_has_val) { T tmp = rhs.get(); geterr().~unexpected(); @@ -2646,10 +2387,10 @@ struct expected_operations_base : expected_storage_base { // then we move the old unexpected value back into place before rethrowing the // exception. template ::value && - !std::is_nothrow_move_constructible::value>* = nullptr> - void assign(const expected_operations_base& rhs) { + detail::enable_if_t::value && + !std::is_nothrow_move_constructible::value> + * = nullptr> + void assign(const expected_operations_base &rhs) { if (!this->m_has_val && rhs.m_has_val) { auto tmp = std::move(geterr()); geterr().~unexpected(); @@ -2671,9 +2412,9 @@ struct expected_operations_base : expected_storage_base { // These overloads do the same as above, but for rvalues template ::value>* = - nullptr> - void assign(expected_operations_base&& rhs) noexcept { + detail::enable_if_t::value> + * = nullptr> + void assign(expected_operations_base &&rhs) noexcept { if (!this->m_has_val && rhs.m_has_val) { geterr().~unexpected(); construct(std::move(rhs).get()); @@ -2683,9 +2424,9 @@ struct expected_operations_base : expected_storage_base { } template ::value>* = nullptr> - void assign(expected_operations_base&& rhs) { + detail::enable_if_t::value> + * = nullptr> + void assign(expected_operations_base &&rhs) { if (!this->m_has_val && rhs.m_has_val) { auto tmp = std::move(geterr()); geterr().~unexpected(); @@ -2707,7 +2448,7 @@ struct expected_operations_base : expected_storage_base { #else // If exceptions are disabled then we can just copy-construct - void assign(const expected_operations_base& rhs) noexcept { + void assign(const expected_operations_base &rhs) noexcept { if (!this->m_has_val && rhs.m_has_val) { geterr().~unexpected(); construct(rhs.get()); @@ -2716,7 +2457,7 @@ struct expected_operations_base : expected_storage_base { } } - void assign(expected_operations_base&& rhs) noexcept { + void assign(expected_operations_base &&rhs) noexcept { if (!this->m_has_val && rhs.m_has_val) { geterr().~unexpected(); construct(std::move(rhs).get()); @@ -2729,7 +2470,7 @@ struct expected_operations_base : expected_storage_base { // The common part of move/copy assigning template - void assign_common(Rhs&& rhs) { + void assign_common(Rhs &&rhs) { if (this->m_has_val) { if (rhs.m_has_val) { get() = std::forward(rhs).get(); @@ -2746,22 +2487,22 @@ struct expected_operations_base : expected_storage_base { bool has_value() const { return this->m_has_val; } - TL_EXPECTED_11_CONSTEXPR T& get() & { return this->m_val; } - constexpr const T& get() const& { return this->m_val; } - TL_EXPECTED_11_CONSTEXPR T&& get() && { return std::move(this->m_val); } + TL_EXPECTED_11_CONSTEXPR T &get() & { return this->m_val; } + constexpr const T &get() const & { return this->m_val; } + TL_EXPECTED_11_CONSTEXPR T &&get() && { return std::move(this->m_val); } #ifndef TL_EXPECTED_NO_CONSTRR - constexpr const T&& get() const&& { return std::move(this->m_val); } + constexpr const T &&get() const && { return std::move(this->m_val); } #endif - TL_EXPECTED_11_CONSTEXPR unexpected& geterr() & { + TL_EXPECTED_11_CONSTEXPR unexpected &geterr() & { return this->m_unexpect; } - constexpr const unexpected& geterr() const& { return this->m_unexpect; } - TL_EXPECTED_11_CONSTEXPR unexpected&& geterr() && { + constexpr const unexpected &geterr() const & { return this->m_unexpect; } + TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() && { return std::move(this->m_unexpect); } #ifndef TL_EXPECTED_NO_CONSTRR - constexpr const unexpected&& geterr() const&& { + constexpr const unexpected &&geterr() const && { return std::move(this->m_unexpect); } #endif @@ -2783,19 +2524,19 @@ struct expected_operations_base : expected_storage_base { // This function doesn't use its argument, but needs it so that code in // levels above this can work independently of whether T is void template - void construct_with(Rhs&&) noexcept { + void construct_with(Rhs &&) noexcept { this->m_has_val = true; } template - void construct_error(Args&&... args) noexcept { + void construct_error(Args &&...args) noexcept { new (std::addressof(this->m_unexpect)) unexpected(std::forward(args)...); this->m_has_val = false; } template - void assign(Rhs&& rhs) noexcept { + void assign(Rhs &&rhs) noexcept { if (!this->m_has_val) { if (rhs.m_has_val) { geterr().~unexpected(); @@ -2812,15 +2553,15 @@ struct expected_operations_base : expected_storage_base { bool has_value() const { return this->m_has_val; } - TL_EXPECTED_11_CONSTEXPR unexpected& geterr() & { + TL_EXPECTED_11_CONSTEXPR unexpected &geterr() & { return this->m_unexpect; } - constexpr const unexpected& geterr() const& { return this->m_unexpect; } - TL_EXPECTED_11_CONSTEXPR unexpected&& geterr() && { + constexpr const unexpected &geterr() const & { return this->m_unexpect; } + TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() && { return std::move(this->m_unexpect); } #ifndef TL_EXPECTED_NO_CONSTRR - constexpr const unexpected&& geterr() const&& { + constexpr const unexpected &&geterr() const && { return std::move(this->m_unexpect); } #endif @@ -2833,8 +2574,9 @@ struct expected_operations_base : expected_storage_base { // This class manages conditionally having a trivial copy constructor // This specialization is for when T and E are trivially copy constructible template :: - value&& TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value> + bool = is_void_or::value && + TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value> struct expected_copy_base : expected_operations_base { using expected_operations_base::expected_operations_base; }; @@ -2845,7 +2587,7 @@ struct expected_copy_base : expected_operations_base { using expected_operations_base::expected_operations_base; expected_copy_base() = default; - expected_copy_base(const expected_copy_base& rhs) + expected_copy_base(const expected_copy_base &rhs) : expected_operations_base(no_init) { if (rhs.has_value()) { this->construct_with(rhs); @@ -2854,9 +2596,9 @@ struct expected_copy_base : expected_operations_base { } } - expected_copy_base(expected_copy_base&& rhs) = default; - expected_copy_base& operator=(const expected_copy_base& rhs) = default; - expected_copy_base& operator=(expected_copy_base&& rhs) = default; + expected_copy_base(expected_copy_base &&rhs) = default; + expected_copy_base &operator=(const expected_copy_base &rhs) = default; + expected_copy_base &operator=(expected_copy_base &&rhs) = default; }; // This class manages conditionally having a trivial move constructor @@ -2866,7 +2608,8 @@ struct expected_copy_base : expected_operations_base { // move constructible #ifndef TL_EXPECTED_GCC49 template >::value&& + bool = + is_void_or>::value && std::is_trivially_move_constructible::value> struct expected_move_base : expected_copy_base { using expected_copy_base::expected_copy_base; @@ -2880,9 +2623,9 @@ struct expected_move_base : expected_copy_base { using expected_copy_base::expected_copy_base; expected_move_base() = default; - expected_move_base(const expected_move_base& rhs) = default; + expected_move_base(const expected_move_base &rhs) = default; - expected_move_base(expected_move_base&& rhs) noexcept( + expected_move_base(expected_move_base &&rhs) noexcept( std::is_nothrow_move_constructible::value) : expected_copy_base(no_init) { if (rhs.has_value()) { @@ -2891,19 +2634,21 @@ struct expected_move_base : expected_copy_base { this->construct_error(std::move(rhs.geterr())); } } - expected_move_base& operator=(const expected_move_base& rhs) = default; - expected_move_base& operator=(expected_move_base&& rhs) = default; + expected_move_base &operator=(const expected_move_base &rhs) = default; + expected_move_base &operator=(expected_move_base &&rhs) = default; }; // This class manages conditionally having a trivial copy assignment operator -template >::value&& - TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value&& - TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value&& - TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value> +template < + class T, class E, + bool = + is_void_or< + T, conjunction>::value && + TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value && + TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value && + TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value> struct expected_copy_assign_base : expected_move_base { using expected_move_base::expected_move_base; }; @@ -2913,14 +2658,14 @@ struct expected_copy_assign_base : expected_move_base { using expected_move_base::expected_move_base; expected_copy_assign_base() = default; - expected_copy_assign_base(const expected_copy_assign_base& rhs) = default; + expected_copy_assign_base(const expected_copy_assign_base &rhs) = default; - expected_copy_assign_base(expected_copy_assign_base&& rhs) = default; - expected_copy_assign_base& operator=(const expected_copy_assign_base& rhs) { + expected_copy_assign_base(expected_copy_assign_base &&rhs) = default; + expected_copy_assign_base &operator=(const expected_copy_assign_base &rhs) { this->assign(rhs); return *this; } - expected_copy_assign_base& operator=(expected_copy_assign_base&& rhs) = + expected_copy_assign_base &operator=(expected_copy_assign_base &&rhs) = default; }; @@ -2930,14 +2675,15 @@ struct expected_copy_assign_base : expected_move_base { // to make do with a non-trivial move assignment operator even if T is trivially // move assignable #ifndef TL_EXPECTED_GCC49 -template , - std::is_trivially_move_constructible, - std::is_trivially_move_assignable>>:: - value&& std::is_trivially_destructible::value&& - std::is_trivially_move_constructible::value&& - std::is_trivially_move_assignable::value> +template < + class T, class E, + bool = is_void_or< + T, conjunction, + std::is_trivially_move_constructible, + std::is_trivially_move_assignable>>::value && + std::is_trivially_destructible::value && + std::is_trivially_move_constructible::value && + std::is_trivially_move_assignable::value> struct expected_move_assign_base : expected_copy_assign_base { using expected_copy_assign_base::expected_copy_assign_base; }; @@ -2952,17 +2698,17 @@ struct expected_move_assign_base using expected_copy_assign_base::expected_copy_assign_base; expected_move_assign_base() = default; - expected_move_assign_base(const expected_move_assign_base& rhs) = default; + expected_move_assign_base(const expected_move_assign_base &rhs) = default; - expected_move_assign_base(expected_move_assign_base&& rhs) = default; + expected_move_assign_base(expected_move_assign_base &&rhs) = default; - expected_move_assign_base& operator=(const expected_move_assign_base& rhs) = + expected_move_assign_base &operator=(const expected_move_assign_base &rhs) = default; - expected_move_assign_base& - operator=(expected_move_assign_base&& rhs) noexcept( - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value) { + expected_move_assign_base &operator=( + expected_move_assign_base + &&rhs) noexcept(std::is_nothrow_move_constructible::value && + std::is_nothrow_move_assignable::value) { this->assign(std::move(rhs)); return *this; } @@ -2977,44 +2723,44 @@ template ::value)> struct expected_delete_ctor_base { expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base&) = default; - expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = default; - expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = + expected_delete_ctor_base(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; + expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = + expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = default; }; template struct expected_delete_ctor_base { expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base&) = default; - expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = delete; - expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = + expected_delete_ctor_base(const expected_delete_ctor_base &) = default; + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; + expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = + expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = default; }; template struct expected_delete_ctor_base { expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base&) = delete; - expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = default; - expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = + expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; + expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = + expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = default; }; template struct expected_delete_ctor_base { expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base&) = delete; - expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = delete; - expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = + expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; + expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; + expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = + expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = default; }; @@ -3032,45 +2778,49 @@ template ::value)> struct expected_delete_assign_base { expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base&) = default; - expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default; - expected_delete_assign_base& operator=(const expected_delete_assign_base&) = + expected_delete_assign_base(const expected_delete_assign_base &) = default; + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + expected_delete_assign_base &operator=(const expected_delete_assign_base &) = default; - expected_delete_assign_base& operator=( - expected_delete_assign_base&&) noexcept = default; + expected_delete_assign_base &operator=( + expected_delete_assign_base &&) noexcept = default; }; template struct expected_delete_assign_base { expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base&) = default; - expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default; - expected_delete_assign_base& operator=(const expected_delete_assign_base&) = + expected_delete_assign_base(const expected_delete_assign_base &) = default; + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = default; - expected_delete_assign_base& operator=( - expected_delete_assign_base&&) noexcept = delete; + expected_delete_assign_base &operator=(const expected_delete_assign_base &) = + default; + expected_delete_assign_base &operator=( + expected_delete_assign_base &&) noexcept = delete; }; template struct expected_delete_assign_base { expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base&) = default; - expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default; - expected_delete_assign_base& operator=(const expected_delete_assign_base&) = + expected_delete_assign_base(const expected_delete_assign_base &) = default; + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + expected_delete_assign_base &operator=(const expected_delete_assign_base &) = delete; - expected_delete_assign_base& operator=( - expected_delete_assign_base&&) noexcept = default; + expected_delete_assign_base &operator=( + expected_delete_assign_base &&) noexcept = default; }; template struct expected_delete_assign_base { expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base&) = default; - expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default; - expected_delete_assign_base& operator=(const expected_delete_assign_base&) = + expected_delete_assign_base(const expected_delete_assign_base &) = default; + expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + default; + expected_delete_assign_base &operator=(const expected_delete_assign_base &) = delete; - expected_delete_assign_base& operator=( - expected_delete_assign_base&&) noexcept = delete; + expected_delete_assign_base &operator=( + expected_delete_assign_base &&) noexcept = delete; }; // This is needed to be able to construct the expected_default_ctor_base which @@ -3088,13 +2838,13 @@ template struct expected_default_ctor_base { constexpr expected_default_ctor_base() noexcept = delete; constexpr expected_default_ctor_base( - expected_default_ctor_base const&) noexcept = default; - constexpr expected_default_ctor_base(expected_default_ctor_base&&) noexcept = - default; - expected_default_ctor_base& operator=( - expected_default_ctor_base const&) noexcept = default; - expected_default_ctor_base& operator=(expected_default_ctor_base&&) noexcept = + expected_default_ctor_base const &) noexcept = default; + constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept = default; + expected_default_ctor_base &operator=( + expected_default_ctor_base const &) noexcept = default; + expected_default_ctor_base &operator=( + expected_default_ctor_base &&) noexcept = default; constexpr explicit expected_default_ctor_base(default_constructor_tag) {} }; @@ -3121,14 +2871,14 @@ class bad_expected_access : public std::exception { public: explicit bad_expected_access(E e) : m_val(std::move(e)) {} - virtual const char* what() const noexcept override { + virtual const char *what() const noexcept override { return "Bad expected access"; } - const E& error() const& { return m_val; } - E& error() & { return m_val; } - const E&& error() const&& { return std::move(m_val); } - E&& error() && { return std::move(m_val); } + const E &error() const & { return m_val; } + E &error() & { return m_val; } + const E &&error() const && { return std::move(m_val); } + E &&error() && { return std::move(m_val); } private: E m_val; @@ -3156,26 +2906,26 @@ class expected : private detail::expected_move_assign_base, "T must not be unexpected"); static_assert(!std::is_reference::value, "E must not be a reference"); - T* valptr() { return std::addressof(this->m_val); } - const T* valptr() const { return std::addressof(this->m_val); } - unexpected* errptr() { return std::addressof(this->m_unexpect); } - const unexpected* errptr() const { + T *valptr() { return std::addressof(this->m_val); } + const T *valptr() const { return std::addressof(this->m_val); } + unexpected *errptr() { return std::addressof(this->m_unexpect); } + const unexpected *errptr() const { return std::addressof(this->m_unexpect); } template ::value>* = nullptr> - TL_EXPECTED_11_CONSTEXPR U& val() { + detail::enable_if_t::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &val() { return this->m_val; } - TL_EXPECTED_11_CONSTEXPR unexpected& err() { return this->m_unexpect; } + TL_EXPECTED_11_CONSTEXPR unexpected &err() { return this->m_unexpect; } template ::value>* = nullptr> - constexpr const U& val() const { + detail::enable_if_t::value> * = nullptr> + constexpr const U &val() const { return this->m_val; } - constexpr const unexpected& err() const { return this->m_unexpect; } + constexpr const unexpected &err() const { return this->m_unexpect; } using impl_base = detail::expected_move_assign_base; using ctor_base = detail::expected_default_ctor_base; @@ -3188,46 +2938,46 @@ class expected : private detail::expected_move_assign_base, #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template - TL_EXPECTED_11_CONSTEXPR auto and_then(F&& f) & { + TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & { return and_then_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto and_then(F&& f) && { + TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && { return and_then_impl(std::move(*this), std::forward(f)); } template - constexpr auto and_then(F&& f) const& { + constexpr auto and_then(F &&f) const & { return and_then_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr auto and_then(F&& f) const&& { + constexpr auto and_then(F &&f) const && { return and_then_impl(std::move(*this), std::forward(f)); } #endif #else template - TL_EXPECTED_11_CONSTEXPR auto and_then(F&& f) & -> decltype( - and_then_impl(std::declval(), std::forward(f))) { + TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & -> decltype(and_then_impl( + std::declval(), std::forward(f))) { return and_then_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto and_then(F&& f) && -> decltype( - and_then_impl(std::declval(), std::forward(f))) { + TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && -> decltype(and_then_impl( + std::declval(), std::forward(f))) { return and_then_impl(std::move(*this), std::forward(f)); } template - constexpr auto and_then(F&& f) const& -> decltype( - and_then_impl(std::declval(), std::forward(f))) { + constexpr auto and_then(F &&f) const & -> decltype(and_then_impl( + std::declval(), std::forward(f))) { return and_then_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr auto and_then(F&& f) const&& -> decltype( - and_then_impl(std::declval(), std::forward(f))) { + constexpr auto and_then(F &&f) const && -> decltype(and_then_impl( + std::declval(), std::forward(f))) { return and_then_impl(std::move(*this), std::forward(f)); } #endif @@ -3236,46 +2986,46 @@ class expected : private detail::expected_move_assign_base, #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template - TL_EXPECTED_11_CONSTEXPR auto map(F&& f) & { + TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & { return expected_map_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto map(F&& f) && { + TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && { return expected_map_impl(std::move(*this), std::forward(f)); } template - constexpr auto map(F&& f) const& { + constexpr auto map(F &&f) const & { return expected_map_impl(*this, std::forward(f)); } template - constexpr auto map(F&& f) const&& { + constexpr auto map(F &&f) const && { return expected_map_impl(std::move(*this), std::forward(f)); } #else template - TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), - std::declval())) - map(F&& f) & { + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl( + std::declval(), std::declval())) + map(F &&f) & { return expected_map_impl(*this, std::forward(f)); } template TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), - std::declval())) - map(F&& f) && { + std::declval())) + map(F &&f) && { return expected_map_impl(std::move(*this), std::forward(f)); } template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - map(F&& f) const& { + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + map(F &&f) const & { return expected_map_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - map(F&& f) const&& { + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + map(F &&f) const && { return expected_map_impl(std::move(*this), std::forward(f)); } #endif @@ -3284,46 +3034,46 @@ class expected : private detail::expected_move_assign_base, #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template - TL_EXPECTED_11_CONSTEXPR auto transform(F&& f) & { + TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) & { return expected_map_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto transform(F&& f) && { + TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) && { return expected_map_impl(std::move(*this), std::forward(f)); } template - constexpr auto transform(F&& f) const& { + constexpr auto transform(F &&f) const & { return expected_map_impl(*this, std::forward(f)); } template - constexpr auto transform(F&& f) const&& { + constexpr auto transform(F &&f) const && { return expected_map_impl(std::move(*this), std::forward(f)); } #else template - TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), - std::declval())) - transform(F&& f) & { + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl( + std::declval(), std::declval())) + transform(F &&f) & { return expected_map_impl(*this, std::forward(f)); } template TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), - std::declval())) - transform(F&& f) && { + std::declval())) + transform(F &&f) && { return expected_map_impl(std::move(*this), std::forward(f)); } template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - transform(F&& f) const& { + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + transform(F &&f) const & { return expected_map_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - transform(F&& f) const&& { + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + transform(F &&f) const && { return expected_map_impl(std::move(*this), std::forward(f)); } #endif @@ -3332,46 +3082,46 @@ class expected : private detail::expected_move_assign_base, #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template - TL_EXPECTED_11_CONSTEXPR auto map_error(F&& f) & { + TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & { return map_error_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto map_error(F&& f) && { + TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && { return map_error_impl(std::move(*this), std::forward(f)); } template - constexpr auto map_error(F&& f) const& { + constexpr auto map_error(F &&f) const & { return map_error_impl(*this, std::forward(f)); } template - constexpr auto map_error(F&& f) const&& { + constexpr auto map_error(F &&f) const && { return map_error_impl(std::move(*this), std::forward(f)); } #else template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), - std::declval())) - map_error(F&& f) & { + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) & { return map_error_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), - std::declval())) - map_error(F&& f) && { + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) && { return map_error_impl(std::move(*this), std::forward(f)); } template - constexpr decltype(map_error_impl(std::declval(), - std::declval())) - map_error(F&& f) const& { + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) const & { return map_error_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr decltype(map_error_impl(std::declval(), - std::declval())) - map_error(F&& f) const&& { + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F &&f) const && { return map_error_impl(std::move(*this), std::forward(f)); } #endif @@ -3379,147 +3129,149 @@ class expected : private detail::expected_move_assign_base, #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template - TL_EXPECTED_11_CONSTEXPR auto transform_error(F&& f) & { + TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) & { return map_error_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto transform_error(F&& f) && { + TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) && { return map_error_impl(std::move(*this), std::forward(f)); } template - constexpr auto transform_error(F&& f) const& { + constexpr auto transform_error(F &&f) const & { return map_error_impl(*this, std::forward(f)); } template - constexpr auto transform_error(F&& f) const&& { + constexpr auto transform_error(F &&f) const && { return map_error_impl(std::move(*this), std::forward(f)); } #else template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), - std::declval())) - transform_error(F&& f) & { + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) & { return map_error_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), - std::declval())) - transform_error(F&& f) && { + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) && { return map_error_impl(std::move(*this), std::forward(f)); } template - constexpr decltype(map_error_impl(std::declval(), - std::declval())) - transform_error(F&& f) const& { + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) const & { return map_error_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr decltype(map_error_impl(std::declval(), - std::declval())) - transform_error(F&& f) const&& { + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F &&f) const && { return map_error_impl(std::move(*this), std::forward(f)); } #endif #endif template - expected TL_EXPECTED_11_CONSTEXPR or_else(F&& f) & { + expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & { return or_else_impl(*this, std::forward(f)); } template - expected TL_EXPECTED_11_CONSTEXPR or_else(F&& f) && { + expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && { return or_else_impl(std::move(*this), std::forward(f)); } template - expected constexpr or_else(F&& f) const& { + expected constexpr or_else(F &&f) const & { return or_else_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - expected constexpr or_else(F&& f) const&& { + expected constexpr or_else(F &&f) const && { return or_else_impl(std::move(*this), std::forward(f)); } #endif constexpr expected() = default; - constexpr expected(const expected& rhs) = default; - constexpr expected(expected&& rhs) = default; - expected& operator=(const expected& rhs) = default; - expected& operator=(expected&& rhs) = default; + constexpr expected(const expected &rhs) = default; + constexpr expected(expected &&rhs) = default; + expected &operator=(const expected &rhs) = default; + expected &operator=(expected &&rhs) = default; template ::value>* = + detail::enable_if_t::value> * = nullptr> - constexpr expected(in_place_t, Args&&... args) + constexpr expected(in_place_t, Args &&...args) : impl_base(in_place, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} template &, Args&&...>::value>* = nullptr> - constexpr expected(in_place_t, std::initializer_list il, Args&&... args) + T, std::initializer_list &, Args &&...>::value> * = nullptr> + constexpr expected(in_place_t, std::initializer_list il, Args &&...args) : impl_base(in_place, il, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} - template < - class G = E, - detail::enable_if_t::value>* = nullptr, - detail::enable_if_t::value>* = nullptr> - explicit constexpr expected(const unexpected& e) + template ::value> * = + nullptr, + detail::enable_if_t::value> * = + nullptr> + explicit constexpr expected(const unexpected &e) : impl_base(unexpect, e.value()), ctor_base(detail::default_constructor_tag{}) {} template < class G = E, - detail::enable_if_t::value>* = nullptr, - detail::enable_if_t::value>* = nullptr> - constexpr expected(unexpected const& e) + detail::enable_if_t::value> * = + nullptr, + detail::enable_if_t::value> * = nullptr> + constexpr expected(unexpected const &e) : impl_base(unexpect, e.value()), ctor_base(detail::default_constructor_tag{}) {} template < class G = E, - detail::enable_if_t::value>* = nullptr, - detail::enable_if_t::value>* = nullptr> - explicit constexpr expected(unexpected&& e) noexcept( - std::is_nothrow_constructible::value) + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t::value> * = nullptr> + explicit constexpr expected(unexpected &&e) noexcept( + std::is_nothrow_constructible::value) : impl_base(unexpect, std::move(e.value())), ctor_base(detail::default_constructor_tag{}) {} template < class G = E, - detail::enable_if_t::value>* = nullptr, - detail::enable_if_t::value>* = nullptr> - constexpr expected(unexpected&& e) noexcept( - std::is_nothrow_constructible::value) + detail::enable_if_t::value> * = nullptr, + detail::enable_if_t::value> * = nullptr> + constexpr expected(unexpected &&e) noexcept( + std::is_nothrow_constructible::value) : impl_base(unexpect, std::move(e.value())), ctor_base(detail::default_constructor_tag{}) {} template ::value>* = + detail::enable_if_t::value> * = nullptr> - constexpr explicit expected(unexpect_t, Args&&... args) + constexpr explicit expected(unexpect_t, Args &&...args) : impl_base(unexpect, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} template &, Args&&...>::value>* = nullptr> + E, std::initializer_list &, Args &&...>::value> * = nullptr> constexpr explicit expected(unexpect_t, std::initializer_list il, - Args&&... args) + Args &&...args) : impl_base(unexpect, il, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} template ::value && - std::is_convertible::value)>* = + detail::enable_if_t::value && + std::is_convertible::value)> * = nullptr, - detail::expected_enable_from_other* = nullptr> - explicit TL_EXPECTED_11_CONSTEXPR expected(const expected& rhs) + detail::expected_enable_from_other + * = nullptr> + explicit TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) : ctor_base(detail::default_constructor_tag{}) { if (rhs.has_value()) { this->construct(*rhs); @@ -3528,13 +3280,13 @@ class expected : private detail::expected_move_assign_base, } } - template < - class U, class G, - detail::enable_if_t<(std::is_convertible::value && - std::is_convertible::value)>* = nullptr, - detail::expected_enable_from_other* = - nullptr> - TL_EXPECTED_11_CONSTEXPR expected(const expected& rhs) + template ::value && + std::is_convertible::value)> * = + nullptr, + detail::expected_enable_from_other + * = nullptr> + TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) : ctor_base(detail::default_constructor_tag{}) { if (rhs.has_value()) { this->construct(*rhs); @@ -3545,10 +3297,10 @@ class expected : private detail::expected_move_assign_base, template < class U, class G, - detail::enable_if_t::value && - std::is_convertible::value)>* = nullptr, - detail::expected_enable_from_other* = nullptr> - explicit TL_EXPECTED_11_CONSTEXPR expected(expected&& rhs) + detail::enable_if_t::value && + std::is_convertible::value)> * = nullptr, + detail::expected_enable_from_other * = nullptr> + explicit TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) : ctor_base(detail::default_constructor_tag{}) { if (rhs.has_value()) { this->construct(std::move(*rhs)); @@ -3559,10 +3311,10 @@ class expected : private detail::expected_move_assign_base, template < class U, class G, - detail::enable_if_t<(std::is_convertible::value && - std::is_convertible::value)>* = nullptr, - detail::expected_enable_from_other* = nullptr> - TL_EXPECTED_11_CONSTEXPR expected(expected&& rhs) + detail::enable_if_t<(std::is_convertible::value && + std::is_convertible::value)> * = nullptr, + detail::expected_enable_from_other * = nullptr> + TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) : ctor_base(detail::default_constructor_tag{}) { if (rhs.has_value()) { this->construct(std::move(*rhs)); @@ -3571,31 +3323,33 @@ class expected : private detail::expected_move_assign_base, } } - template ::value>* = nullptr, - detail::expected_enable_forward_value* = nullptr> - explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U&& v) + template < + class U = T, + detail::enable_if_t::value> * = nullptr, + detail::expected_enable_forward_value * = nullptr> + explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) : expected(in_place, std::forward(v)) {} - template ::value>* = nullptr, - detail::expected_enable_forward_value* = nullptr> - TL_EXPECTED_MSVC2015_CONSTEXPR expected(U&& v) + template < + class U = T, + detail::enable_if_t::value> * = nullptr, + detail::expected_enable_forward_value * = nullptr> + TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) : expected(in_place, std::forward(v)) {} template < class U = T, class G = T, - detail::enable_if_t::value>* = + detail::enable_if_t::value> * = nullptr, - detail::enable_if_t::value>* = nullptr, + detail::enable_if_t::value> * = nullptr, detail::enable_if_t< (!std::is_same, detail::decay_t>::value && !detail::conjunction, std::is_same>>::value && std::is_constructible::value && - std::is_assignable::value && - std::is_nothrow_move_constructible::value)>* = nullptr> - expected& operator=(U&& v) { + std::is_assignable::value && + std::is_nothrow_move_constructible::value)> * = nullptr> + expected &operator=(U &&v) { if (has_value()) { val() = std::forward(v); } else { @@ -3609,17 +3363,17 @@ class expected : private detail::expected_move_assign_base, template < class U = T, class G = T, - detail::enable_if_t::value>* = + detail::enable_if_t::value> * = nullptr, - detail::enable_if_t::value>* = nullptr, + detail::enable_if_t::value> * = nullptr, detail::enable_if_t< (!std::is_same, detail::decay_t>::value && !detail::conjunction, std::is_same>>::value && std::is_constructible::value && - std::is_assignable::value && - std::is_nothrow_move_constructible::value)>* = nullptr> - expected& operator=(U&& v) { + std::is_assignable::value && + std::is_nothrow_move_constructible::value)> * = nullptr> + expected &operator=(U &&v) { if (has_value()) { val() = std::forward(v); } else { @@ -3645,8 +3399,8 @@ class expected : private detail::expected_move_assign_base, template ::value && - std::is_assignable::value>* = nullptr> - expected& operator=(const unexpected& rhs) { + std::is_assignable::value> * = nullptr> + expected &operator=(const unexpected &rhs) { if (!has_value()) { err() = rhs; } else { @@ -3660,8 +3414,8 @@ class expected : private detail::expected_move_assign_base, template ::value && - std::is_move_assignable::value>* = nullptr> - expected& operator=(unexpected&& rhs) noexcept { + std::is_move_assignable::value> * = nullptr> + expected &operator=(unexpected &&rhs) noexcept { if (!has_value()) { err() = std::move(rhs); } else { @@ -3674,8 +3428,8 @@ class expected : private detail::expected_move_assign_base, } template ::value>* = nullptr> - void emplace(Args&&... args) { + T, Args &&...>::value> * = nullptr> + void emplace(Args &&...args) { if (has_value()) { val().~T(); } else { @@ -3686,8 +3440,8 @@ class expected : private detail::expected_move_assign_base, } template ::value>* = nullptr> - void emplace(Args&&... args) { + T, Args &&...>::value> * = nullptr> + void emplace(Args &&...args) { if (has_value()) { val().~T(); ::new (valptr()) T(std::forward(args)...); @@ -3712,8 +3466,8 @@ class expected : private detail::expected_move_assign_base, template &, Args&&...>::value>* = nullptr> - void emplace(std::initializer_list il, Args&&... args) { + T, std::initializer_list &, Args &&...>::value> * = nullptr> + void emplace(std::initializer_list il, Args &&...args) { if (has_value()) { T t(il, std::forward(args)...); val() = std::move(t); @@ -3726,8 +3480,8 @@ class expected : private detail::expected_move_assign_base, template &, Args&&...>::value>* = nullptr> - void emplace(std::initializer_list il, Args&&... args) { + T, std::initializer_list &, Args &&...>::value> * = nullptr> + void emplace(std::initializer_list il, Args &&...args) { if (has_value()) { T t(il, std::forward(args)...); val() = std::move(t); @@ -3758,30 +3512,30 @@ class expected : private detail::expected_move_assign_base, using e_is_nothrow_move_constructible = std::true_type; using move_constructing_e_can_throw = std::false_type; - void swap_where_both_have_value(expected& /*rhs*/, t_is_void) noexcept { + void swap_where_both_have_value(expected & /*rhs*/, t_is_void) noexcept { // swapping void is a no-op } - void swap_where_both_have_value(expected& rhs, t_is_not_void) { + void swap_where_both_have_value(expected &rhs, t_is_not_void) { using std::swap; swap(val(), rhs.val()); } - void swap_where_only_one_has_value(expected& rhs, t_is_void) noexcept( + void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept( std::is_nothrow_move_constructible::value) { ::new (errptr()) unexpected_type(std::move(rhs.err())); rhs.err().~unexpected_type(); std::swap(this->m_has_val, rhs.m_has_val); } - void swap_where_only_one_has_value(expected& rhs, t_is_not_void) { + void swap_where_only_one_has_value(expected &rhs, t_is_not_void) { swap_where_only_one_has_value_and_t_is_not_void( rhs, typename std::is_nothrow_move_constructible::type{}, typename std::is_nothrow_move_constructible::type{}); } void swap_where_only_one_has_value_and_t_is_not_void( - expected& rhs, t_is_nothrow_move_constructible, + expected &rhs, t_is_nothrow_move_constructible, e_is_nothrow_move_constructible) noexcept { auto temp = std::move(val()); val().~T(); @@ -3792,7 +3546,7 @@ class expected : private detail::expected_move_assign_base, } void swap_where_only_one_has_value_and_t_is_not_void( - expected& rhs, t_is_nothrow_move_constructible, + expected &rhs, t_is_nothrow_move_constructible, move_constructing_e_can_throw) { auto temp = std::move(val()); val().~T(); @@ -3815,7 +3569,7 @@ class expected : private detail::expected_move_assign_base, } void swap_where_only_one_has_value_and_t_is_not_void( - expected& rhs, move_constructing_t_can_throw, + expected &rhs, move_constructing_t_can_throw, e_is_nothrow_move_constructible) { auto temp = std::move(rhs.err()); rhs.err().~unexpected_type(); @@ -3843,11 +3597,10 @@ class expected : private detail::expected_move_assign_base, detail::is_swappable::value && (std::is_nothrow_move_constructible::value || std::is_nothrow_move_constructible::value)> - swap(expected& rhs) noexcept( - std::is_nothrow_move_constructible::value&& - detail::is_nothrow_swappable::value&& - std::is_nothrow_move_constructible::value&& - detail::is_nothrow_swappable::value) { + swap(expected &rhs) noexcept(std::is_nothrow_move_constructible::value && + detail::is_nothrow_swappable::value && + std::is_nothrow_move_constructible::value && + detail::is_nothrow_swappable::value) { if (has_value() && rhs.has_value()) { swap_where_both_have_value(rhs, typename std::is_void::type{}); } else if (!has_value() && rhs.has_value()) { @@ -3860,36 +3613,36 @@ class expected : private detail::expected_move_assign_base, } } - constexpr const T* operator->() const { + constexpr const T *operator->() const { TL_ASSERT(has_value()); return valptr(); } - TL_EXPECTED_11_CONSTEXPR T* operator->() { + TL_EXPECTED_11_CONSTEXPR T *operator->() { TL_ASSERT(has_value()); return valptr(); } template ::value>* = nullptr> - constexpr const U& operator*() const& { + detail::enable_if_t::value> * = nullptr> + constexpr const U &operator*() const & { TL_ASSERT(has_value()); return val(); } template ::value>* = nullptr> - TL_EXPECTED_11_CONSTEXPR U& operator*() & { + detail::enable_if_t::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &operator*() & { TL_ASSERT(has_value()); return val(); } template ::value>* = nullptr> - constexpr const U&& operator*() const&& { + detail::enable_if_t::value> * = nullptr> + constexpr const U &&operator*() const && { TL_ASSERT(has_value()); return std::move(val()); } template ::value>* = nullptr> - TL_EXPECTED_11_CONSTEXPR U&& operator*() && { + detail::enable_if_t::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &&operator*() && { TL_ASSERT(has_value()); return std::move(val()); } @@ -3898,62 +3651,62 @@ class expected : private detail::expected_move_assign_base, constexpr explicit operator bool() const noexcept { return this->m_has_val; } template ::value>* = nullptr> - TL_EXPECTED_11_CONSTEXPR const U& value() const& { + detail::enable_if_t::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR const U &value() const & { if (!has_value()) detail::throw_exception(bad_expected_access(err().value())); return val(); } template ::value>* = nullptr> - TL_EXPECTED_11_CONSTEXPR U& value() & { + detail::enable_if_t::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &value() & { if (!has_value()) detail::throw_exception(bad_expected_access(err().value())); return val(); } template ::value>* = nullptr> - TL_EXPECTED_11_CONSTEXPR const U&& value() const&& { + detail::enable_if_t::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR const U &&value() const && { if (!has_value()) detail::throw_exception(bad_expected_access(std::move(err()).value())); return std::move(val()); } template ::value>* = nullptr> - TL_EXPECTED_11_CONSTEXPR U&& value() && { + detail::enable_if_t::value> * = nullptr> + TL_EXPECTED_11_CONSTEXPR U &&value() && { if (!has_value()) detail::throw_exception(bad_expected_access(std::move(err()).value())); return std::move(val()); } - constexpr const E& error() const& { + constexpr const E &error() const & { TL_ASSERT(!has_value()); return err().value(); } - TL_EXPECTED_11_CONSTEXPR E& error() & { + TL_EXPECTED_11_CONSTEXPR E &error() & { TL_ASSERT(!has_value()); return err().value(); } - constexpr const E&& error() const&& { + constexpr const E &&error() const && { TL_ASSERT(!has_value()); return std::move(err().value()); } - TL_EXPECTED_11_CONSTEXPR E&& error() && { + TL_EXPECTED_11_CONSTEXPR E &&error() && { TL_ASSERT(!has_value()); return std::move(err().value()); } template - constexpr T value_or(U&& v) const& { + constexpr T value_or(U &&v) const & { static_assert(std::is_copy_constructible::value && - std::is_convertible::value, + std::is_convertible::value, "T must be copy-constructible and convertible to from U&&"); return bool(*this) ? **this : static_cast(std::forward(v)); } template - TL_EXPECTED_11_CONSTEXPR T value_or(U&& v) && { + TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) && { static_assert(std::is_move_constructible::value && - std::is_convertible::value, + std::is_convertible::value, "T must be move-constructible and convertible to from U&&"); return bool(*this) ? std::move(**this) : static_cast(std::forward(v)); } @@ -3969,10 +3722,10 @@ using ret_t = expected>; #ifdef TL_EXPECTED_CXX14 template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval()))> -constexpr auto and_then_impl(Exp&& exp, F&& f) { +constexpr auto and_then_impl(Exp &&exp, F &&f) { static_assert(detail::is_expected::value, "F must return an expected"); return exp.has_value() @@ -3981,9 +3734,9 @@ constexpr auto and_then_impl(Exp&& exp, F&& f) { } template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval()))> -constexpr auto and_then_impl(Exp&& exp, F&& f) { +constexpr auto and_then_impl(Exp &&exp, F &&f) { static_assert(detail::is_expected::value, "F must return an expected"); return exp.has_value() ? detail::invoke(std::forward(f)) @@ -3995,8 +3748,8 @@ struct TC; template (), *std::declval())), - detail::enable_if_t>::value>* = nullptr> -auto and_then_impl(Exp&& exp, F&& f) -> Ret { + detail::enable_if_t>::value> * = nullptr> +auto and_then_impl(Exp &&exp, F &&f) -> Ret { static_assert(detail::is_expected::value, "F must return an expected"); return exp.has_value() @@ -4006,8 +3759,8 @@ auto and_then_impl(Exp&& exp, F&& f) -> Ret { template ())), - detail::enable_if_t>::value>* = nullptr> -constexpr auto and_then_impl(Exp&& exp, F&& f) -> Ret { + detail::enable_if_t>::value> * = nullptr> +constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret { static_assert(detail::is_expected::value, "F must return an expected"); return exp.has_value() ? detail::invoke(std::forward(f)) @@ -4017,11 +3770,11 @@ constexpr auto and_then_impl(Exp&& exp, F&& f) -> Ret { #ifdef TL_EXPECTED_CXX14 template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval())), - detail::enable_if_t::value>* = nullptr> -constexpr auto expected_map_impl(Exp&& exp, F&& f) { + detail::enable_if_t::value> * = nullptr> +constexpr auto expected_map_impl(Exp &&exp, F &&f) { using result = ret_t>; return exp.has_value() ? result(detail::invoke(std::forward(f), *std::forward(exp))) @@ -4029,11 +3782,11 @@ constexpr auto expected_map_impl(Exp&& exp, F&& f) { } template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval())), - detail::enable_if_t::value>* = nullptr> -auto expected_map_impl(Exp&& exp, F&& f) { + detail::enable_if_t::value> * = nullptr> +auto expected_map_impl(Exp &&exp, F &&f) { using result = expected>; if (exp.has_value()) { detail::invoke(std::forward(f), *std::forward(exp)); @@ -4044,20 +3797,20 @@ auto expected_map_impl(Exp&& exp, F&& f) { } template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value>* = nullptr> -constexpr auto expected_map_impl(Exp&& exp, F&& f) { + detail::enable_if_t::value> * = nullptr> +constexpr auto expected_map_impl(Exp &&exp, F &&f) { using result = ret_t>; return exp.has_value() ? result(detail::invoke(std::forward(f))) : result(unexpect, std::forward(exp).error()); } template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value>* = nullptr> -auto expected_map_impl(Exp&& exp, F&& f) { + detail::enable_if_t::value> * = nullptr> +auto expected_map_impl(Exp &&exp, F &&f) { using result = expected>; if (exp.has_value()) { detail::invoke(std::forward(f)); @@ -4068,12 +3821,12 @@ auto expected_map_impl(Exp&& exp, F&& f) { } #else template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval())), - detail::enable_if_t::value>* = nullptr> + detail::enable_if_t::value> * = nullptr> -constexpr auto expected_map_impl(Exp&& exp, F&& f) +constexpr auto expected_map_impl(Exp &&exp, F &&f) -> ret_t> { using result = ret_t>; @@ -4083,12 +3836,12 @@ constexpr auto expected_map_impl(Exp&& exp, F&& f) } template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval())), - detail::enable_if_t::value>* = nullptr> + detail::enable_if_t::value> * = nullptr> -auto expected_map_impl(Exp&& exp, F&& f) -> expected> { +auto expected_map_impl(Exp &&exp, F &&f) -> expected> { if (exp.has_value()) { detail::invoke(std::forward(f), *std::forward(exp)); return {}; @@ -4098,11 +3851,11 @@ auto expected_map_impl(Exp&& exp, F&& f) -> expected> { } template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value>* = nullptr> + detail::enable_if_t::value> * = nullptr> -constexpr auto expected_map_impl(Exp&& exp, F&& f) +constexpr auto expected_map_impl(Exp &&exp, F &&f) -> ret_t> { using result = ret_t>; @@ -4111,11 +3864,11 @@ constexpr auto expected_map_impl(Exp&& exp, F&& f) } template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value>* = nullptr> + detail::enable_if_t::value> * = nullptr> -auto expected_map_impl(Exp&& exp, F&& f) -> expected> { +auto expected_map_impl(Exp &&exp, F &&f) -> expected> { if (exp.has_value()) { detail::invoke(std::forward(f)); return {}; @@ -4128,11 +3881,11 @@ auto expected_map_impl(Exp&& exp, F&& f) -> expected> { #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value>* = nullptr> -constexpr auto map_error_impl(Exp&& exp, F&& f) { + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) { using result = expected, detail::decay_t>; return exp.has_value() ? result(*std::forward(exp)) @@ -4140,11 +3893,11 @@ constexpr auto map_error_impl(Exp&& exp, F&& f) { std::forward(exp).error())); } template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value>* = nullptr> -auto map_error_impl(Exp&& exp, F&& f) { + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) { using result = expected, monostate>; if (exp.has_value()) { return result(*std::forward(exp)); @@ -4154,11 +3907,11 @@ auto map_error_impl(Exp&& exp, F&& f) { return result(unexpect, monostate{}); } template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value>* = nullptr> -constexpr auto map_error_impl(Exp&& exp, F&& f) { + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) { using result = expected, detail::decay_t>; return exp.has_value() ? result() @@ -4166,11 +3919,11 @@ constexpr auto map_error_impl(Exp&& exp, F&& f) { std::forward(exp).error())); } template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value>* = nullptr> -auto map_error_impl(Exp&& exp, F&& f) { + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) { using result = expected, monostate>; if (exp.has_value()) { return result(); @@ -4181,11 +3934,11 @@ auto map_error_impl(Exp&& exp, F&& f) { } #else template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value>* = nullptr> -constexpr auto map_error_impl(Exp&& exp, F&& f) + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) -> expected, detail::decay_t> { using result = expected, detail::decay_t>; @@ -4196,11 +3949,11 @@ constexpr auto map_error_impl(Exp&& exp, F&& f) } template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value>* = nullptr> -auto map_error_impl(Exp&& exp, F&& f) -> expected, monostate> { + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { using result = expected, monostate>; if (exp.has_value()) { return result(*std::forward(exp)); @@ -4211,11 +3964,11 @@ auto map_error_impl(Exp&& exp, F&& f) -> expected, monostate> { } template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value>* = nullptr> -constexpr auto map_error_impl(Exp&& exp, F&& f) + detail::enable_if_t::value> * = nullptr> +constexpr auto map_error_impl(Exp &&exp, F &&f) -> expected, detail::decay_t> { using result = expected, detail::decay_t>; @@ -4226,11 +3979,11 @@ constexpr auto map_error_impl(Exp&& exp, F&& f) } template >::value>* = nullptr, + detail::enable_if_t>::value> * = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value>* = nullptr> -auto map_error_impl(Exp&& exp, F&& f) -> expected, monostate> { + detail::enable_if_t::value> * = nullptr> +auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { using result = expected, monostate>; if (exp.has_value()) { return result(); @@ -4245,8 +3998,8 @@ auto map_error_impl(Exp&& exp, F&& f) -> expected, monostate> { template (), std::declval().error())), - detail::enable_if_t::value>* = nullptr> -constexpr auto or_else_impl(Exp&& exp, F&& f) { + detail::enable_if_t::value> * = nullptr> +constexpr auto or_else_impl(Exp &&exp, F &&f) { static_assert(detail::is_expected::value, "F must return an expected"); return exp.has_value() ? std::forward(exp) : detail::invoke(std::forward(f), @@ -4256,8 +4009,8 @@ constexpr auto or_else_impl(Exp&& exp, F&& f) { template (), std::declval().error())), - detail::enable_if_t::value>* = nullptr> -detail::decay_t or_else_impl(Exp&& exp, F&& f) { + detail::enable_if_t::value> * = nullptr> +detail::decay_t or_else_impl(Exp &&exp, F &&f) { return exp.has_value() ? std::forward(exp) : (detail::invoke(std::forward(f), std::forward(exp).error()), @@ -4267,8 +4020,8 @@ detail::decay_t or_else_impl(Exp&& exp, F&& f) { template (), std::declval().error())), - detail::enable_if_t::value>* = nullptr> -auto or_else_impl(Exp&& exp, F&& f) -> Ret { + detail::enable_if_t::value> * = nullptr> +auto or_else_impl(Exp &&exp, F &&f) -> Ret { static_assert(detail::is_expected::value, "F must return an expected"); return exp.has_value() ? std::forward(exp) : detail::invoke(std::forward(f), @@ -4278,8 +4031,8 @@ auto or_else_impl(Exp&& exp, F&& f) -> Ret { template (), std::declval().error())), - detail::enable_if_t::value>* = nullptr> -detail::decay_t or_else_impl(Exp&& exp, F&& f) { + detail::enable_if_t::value> * = nullptr> +detail::decay_t or_else_impl(Exp &&exp, F &&f) { return exp.has_value() ? std::forward(exp) : (detail::invoke(std::forward(f), std::forward(exp).error()), @@ -4289,65 +4042,65 @@ detail::decay_t or_else_impl(Exp&& exp, F&& f) { } // namespace detail template -constexpr bool operator==(const expected& lhs, - const expected& rhs) { +constexpr bool operator==(const expected &lhs, + const expected &rhs) { return (lhs.has_value() != rhs.has_value()) ? false : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs); } template -constexpr bool operator!=(const expected& lhs, - const expected& rhs) { +constexpr bool operator!=(const expected &lhs, + const expected &rhs) { return (lhs.has_value() != rhs.has_value()) ? true : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs); } template -constexpr bool operator==(const expected& lhs, - const expected& rhs) { +constexpr bool operator==(const expected &lhs, + const expected &rhs) { return (lhs.has_value() != rhs.has_value()) ? false : (!lhs.has_value() ? lhs.error() == rhs.error() : true); } template -constexpr bool operator!=(const expected& lhs, - const expected& rhs) { +constexpr bool operator!=(const expected &lhs, + const expected &rhs) { return (lhs.has_value() != rhs.has_value()) ? true : (!lhs.has_value() ? lhs.error() == rhs.error() : false); } template -constexpr bool operator==(const expected& x, const U& v) { +constexpr bool operator==(const expected &x, const U &v) { return x.has_value() ? *x == v : false; } template -constexpr bool operator==(const U& v, const expected& x) { +constexpr bool operator==(const U &v, const expected &x) { return x.has_value() ? *x == v : false; } template -constexpr bool operator!=(const expected& x, const U& v) { +constexpr bool operator!=(const expected &x, const U &v) { return x.has_value() ? *x != v : true; } template -constexpr bool operator!=(const U& v, const expected& x) { +constexpr bool operator!=(const U &v, const expected &x) { return x.has_value() ? *x != v : true; } template -constexpr bool operator==(const expected& x, const unexpected& e) { +constexpr bool operator==(const expected &x, const unexpected &e) { return x.has_value() ? false : x.error() == e.value(); } template -constexpr bool operator==(const unexpected& e, const expected& x) { +constexpr bool operator==(const unexpected &e, const expected &x) { return x.has_value() ? false : x.error() == e.value(); } template -constexpr bool operator!=(const expected& x, const unexpected& e) { +constexpr bool operator!=(const expected &x, const unexpected &e) { return x.has_value() ? true : x.error() != e.value(); } template -constexpr bool operator!=(const unexpected& e, const expected& x) { +constexpr bool operator!=(const unexpected &e, const expected &x) { return x.has_value() ? true : x.error() != e.value(); } @@ -4356,9 +4109,9 @@ template ::value) && detail::is_swappable::value && std::is_move_constructible::value && - detail::is_swappable::value>* = nullptr> -void swap(expected& lhs, - expected& rhs) noexcept(noexcept(lhs.swap(rhs))) { + detail::is_swappable::value> * = nullptr> +void swap(expected &lhs, + expected &rhs) noexcept(noexcept(lhs.swap(rhs))) { lhs.swap(rhs); } } // namespace tl @@ -4366,16 +4119,236 @@ void swap(expected& lhs, #endif /* end file include/ada/expected.h */ +/* begin file include/ada/url_pattern_regex.h */ /** - * @private + * @file url_search_params.h + * @brief Declaration for the URL Search Params */ -namespace ada { -struct url_aggregator; -struct url; -} // namespace ada +#ifndef ADA_URL_PATTERN_REGEX_H +#define ADA_URL_PATTERN_REGEX_H -/** - * @namespace ada::parser +#include +#include + +#ifdef ADA_USE_UNSAFE_STD_REGEX_PROVIDER +#include +#endif // ADA_USE_UNSAFE_STD_REGEX_PROVIDER + +#if ADA_INCLUDE_URL_PATTERN +namespace ada::url_pattern_regex { + +template +concept regex_concept = requires(T t, std::string_view pattern, + bool ignore_case, std::string_view input) { + // Ensure the class has a type alias 'regex_type' + typename T::regex_type; + + // Function to create a regex instance + { + T::create_instance(pattern, ignore_case) + } -> std::same_as>; + + // Function to perform regex search + { + T::regex_search(input, std::declval()) + } -> std::same_as>>>; + + // Function to match regex pattern + { + T::regex_match(input, std::declval()) + } -> std::same_as; + + // Copy constructor + { T(std::declval()) } -> std::same_as; + + // Move constructor + { T(std::declval()) } -> std::same_as; +}; + +#ifdef ADA_USE_UNSAFE_STD_REGEX_PROVIDER +class std_regex_provider final { + public: + std_regex_provider() = default; + using regex_type = std::regex; + static std::optional create_instance(std::string_view pattern, + bool ignore_case); + static std::optional>> regex_search( + std::string_view input, const regex_type& pattern); + static bool regex_match(std::string_view input, const regex_type& pattern); +}; +#endif // ADA_USE_UNSAFE_STD_REGEX_PROVIDER + +} // namespace ada::url_pattern_regex +#endif // ADA_INCLUDE_URL_PATTERN +#endif // ADA_URL_PATTERN_REGEX_H +/* end file include/ada/url_pattern_regex.h */ +/* begin file include/ada/url_pattern_init.h */ +/** + * @file url_pattern_init.h + * @brief Declaration for the url_pattern_init implementation. + */ +#ifndef ADA_URL_PATTERN_INIT_H +#define ADA_URL_PATTERN_INIT_H + +/* begin file include/ada/errors.h */ +/** + * @file errors.h + * @brief Definitions for the errors. + */ +#ifndef ADA_ERRORS_H +#define ADA_ERRORS_H + +#include +namespace ada { +enum class errors : uint8_t { type_error }; +} // namespace ada +#endif // ADA_ERRORS_H +/* end file include/ada/errors.h */ + +#include +#include +#include +#include + +#if ADA_TESTING +#include +#endif // ADA_TESTING + +#if ADA_INCLUDE_URL_PATTERN +namespace ada { + +// Important: C++20 allows us to use concept rather than `using` or `typedef +// and allows functions with second argument, which is optional (using either +// std::nullopt or a parameter with default value) +template +concept url_pattern_encoding_callback = requires(F f, std::string_view sv) { + { f(sv) } -> std::same_as>; +}; + +// A structure providing matching patterns for individual components +// of a URL. When a URLPattern is created, or when a URLPattern is +// used to match or test against a URL, the input can be given as +// either a string or a URLPatternInit struct. If a string is given, +// it will be parsed to create a URLPatternInit. The URLPatternInit +// API is defined as part of the URLPattern specification. +// All provided strings must be valid UTF-8. +struct url_pattern_init { + enum class process_type : uint8_t { + url, + pattern, + }; + + friend std::ostream& operator<<(std::ostream& os, process_type type) { + switch (type) { + case process_type::url: + return os << "url"; + case process_type::pattern: + return os << "pattern"; + default: + return os << "unknown"; + } + } + + // All strings must be valid UTF-8. + // @see https://urlpattern.spec.whatwg.org/#process-a-urlpatterninit + static tl::expected process( + const url_pattern_init& init, process_type type, + std::optional protocol = std::nullopt, + std::optional username = std::nullopt, + std::optional password = std::nullopt, + std::optional hostname = std::nullopt, + std::optional port = std::nullopt, + std::optional pathname = std::nullopt, + std::optional search = std::nullopt, + std::optional hash = std::nullopt); + + // @see https://urlpattern.spec.whatwg.org/#process-protocol-for-init + static tl::expected process_protocol( + std::string_view value, process_type type); + + // @see https://urlpattern.spec.whatwg.org/#process-username-for-init + static tl::expected process_username( + std::string_view value, process_type type); + + // @see https://urlpattern.spec.whatwg.org/#process-password-for-init + static tl::expected process_password( + std::string_view value, process_type type); + + // @see https://urlpattern.spec.whatwg.org/#process-hostname-for-init + static tl::expected process_hostname( + std::string_view value, process_type type); + + // @see https://urlpattern.spec.whatwg.org/#process-port-for-init + static tl::expected process_port( + std::string_view port, std::string_view protocol, process_type type); + + // @see https://urlpattern.spec.whatwg.org/#process-pathname-for-init + static tl::expected process_pathname( + std::string_view value, std::string_view protocol, process_type type); + + // @see https://urlpattern.spec.whatwg.org/#process-search-for-init + static tl::expected process_search( + std::string_view value, process_type type); + + // @see https://urlpattern.spec.whatwg.org/#process-hash-for-init + static tl::expected process_hash(std::string_view value, + process_type type); + +#if ADA_TESTING + friend void PrintTo(const url_pattern_init& init, std::ostream* os) { + *os << "protocol: '" << init.protocol.value_or("undefined") << "', "; + *os << "username: '" << init.username.value_or("undefined") << "', "; + *os << "password: '" << init.password.value_or("undefined") << "', "; + *os << "hostname: '" << init.hostname.value_or("undefined") << "', "; + *os << "port: '" << init.port.value_or("undefined") << "', "; + *os << "pathname: '" << init.pathname.value_or("undefined") << "', "; + *os << "search: '" << init.search.value_or("undefined") << "', "; + *os << "hash: '" << init.hash.value_or("undefined") << "', "; + *os << "base_url: '" << init.base_url.value_or("undefined") << "', "; + } +#endif // ADA_TESTING + + bool operator==(const url_pattern_init&) const; + // If present, must be valid UTF-8. + std::optional protocol{}; + // If present, must be valid UTF-8. + std::optional username{}; + // If present, must be valid UTF-8. + std::optional password{}; + // If present, must be valid UTF-8. + std::optional hostname{}; + // If present, must be valid UTF-8. + std::optional port{}; + // If present, must be valid UTF-8. + std::optional pathname{}; + // If present, must be valid UTF-8. + std::optional search{}; + // If present, must be valid UTF-8. + std::optional hash{}; + // If present, must be valid UTF-8. + std::optional base_url{}; +}; +} // namespace ada +#endif // ADA_INCLUDE_URL_PATTERN +#endif // ADA_URL_PATTERN_INIT_H +/* end file include/ada/url_pattern_init.h */ + +/** + * @private + */ +namespace ada { +struct url_aggregator; +struct url; +#if ADA_INCLUDE_URL_PATTERN +template +class url_pattern; +struct url_pattern_options; +#endif // ADA_INCLUDE_URL_PATTERN +enum class errors : uint8_t; +} // namespace ada + +/** + * @namespace ada::parser * @brief Includes the definitions for supported parsers */ namespace ada::parser { @@ -4385,7 +4358,7 @@ namespace ada::parser { * parameter that can be used to resolve relative URLs. If the base_url is * provided, the user_input is resolved against the base_url. */ -template +template result_type parse_url(std::string_view user_input, const result_type* base_url = nullptr); @@ -4394,7 +4367,7 @@ extern template url_aggregator parse_url( extern template url parse_url(std::string_view user_input, const url* base_url); -template +template result_type parse_url_impl(std::string_view user_input, const result_type* base_url = nullptr); @@ -4402,507 +4375,496 @@ extern template url_aggregator parse_url_impl( std::string_view user_input, const url_aggregator* base_url); extern template url parse_url_impl(std::string_view user_input, const url* base_url); + +#if ADA_INCLUDE_URL_PATTERN +template +tl::expected, errors> parse_url_pattern_impl( + std::variant&& input, + const std::string_view* base_url, const url_pattern_options* options); +#endif // ADA_INCLUDE_URL_PATTERN + } // namespace ada::parser #endif // ADA_PARSER_H /* end file include/ada/parser.h */ -/* begin file include/ada/scheme-inl.h */ +/* begin file include/ada/parser-inl.h */ /** - * @file scheme-inl.h - * @brief Definitions for the URL scheme. + * @file parser-inl.h */ -#ifndef ADA_SCHEME_INL_H -#define ADA_SCHEME_INL_H - -namespace ada::scheme { +#ifndef ADA_PARSER_INL_H +#define ADA_PARSER_INL_H +/* begin file include/ada/url_pattern.h */ /** - * @namespace ada::scheme::details - * @brief Includes the definitions for scheme specific entities + * @file url_pattern.h + * @brief Declaration for the URLPattern implementation. */ -namespace details { -// for use with is_special and get_special_port -// Spaces, if present, are removed from URL. -constexpr std::string_view is_special_list[] = {"http", " ", "https", "ws", - "ftp", "wss", "file", " "}; -// for use with get_special_port -constexpr uint16_t special_ports[] = {80, 0, 443, 80, 21, 443, 0, 0}; -} // namespace details - -/**** - * @private - * In is_special, get_scheme_type, and get_special_port, we - * use a standard hashing technique to find the index of the scheme in - * the is_special_list. The hashing technique is based on the size of - * the scheme and the first character of the scheme. It ensures that we - * do at most one string comparison per call. If the protocol is - * predictible (e.g., it is always "http"), we can get a better average - * performance by using a simpler approach where we loop and compare - * scheme with all possible protocols starting with the most likely - * protocol. Doing multiple comparisons may have a poor worst case - * performance, however. In this instance, we choose a potentially - * slightly lower best-case performance for a better worst-case - * performance. We can revisit this choice at any time. - * - * Reference: - * Schmidt, Douglas C. "Gperf: A perfect hash function generator." - * More C++ gems 17 (2000). - * - * Reference: https://en.wikipedia.org/wiki/Perfect_hash_function - * - * Reference: https://github.com/ada-url/ada/issues/617 - ****/ +#ifndef ADA_URL_PATTERN_H +#define ADA_URL_PATTERN_H -ada_really_inline constexpr bool is_special(std::string_view scheme) { - if (scheme.empty()) { - return false; - } - int hash_value = (2 * scheme.size() + (unsigned)(scheme[0])) & 7; - const std::string_view target = details::is_special_list[hash_value]; - return (target[0] == scheme[0]) && (target.substr(1) == scheme.substr(1)); -} -constexpr uint16_t get_special_port(std::string_view scheme) noexcept { - if (scheme.empty()) { - return 0; - } - int hash_value = (2 * scheme.size() + (unsigned)(scheme[0])) & 7; - const std::string_view target = details::is_special_list[hash_value]; - if ((target[0] == scheme[0]) && (target.substr(1) == scheme.substr(1))) { - return details::special_ports[hash_value]; - } else { - return 0; - } -} -constexpr uint16_t get_special_port(ada::scheme::type type) noexcept { - return details::special_ports[int(type)]; -} -constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept { - if (scheme.empty()) { - return ada::scheme::NOT_SPECIAL; - } - int hash_value = (2 * scheme.size() + (unsigned)(scheme[0])) & 7; - const std::string_view target = details::is_special_list[hash_value]; - if ((target[0] == scheme[0]) && (target.substr(1) == scheme.substr(1))) { - return ada::scheme::type(hash_value); - } else { - return ada::scheme::NOT_SPECIAL; - } -} +/* begin file include/ada/implementation.h */ +/** + * @file implementation.h + * @brief Definitions for user facing functions for parsing URL and it's + * components. + */ +#ifndef ADA_IMPLEMENTATION_H +#define ADA_IMPLEMENTATION_H -} // namespace ada::scheme +#include +#include +#include -#endif // ADA_SCHEME_INL_H -/* end file include/ada/scheme-inl.h */ -/* begin file include/ada/serializers.h */ +/* begin file include/ada/url.h */ /** - * @file serializers.h - * @brief Definitions for the URL serializers. + * @file url.h + * @brief Declaration for the URL */ -#ifndef ADA_SERIALIZERS_H -#define ADA_SERIALIZERS_H +#ifndef ADA_URL_H +#define ADA_URL_H -#include +#include #include +#include #include +#include +/* begin file include/ada/checkers.h */ /** - * @namespace ada::serializers - * @brief Includes the definitions for URL serializers + * @file checkers.h + * @brief Declarations for URL specific checkers used within Ada. */ -namespace ada::serializers { +#ifndef ADA_CHECKERS_H +#define ADA_CHECKERS_H + + +#include +#include /** - * Finds and returns the longest sequence of 0 values in a ipv6 input. + * These functions are not part of our public API and may + * change at any time. + * @private + * @namespace ada::checkers + * @brief Includes the definitions for validation functions */ -void find_longest_sequence_of_ipv6_pieces( - const std::array& address, size_t& compress, - size_t& compress_length) noexcept; +namespace ada::checkers { /** - * Serializes an ipv6 address. - * @details An IPv6 address is a 128-bit unsigned integer that identifies a - * network address. - * @see https://url.spec.whatwg.org/#concept-ipv6-serializer + * @private + * Assuming that x is an ASCII letter, this function returns the lower case + * equivalent. + * @details More likely to be inlined by the compiler and constexpr. */ -std::string ipv6(const std::array& address) noexcept; +constexpr char to_lower(char x) noexcept; /** - * Serializes an ipv4 address. - * @details An IPv4 address is a 32-bit unsigned integer that identifies a - * network address. - * @see https://url.spec.whatwg.org/#concept-ipv4-serializer + * @private + * Returns true if the character is an ASCII letter. Equivalent to std::isalpha + * but more likely to be inlined by the compiler. + * + * @attention std::isalpha is not constexpr generally. */ -std::string ipv4(uint64_t address) noexcept; - -} // namespace ada::serializers +constexpr bool is_alpha(char x) noexcept; -#endif // ADA_SERIALIZERS_H -/* end file include/ada/serializers.h */ -/* begin file include/ada/unicode.h */ /** - * @file unicode.h - * @brief Definitions for all unicode specific functions. + * @private + * Check whether a string starts with 0x or 0X. The function is only + * safe if input.size() >=2. + * + * @see has_hex_prefix */ -#ifndef ADA_UNICODE_H -#define ADA_UNICODE_H - -#include -#include +constexpr bool has_hex_prefix_unsafe(std::string_view input); +/** + * @private + * Check whether a string starts with 0x or 0X. + */ +constexpr bool has_hex_prefix(std::string_view input); /** - * Unicode operations. These functions are not part of our public API and may - * change at any time. - * * @private - * @namespace ada::unicode - * @brief Includes the definitions for unicode operations + * Check whether x is an ASCII digit. More likely to be inlined than + * std::isdigit. */ -namespace ada::unicode { +constexpr bool is_digit(char x) noexcept; /** * @private - * We receive a UTF-8 string representing a domain name. - * If the string is percent encoded, we apply percent decoding. - * - * Given a domain, we need to identify its labels. - * They are separated by label-separators: - * - * U+002E (.) FULL STOP - * U+FF0E FULLWIDTH FULL STOP - * U+3002 IDEOGRAPHIC FULL STOP - * U+FF61 HALFWIDTH IDEOGRAPHIC FULL STOP + * @details A string starts with a Windows drive letter if all of the following + * are true: * - * They are all mapped to U+002E. - * - * We process each label into a string that should not exceed 63 octets. - * If the string is already punycode (starts with "xn--"), then we must - * scan it to look for unallowed code points. - * Otherwise, if the string is not pure ASCII, we need to transcode it - * to punycode by following RFC 3454 which requires us to - * - Map characters (see section 3), - * - Normalize (see section 4), - * - Reject forbidden characters, - * - Check for right-to-left characters and if so, check all requirements (see - * section 6), - * - Optionally reject based on unassigned code points (section 7). - * - * The Unicode standard provides a table of code points with a mapping, a list - * of forbidden code points and so forth. This table is subject to change and - * will vary based on the implementation. For Unicode 15, the table is at - * https://www.unicode.org/Public/idna/15.0.0/IdnaMappingTable.txt - * If you use ICU, they parse this table and map it to code using a Python - * script. - * - * The resulting strings should not exceed 255 octets according to RFC 1035 - * section 2.3.4. ICU checks for label size and domain size, but these errors - * are ignored. - * - * @see https://url.spec.whatwg.org/#concept-domain-to-ascii + * - its length is greater than or equal to 2 + * - its first two code points are a Windows drive letter + * - its length is 2 or its third code point is U+002F (/), U+005C (\), U+003F + * (?), or U+0023 (#). * + * https://url.spec.whatwg.org/#start-with-a-windows-drive-letter */ -bool to_ascii(std::optional& out, std::string_view plain, - size_t first_percent); +inline constexpr bool is_windows_drive_letter(std::string_view input) noexcept; /** * @private - * Checks if the input has tab or newline characters. - * - * @attention The has_tabs_or_newline function is a bottleneck and it is simple - * enough that compilers like GCC can 'autovectorize it'. + * @details A normalized Windows drive letter is a Windows drive letter of which + * the second code point is U+003A (:). */ -ada_really_inline bool has_tabs_or_newline( - std::string_view user_input) noexcept; +inline constexpr bool is_normalized_windows_drive_letter( + std::string_view input) noexcept; /** * @private - * Checks if the input is a forbidden host code point. - * @see https://url.spec.whatwg.org/#forbidden-host-code-point + * Returns true if an input is an ipv4 address. It is assumed that the string + * does not contain uppercase ASCII characters (the input should have been + * lowered cased before calling this function) and is not empty. */ -ada_really_inline constexpr bool is_forbidden_host_code_point(char c) noexcept; +ada_really_inline constexpr bool is_ipv4(std::string_view view) noexcept; /** * @private - * Checks if the input contains a forbidden domain code point. - * @see https://url.spec.whatwg.org/#forbidden-domain-code-point + * Returns a bitset. If the first bit is set, then at least one character needs + * percent encoding. If the second bit is set, a \\ is found. If the third bit + * is set then we have a dot. If the fourth bit is set, then we have a percent + * character. */ -ada_really_inline constexpr bool contains_forbidden_domain_code_point( - const char* input, size_t length) noexcept; +ada_really_inline constexpr uint8_t path_signature( + std::string_view input) noexcept; /** * @private - * Checks if the input contains a forbidden domain code point in which case - * the first bit is set to 1. If the input contains an upper case ASCII letter, - * then the second bit is set to 1. - * @see https://url.spec.whatwg.org/#forbidden-domain-code-point + * Returns true if the length of the domain name and its labels are according to + * the specifications. The length of the domain must be 255 octets (253 + * characters not including the last 2 which are the empty label reserved at the + * end). When the empty label is included (a dot at the end), the domain name + * can have 254 characters. The length of a label must be at least 1 and at most + * 63 characters. + * @see section 3.1. of https://www.rfc-editor.org/rfc/rfc1034 + * @see https://www.unicode.org/reports/tr46/#ToASCII */ -ada_really_inline constexpr uint8_t -contains_forbidden_domain_code_point_or_upper(const char* input, - size_t length) noexcept; +ada_really_inline constexpr bool verify_dns_length( + std::string_view input) noexcept; -/** - * @private - * Checks if the input is a forbidden domain code point. - * @see https://url.spec.whatwg.org/#forbidden-domain-code-point - */ -ada_really_inline constexpr bool is_forbidden_domain_code_point( - char c) noexcept; +} // namespace ada::checkers +#endif // ADA_CHECKERS_H +/* end file include/ada/checkers.h */ +/* begin file include/ada/url_components.h */ /** - * @private - * Checks if the input is alphanumeric, '+', '-' or '.' + * @file url_components.h + * @brief Declaration for the URL Components */ -ada_really_inline constexpr bool is_alnum_plus(char c) noexcept; +#ifndef ADA_URL_COMPONENTS_H +#define ADA_URL_COMPONENTS_H -/** - * @private - * @details An ASCII hex digit is an ASCII upper hex digit or ASCII lower hex - * digit. An ASCII upper hex digit is an ASCII digit or a code point in the - * range U+0041 (A) to U+0046 (F), inclusive. An ASCII lower hex digit is an - * ASCII digit or a code point in the range U+0061 (a) to U+0066 (f), inclusive. - */ -ada_really_inline constexpr bool is_ascii_hex_digit(char c) noexcept; +namespace ada { /** - * @private - * Checks if the input is a C0 control or space character. + * @brief URL Component representations using offsets. * - * @details A C0 control or space is a C0 control or U+0020 SPACE. - * A C0 control is a code point in the range U+0000 NULL to U+001F INFORMATION - * SEPARATOR ONE, inclusive. - */ -ada_really_inline constexpr bool is_c0_control_or_space(char c) noexcept; - -/** - * @private - * Checks if the input is a ASCII tab or newline character. + * @details We design the url_components struct so that it is as small + * and simple as possible. This version uses 32 bytes. * - * @details An ASCII tab or newline is U+0009 TAB, U+000A LF, or U+000D CR. - */ -ada_really_inline constexpr bool is_ascii_tab_or_newline(char c) noexcept; - -/** - * @private - * @details A double-dot path segment must be ".." or an ASCII case-insensitive - * match for ".%2e", "%2e.", or "%2e%2e". - */ -ada_really_inline ada_constexpr bool is_double_dot_path_segment( - std::string_view input) noexcept; - -/** - * @private - * @details A single-dot path segment must be "." or an ASCII case-insensitive - * match for "%2e". + * This struct is used to extract components from a single 'href'. */ -ada_really_inline constexpr bool is_single_dot_path_segment( - std::string_view input) noexcept; +struct url_components { + constexpr static uint32_t omitted = uint32_t(-1); -/** - * @private - * @details ipv4 character might contain 0-9 or a-f character ranges. - */ -ada_really_inline constexpr bool is_lowercase_hex(char c) noexcept; + url_components() = default; + url_components(const url_components &u) = default; + url_components(url_components &&u) noexcept = default; + url_components &operator=(url_components &&u) noexcept = default; + url_components &operator=(const url_components &u) = default; + ~url_components() = default; -/** - * @private - * @details Convert hex to binary. Caller is responsible to ensure that - * the parameter is an hexadecimal digit (0-9, A-F, a-f). - */ -ada_really_inline unsigned constexpr convert_hex_to_binary(char c) noexcept; + /* + * By using 32-bit integers, we implicitly assume that the URL string + * cannot exceed 4 GB. + * + * https://user:pass@example.com:1234/foo/bar?baz#quux + * | | | | ^^^^| | | + * | | | | | | | `----- hash_start + * | | | | | | `--------- search_start + * | | | | | `----------------- pathname_start + * | | | | `--------------------- port + * | | | `----------------------- host_end + * | | `---------------------------------- host_start + * | `--------------------------------------- username_end + * `--------------------------------------------- protocol_end + */ + uint32_t protocol_end{0}; + /** + * Username end is not `omitted` by default to make username and password + * getters less costly to implement. + */ + uint32_t username_end{0}; + uint32_t host_start{0}; + uint32_t host_end{0}; + uint32_t port{omitted}; + uint32_t pathname_start{0}; + uint32_t search_start{omitted}; + uint32_t hash_start{omitted}; -/** - * @private - * first_percent should be = input.find('%') - * - * @todo It would be faster as noexcept maybe, but it could be unsafe since. - * @author Node.js - * @see https://github.com/nodejs/node/blob/main/src/node_url.cc#L245 - * @see https://encoding.spec.whatwg.org/#utf-8-decode-without-bom - */ -std::string percent_decode(std::string_view input, size_t first_percent); + /** + * Check the following conditions: + * protocol_end < username_end < ... < hash_start, + * expect when a value is omitted. It also computes + * a lower bound on the possible string length that may match these + * offsets. + * @return true if the offset values are + * consistent with a possible URL string + */ + [[nodiscard]] constexpr bool check_offset_consistency() const noexcept; -/** - * @private - * Returns a percent-encoding string whether percent encoding was needed or not. - * @see https://github.com/nodejs/node/blob/main/src/node_url.cc#L226 - */ -std::string percent_encode(std::string_view input, - const uint8_t character_set[]); -/** - * @private - * Returns a percent-encoded string version of input, while starting the percent - * encoding at the provided index. - * @see https://github.com/nodejs/node/blob/main/src/node_url.cc#L226 - */ -std::string percent_encode(std::string_view input, - const uint8_t character_set[], size_t index); -/** - * @private - * Returns true if percent encoding was needed, in which case, we store - * the percent-encoded content in 'out'. If the boolean 'append' is set to - * true, the content is appended to 'out'. - * If percent encoding is not needed, out is left unchanged. - * @see https://github.com/nodejs/node/blob/main/src/node_url.cc#L226 - */ -template -bool percent_encode(std::string_view input, const uint8_t character_set[], - std::string& out); -/** - * @private - * Returns the index at which percent encoding should start, or (equivalently), - * the length of the prefix that does not require percent encoding. - */ -ada_really_inline size_t percent_encode_index(std::string_view input, - const uint8_t character_set[]); -/** - * @private - * Lowers the string in-place, assuming that the content is ASCII. - * Return true if the content was ASCII. - */ -constexpr bool to_lower_ascii(char* input, size_t length) noexcept; -} // namespace ada::unicode + /** + * Converts a url_components to JSON stringified version. + */ + [[nodiscard]] std::string to_string() const; -#endif // ADA_UNICODE_H -/* end file include/ada/unicode.h */ -/* begin file include/ada/url_base-inl.h */ -/** - * @file url_base-inl.h - * @brief Inline functions for url base - */ -#ifndef ADA_URL_BASE_INL_H -#define ADA_URL_BASE_INL_H +}; // struct url_components +} // namespace ada +#endif +/* end file include/ada/url_components.h */ -/* begin file include/ada/url_aggregator.h */ -/** - * @file url_aggregator.h - * @brief Declaration for the basic URL definitions - */ -#ifndef ADA_URL_AGGREGATOR_H -#define ADA_URL_AGGREGATOR_H +namespace ada { -#include -#include +struct url_aggregator; -namespace ada { +// namespace parser { +// template +// result_type parse_url(std::string_view user_input, +// const result_type* base_url = nullptr); +// template +// result_type parse_url_impl(std::string_view user_input, +// const result_type* base_url = nullptr); +// } /** - * @brief Lightweight URL struct. + * @brief Generic URL struct reliant on std::string instantiation. * - * @details The url_aggregator class aims to minimize temporary memory - * allocation while representing a parsed URL. Internally, it contains a single - * normalized URL (the href), and it makes available the components, mostly - * using std::string_view. + * @details To disambiguate from a valid URL string it can also be referred to + * as a URL record. A URL is a struct that represents a universal identifier. + * Unlike the url_aggregator, the ada::url represents the different components + * of a parsed URL as independent std::string instances. This makes the + * structure heavier and more reliant on memory allocations. When getting + * components from the parsed URL, a new std::string is typically constructed. + * + * @see https://url.spec.whatwg.org/#url-representation */ -struct url_aggregator : url_base { - url_aggregator() = default; - url_aggregator(const url_aggregator& u) = default; - url_aggregator(url_aggregator&& u) noexcept = default; - url_aggregator& operator=(url_aggregator&& u) noexcept = default; - url_aggregator& operator=(const url_aggregator& u) = default; - ~url_aggregator() override = default; +struct url : url_base { + url() = default; + url(const url &u) = default; + url(url &&u) noexcept = default; + url &operator=(url &&u) noexcept = default; + url &operator=(const url &u) = default; + ~url() override = default; - bool set_href(std::string_view input); - bool set_host(std::string_view input); - bool set_hostname(std::string_view input); - bool set_protocol(std::string_view input); - bool set_username(std::string_view input); - bool set_password(std::string_view input); - bool set_port(std::string_view input); - bool set_pathname(std::string_view input); - void set_search(std::string_view input); - void set_hash(std::string_view input); + /** + * @private + * A URL's username is an ASCII string identifying a username. It is initially + * the empty string. + */ + std::string username{}; - [[nodiscard]] bool has_valid_domain() const noexcept override; /** - * The origin getter steps are to return the serialization of this's URL's - * origin. [HTML] - * @return a newly allocated string. - * @see https://url.spec.whatwg.org/#concept-url-origin + * @private + * A URL's password is an ASCII string identifying a password. It is initially + * the empty string. */ - [[nodiscard]] std::string get_origin() const noexcept override; + std::string password{}; + /** - * Return the normalized string. - * This function does not allocate memory. - * It is highly efficient. - * @return a constant reference to the underlying normalized URL. - * @see https://url.spec.whatwg.org/#dom-url-href - * @see https://url.spec.whatwg.org/#concept-url-serializer + * @private + * A URL's host is null or a host. It is initially null. */ - [[nodiscard]] inline std::string_view get_href() const noexcept; + std::optional host{}; + /** - * The username getter steps are to return this's URL's username. - * This function does not allocate memory. - * @return a lightweight std::string_view. - * @see https://url.spec.whatwg.org/#dom-url-username + * @private + * A URL's port is either null or a 16-bit unsigned integer that identifies a + * networking port. It is initially null. */ - [[nodiscard]] std::string_view get_username() const noexcept; + std::optional port{}; + /** - * The password getter steps are to return this's URL's password. - * This function does not allocate memory. - * @return a lightweight std::string_view. - * @see https://url.spec.whatwg.org/#dom-url-password + * @private + * A URL's path is either an ASCII string or a list of zero or more ASCII + * strings, usually identifying a location. */ - [[nodiscard]] std::string_view get_password() const noexcept; + std::string path{}; + /** - * Return this's URL's port, serialized. - * This function does not allocate memory. - * @return a lightweight std::string_view. - * @see https://url.spec.whatwg.org/#dom-url-port + * @private + * A URL's query is either null or an ASCII string. It is initially null. */ - [[nodiscard]] std::string_view get_port() const noexcept; + std::optional query{}; + /** - * Return U+0023 (#), followed by this's URL's fragment. - * This function does not allocate memory. - * @return a lightweight std::string_view.. - * @see https://url.spec.whatwg.org/#dom-url-hash + * @private + * A URL's fragment is either null or an ASCII string that can be used for + * further processing on the resource the URL's other components identify. It + * is initially null. + */ + std::optional hash{}; + + /** @return true if it has an host but it is the empty string */ + [[nodiscard]] inline bool has_empty_hostname() const noexcept; + /** @return true if the URL has a (non default) port */ + [[nodiscard]] inline bool has_port() const noexcept; + /** @return true if it has a host (included an empty host) */ + [[nodiscard]] inline bool has_hostname() const noexcept; + [[nodiscard]] bool has_valid_domain() const noexcept override; + + /** + * Returns a JSON string representation of this URL. + */ + [[nodiscard]] std::string to_string() const override; + + /** + * @see https://url.spec.whatwg.org/#dom-url-href + * @see https://url.spec.whatwg.org/#concept-url-serializer + */ + [[nodiscard]] ada_really_inline std::string get_href() const noexcept; + + /** + * The origin getter steps are to return the serialization of this's URL's + * origin. [HTML] + * @return a newly allocated string. + * @see https://url.spec.whatwg.org/#concept-url-origin + */ + [[nodiscard]] std::string get_origin() const noexcept override; + + /** + * The protocol getter steps are to return this's URL's scheme, followed by + * U+003A (:). + * @return a newly allocated string. + * @see https://url.spec.whatwg.org/#dom-url-protocol */ - [[nodiscard]] std::string_view get_hash() const noexcept; + [[nodiscard]] std::string get_protocol() const noexcept; + /** * Return url's host, serialized, followed by U+003A (:) and url's port, * serialized. - * This function does not allocate memory. - * When there is no host, this function returns the empty view. - * @return a lightweight std::string_view. + * When there is no host, this function returns the empty string. + * @return a newly allocated string. * @see https://url.spec.whatwg.org/#dom-url-host */ - [[nodiscard]] std::string_view get_host() const noexcept; + [[nodiscard]] std::string get_host() const noexcept; + /** * Return this's URL's host, serialized. - * This function does not allocate memory. - * When there is no host, this function returns the empty view. - * @return a lightweight std::string_view. + * When there is no host, this function returns the empty string. + * @return a newly allocated string. * @see https://url.spec.whatwg.org/#dom-url-hostname */ - [[nodiscard]] std::string_view get_hostname() const noexcept; + [[nodiscard]] std::string get_hostname() const noexcept; + /** * The pathname getter steps are to return the result of URL path serializing * this's URL. - * This function does not allocate memory. - * @return a lightweight std::string_view. + * @return a newly allocated string. * @see https://url.spec.whatwg.org/#dom-url-pathname */ - [[nodiscard]] std::string_view get_pathname() const noexcept; + [[nodiscard]] constexpr std::string_view get_pathname() const noexcept; + /** * Compute the pathname length in bytes without instantiating a view or a * string. * @return size of the pathname in bytes * @see https://url.spec.whatwg.org/#dom-url-pathname */ - [[nodiscard]] ada_really_inline uint32_t get_pathname_length() const noexcept; + [[nodiscard]] ada_really_inline size_t get_pathname_length() const noexcept; + /** * Return U+003F (?), followed by this's URL's query. - * This function does not allocate memory. - * @return a lightweight std::string_view. + * @return a newly allocated string. * @see https://url.spec.whatwg.org/#dom-url-search */ - [[nodiscard]] std::string_view get_search() const noexcept; + [[nodiscard]] std::string get_search() const noexcept; + /** - * The protocol getter steps are to return this's URL's scheme, followed by - * U+003A (:). - * This function does not allocate memory. - * @return a lightweight std::string_view. + * The username getter steps are to return this's URL's username. + * @return a constant reference to the underlying string. + * @see https://url.spec.whatwg.org/#dom-url-username + */ + [[nodiscard]] const std::string &get_username() const noexcept; + + /** + * @return Returns true on successful operation. + * @see https://url.spec.whatwg.org/#dom-url-username + */ + bool set_username(std::string_view input); + + /** + * @return Returns true on success. + * @see https://url.spec.whatwg.org/#dom-url-password + */ + bool set_password(std::string_view input); + + /** + * @return Returns true on success. + * @see https://url.spec.whatwg.org/#dom-url-port + */ + bool set_port(std::string_view input); + + /** + * This function always succeeds. + * @see https://url.spec.whatwg.org/#dom-url-hash + */ + void set_hash(std::string_view input); + + /** + * This function always succeeds. + * @see https://url.spec.whatwg.org/#dom-url-search + */ + void set_search(std::string_view input); + + /** + * @return Returns true on success. + * @see https://url.spec.whatwg.org/#dom-url-search + */ + bool set_pathname(std::string_view input); + + /** + * @return Returns true on success. + * @see https://url.spec.whatwg.org/#dom-url-host + */ + bool set_host(std::string_view input); + + /** + * @return Returns true on success. + * @see https://url.spec.whatwg.org/#dom-url-hostname + */ + bool set_hostname(std::string_view input); + + /** + * @return Returns true on success. * @see https://url.spec.whatwg.org/#dom-url-protocol */ - [[nodiscard]] std::string_view get_protocol() const noexcept; + bool set_protocol(std::string_view input); + + /** + * @see https://url.spec.whatwg.org/#dom-url-href + */ + bool set_href(std::string_view input); + + /** + * The password getter steps are to return this's URL's password. + * @return a constant reference to the underlying string. + * @see https://url.spec.whatwg.org/#dom-url-password + */ + [[nodiscard]] const std::string &get_password() const noexcept; + + /** + * Return this's URL's port, serialized. + * @return a newly constructed string representing the port. + * @see https://url.spec.whatwg.org/#dom-url-port + */ + [[nodiscard]] std::string get_port() const noexcept; + + /** + * Return U+0023 (#), followed by this's URL's fragment. + * @return a newly constructed string representing the hash. + * @see https://url.spec.whatwg.org/#dom-url-hash + */ + [[nodiscard]] std::string get_hash() const noexcept; /** * A URL includes credentials if its username or password is not the empty @@ -4926,92 +4888,54 @@ struct url_aggregator : url_base { * * Inspired after servo/url * - * @return a constant reference to the underlying component attribute. + * @return a newly constructed component. * * @see * https://github.com/servo/rust-url/blob/b65a45515c10713f6d212e6726719a020203cc98/url/src/quirks.rs#L31 */ - [[nodiscard]] ada_really_inline const ada::url_components& get_components() + [[nodiscard]] ada_really_inline ada::url_components get_components() const noexcept; - /** - * Returns a string representation of this URL. - */ - [[nodiscard]] std::string to_string() const override; - /** - * Returns a string diagram of this URL. - */ - [[nodiscard]] std::string to_diagram() const; + /** @return true if the URL has a hash component */ + [[nodiscard]] constexpr bool has_hash() const noexcept override; + /** @return true if the URL has a search component */ + [[nodiscard]] constexpr bool has_search() const noexcept override; - /** - * Verifies that the parsed URL could be valid. Useful for debugging purposes. - * @return true if the URL is valid, otherwise return true of the offsets are - * possible. - */ - [[nodiscard]] bool validate() const noexcept; + private: + friend ada::url ada::parser::parse_url(std::string_view, + const ada::url *); + friend ada::url_aggregator ada::parser::parse_url( + std::string_view, const ada::url_aggregator *); + friend void ada::helpers::strip_trailing_spaces_from_opaque_path( + ada::url &url) noexcept; - /** @return true if it has an host but it is the empty string */ - [[nodiscard]] inline bool has_empty_hostname() const noexcept; - /** @return true if it has a host (included an empty host) */ - [[nodiscard]] inline bool has_hostname() const noexcept; - /** @return true if the URL has a non-empty username */ - [[nodiscard]] inline bool has_non_empty_username() const noexcept; - /** @return true if the URL has a non-empty password */ - [[nodiscard]] inline bool has_non_empty_password() const noexcept; - /** @return true if the URL has a (non default) port */ - [[nodiscard]] inline bool has_port() const noexcept; - /** @return true if the URL has a password */ - [[nodiscard]] inline bool has_password() const noexcept; - /** @return true if the URL has a hash component */ - [[nodiscard]] inline bool has_hash() const noexcept override; - /** @return true if the URL has a search component */ - [[nodiscard]] inline bool has_search() const noexcept override; - - inline void clear_port(); - inline void clear_hash(); - inline void clear_search() override; - - private: - friend ada::url_aggregator ada::parser::parse_url( - std::string_view, const ada::url_aggregator*); - friend void ada::helpers::strip_trailing_spaces_from_opaque_path< - ada::url_aggregator>(ada::url_aggregator& url) noexcept; - friend ada::url_aggregator ada::parser::parse_url_impl< - ada::url_aggregator, true>(std::string_view, const ada::url_aggregator*); + friend ada::url ada::parser::parse_url_impl(std::string_view, + const ada::url *); friend ada::url_aggregator ada::parser::parse_url_impl< - ada::url_aggregator, false>(std::string_view, const ada::url_aggregator*); - - std::string buffer{}; - url_components components{}; - - /** - * Returns true if neither the search, nor the hash nor the pathname - * have been set. - * @return true if the buffer is ready to receive the path. - */ - [[nodiscard]] ada_really_inline bool is_at_path() const noexcept; + ada::url_aggregator, true>(std::string_view, const ada::url_aggregator *); - inline void add_authority_slashes_if_needed() noexcept; + inline void update_unencoded_base_hash(std::string_view input); + inline void update_base_hostname(std::string_view input); + inline void update_base_search(std::string_view input, + const uint8_t query_percent_encode_set[]); + inline void update_base_search(std::optional &&input); + inline void update_base_pathname(std::string_view input); + inline void update_base_username(std::string_view input); + inline void update_base_password(std::string_view input); + inline void update_base_port(std::optional input); /** - * To optimize performance, you may indicate how much memory to allocate - * within this instance. + * Sets the host or hostname according to override condition. + * Return true on success. + * @see https://url.spec.whatwg.org/#hostname-state */ - inline void reserve(uint32_t capacity); - - ada_really_inline size_t parse_port( - std::string_view view, bool check_trailing_content) noexcept override; - - ada_really_inline size_t parse_port(std::string_view view) noexcept override { - return this->parse_port(view, false); - } + template + bool set_host_or_hostname(std::string_view input); /** - * Return true on success. The 'in_place' parameter indicates whether the - * the string_view input is pointing in the buffer. When in_place is false, - * we must nearly always update the buffer. + * Return true on success. * @see https://url.spec.whatwg.org/#concept-ipv4-parser */ - [[nodiscard]] bool parse_ipv4(std::string_view input, bool in_place); + [[nodiscard]] bool parse_ipv4(std::string_view input); /** * Return true on success. @@ -5025,7 +4949,16 @@ struct url_aggregator : url_base { */ [[nodiscard]] bool parse_opaque_host(std::string_view input); - ada_really_inline void parse_path(std::string_view input); + /** + * A URL's scheme is an ASCII string that identifies the type of URL and can + * be used to dispatch a URL for further processing after parsing. It is + * initially the empty string. We only set non_special_scheme when the scheme + * is non-special, otherwise we avoid constructing string. + * + * Special schemes are stored in ada::scheme::details::is_special_list so we + * typically do not need to store them in each url instance. + */ + std::string non_special_scheme{}; /** * A URL cannot have a username/password/port if its host is null or the empty @@ -5033,729 +4966,1747 @@ struct url_aggregator : url_base { */ [[nodiscard]] inline bool cannot_have_credentials_or_port() const; - template - bool set_host_or_hostname(std::string_view input); + ada_really_inline size_t parse_port( + std::string_view view, bool check_trailing_content) noexcept override; - ada_really_inline bool parse_host(std::string_view input); + ada_really_inline size_t parse_port(std::string_view view) noexcept override { + return this->parse_port(view, false); + } + + /** + * Parse the host from the provided input. We assume that + * the input does not contain spaces or tabs. Control + * characters and spaces are not trimmed (they should have + * been removed if needed). + * Return true on success. + * @see https://url.spec.whatwg.org/#host-parsing + */ + [[nodiscard]] ada_really_inline bool parse_host(std::string_view input); - inline void update_base_authority(std::string_view base_buffer, - const ada::url_components& base); - inline void update_unencoded_base_hash(std::string_view input); - inline void update_base_hostname(std::string_view input); - inline void update_base_search(std::string_view input); - inline void update_base_search(std::string_view input, - const uint8_t* query_percent_encode_set); - inline void update_base_pathname(std::string_view input); - inline void update_base_username(std::string_view input); - inline void append_base_username(std::string_view input); - inline void update_base_password(std::string_view input); - inline void append_base_password(std::string_view input); - inline void update_base_port(uint32_t input); - inline void append_base_pathname(std::string_view input); - [[nodiscard]] inline uint32_t retrieve_base_port() const; - inline void clear_hostname(); - inline void clear_password(); - inline void clear_pathname() override; - [[nodiscard]] inline bool has_dash_dot() const noexcept; - void delete_dash_dot(); - inline void consume_prepared_path(std::string_view input); template - [[nodiscard]] ada_really_inline bool parse_scheme_with_colon( - std::string_view input); - ada_really_inline uint32_t replace_and_resize(uint32_t start, uint32_t end, - std::string_view input); - [[nodiscard]] inline bool has_authority() const noexcept; - inline void set_protocol_as_file(); - inline void set_scheme(std::string_view new_scheme) noexcept; + [[nodiscard]] ada_really_inline bool parse_scheme(std::string_view input); + + constexpr void clear_pathname() override; + constexpr void clear_search() override; + constexpr void set_protocol_as_file(); + /** - * Fast function to set the scheme from a view with a colon in the - * buffer, does not change type. + * Parse the path from the provided input. + * Return true on success. Control characters not + * trimmed from the ends (they should have + * been removed if needed). + * + * The input is expected to be UTF-8. + * + * @see https://url.spec.whatwg.org/ */ - inline void set_scheme_from_view_with_colon( - std::string_view new_scheme_with_colon) noexcept; - inline void copy_scheme(const url_aggregator& u) noexcept; + ada_really_inline void parse_path(std::string_view input); -}; // url_aggregator + /** + * Set the scheme for this URL. The provided scheme should be a valid + * scheme string, be lower-cased, not contain spaces or tabs. It should + * have no spurious trailing or leading content. + */ + inline void set_scheme(std::string &&new_scheme) noexcept; -inline std::ostream& operator<<(std::ostream& out, const ada::url& u); -} // namespace ada + /** + * Take the scheme from another URL. The scheme string is moved from the + * provided url. + */ + constexpr void copy_scheme(ada::url &&u) noexcept; -#endif -/* end file include/ada/url_aggregator.h */ -/* begin file include/ada/checkers.h */ -/** - * @file checkers.h - * @brief Declarations for URL specific checkers used within Ada. - */ -#ifndef ADA_CHECKERS_H -#define ADA_CHECKERS_H + /** + * Take the scheme from another URL. The scheme string is copied from the + * provided url. + */ + constexpr void copy_scheme(const ada::url &u); -#include -#include +}; // struct url -/** - * These functions are not part of our public API and may - * change at any time. - * @private - * @namespace ada::checkers - * @brief Includes the definitions for validation functions - */ -namespace ada::checkers { +inline std::ostream &operator<<(std::ostream &out, const ada::url &u); +} // namespace ada -/** - * @private - * Assuming that x is an ASCII letter, this function returns the lower case - * equivalent. - * @details More likely to be inlined by the compiler and constexpr. - */ -constexpr char to_lower(char x) noexcept; +#endif // ADA_URL_H +/* end file include/ada/url.h */ -/** - * @private - * Returns true if the character is an ASCII letter. Equivalent to std::isalpha - * but more likely to be inlined by the compiler. - * - * @attention std::isalpha is not constexpr generally. - */ -constexpr bool is_alpha(char x) noexcept; +namespace ada { + +template +using result = tl::expected; /** - * @private - * Check whether a string starts with 0x or 0X. The function is only - * safe if input.size() >=2. + * The URL parser takes a scalar value string input, with an optional null or + * base URL base (default null). The parser assumes the input is a valid ASCII + * or UTF-8 string. * - * @see has_hex_prefix - */ -inline bool has_hex_prefix_unsafe(std::string_view input); -/** - * @private - * Check whether a string starts with 0x or 0X. + * @param input the string input to analyze (must be valid ASCII or UTF-8) + * @param base_url the optional URL input to use as a base url. + * @return a parsed URL. */ -inline bool has_hex_prefix(std::string_view input); +template +ada_warn_unused ada::result parse( + std::string_view input, const result_type* base_url = nullptr); + +extern template ada::result parse(std::string_view input, + const url* base_url); +extern template ada::result parse( + std::string_view input, const url_aggregator* base_url); /** - * @private - * Check whether x is an ASCII digit. More likely to be inlined than - * std::isdigit. + * Verifies whether the URL strings can be parsed. The function assumes + * that the inputs are valid ASCII or UTF-8 strings. + * @see https://url.spec.whatwg.org/#dom-url-canparse + * @return If URL can be parsed or not. */ -constexpr bool is_digit(char x) noexcept; +bool can_parse(std::string_view input, + const std::string_view* base_input = nullptr); +#if ADA_INCLUDE_URL_PATTERN /** - * @private - * @details A string starts with a Windows drive letter if all of the following - * are true: + * Implementation of the URL pattern parsing algorithm. + * @see https://urlpattern.spec.whatwg.org * - * - its length is greater than or equal to 2 - * - its first two code points are a Windows drive letter - * - its length is 2 or its third code point is U+002F (/), U+005C (\), U+003F - * (?), or U+0023 (#). - * - * https://url.spec.whatwg.org/#start-with-a-windows-drive-letter + * @param input valid UTF-8 string or URLPatternInit struct + * @param base_url an optional valid UTF-8 string + * @param options an optional url_pattern_options struct + * @return url_pattern instance */ -inline constexpr bool is_windows_drive_letter(std::string_view input) noexcept; +template +ada_warn_unused tl::expected, errors> +parse_url_pattern(std::variant&& input, + const std::string_view* base_url = nullptr, + const url_pattern_options* options = nullptr); +#endif // ADA_INCLUDE_URL_PATTERN /** - * @private - * @details A normalized Windows drive letter is a Windows drive letter of which - * the second code point is U+003A (:). + * Computes a href string from a file path. The function assumes + * that the input is a valid ASCII or UTF-8 string. + * @return a href string (starts with file:://) */ -inline constexpr bool is_normalized_windows_drive_letter( - std::string_view input) noexcept; +std::string href_from_file(std::string_view path); +} // namespace ada -/** - * @private - * @warning Will be removed when Ada requires C++20. - */ -ada_really_inline bool begins_with(std::string_view view, - std::string_view prefix); +#endif // ADA_IMPLEMENTATION_H +/* end file include/ada/implementation.h */ -/** - * @private - * Returns true if an input is an ipv4 address. It is assumed that the string - * does not contain uppercase ASCII characters (the input should have been - * lowered cased before calling this function) and is not empty. - */ -ada_really_inline ada_constexpr bool is_ipv4(std::string_view view) noexcept; +#include +#include +#include +#include +#include +#include -/** - * @private - * Returns a bitset. If the first bit is set, then at least one character needs - * percent encoding. If the second bit is set, a \\ is found. If the third bit - * is set then we have a dot. If the fourth bit is set, then we have a percent - * character. - */ -ada_really_inline constexpr uint8_t path_signature( - std::string_view input) noexcept; +#if ADA_TESTING +#include +#endif // ADA_TESTING -/** - * @private - * Returns true if the length of the domain name and its labels are according to - * the specifications. The length of the domain must be 255 octets (253 - * characters not including the last 2 which are the empty label reserved at the - * end). When the empty label is included (a dot at the end), the domain name - * can have 254 characters. The length of a label must be at least 1 and at most - * 63 characters. - * @see section 3.1. of https://www.rfc-editor.org/rfc/rfc1034 - * @see https://www.unicode.org/reports/tr46/#ToASCII - */ -ada_really_inline constexpr bool verify_dns_length( - std::string_view input) noexcept; +#if ADA_INCLUDE_URL_PATTERN +namespace ada { -} // namespace ada::checkers +enum class url_pattern_part_type : uint8_t { + // The part represents a simple fixed text string. + FIXED_TEXT, + // The part represents a matching group with a custom regular expression. + REGEXP, + // The part represents a matching group that matches code points up to the + // next separator code point. This is typically used for a named group like + // ":foo" that does not have a custom regular expression. + SEGMENT_WILDCARD, + // The part represents a matching group that greedily matches all code points. + // This is typically used for the "*" wildcard matching group. + FULL_WILDCARD, +}; -#endif // ADA_CHECKERS_H -/* end file include/ada/checkers.h */ -/* begin file include/ada/url.h */ -/** - * @file url.h - * @brief Declaration for the URL - */ -#ifndef ADA_URL_H -#define ADA_URL_H +enum class url_pattern_part_modifier : uint8_t { + // The part does not have a modifier. + none, + // The part has an optional modifier indicated by the U+003F (?) code point. + optional, + // The part has a "zero or more" modifier indicated by the U+002A (*) code + // point. + zero_or_more, + // The part has a "one or more" modifier indicated by the U+002B (+) code + // point. + one_or_more, +}; -#include -#include -#include -#include -#include -#include +// @see https://urlpattern.spec.whatwg.org/#part +class url_pattern_part { + public: + url_pattern_part(url_pattern_part_type _type, std::string&& _value, + url_pattern_part_modifier _modifier) + : type(_type), value(std::move(_value)), modifier(_modifier) {} + + url_pattern_part(url_pattern_part_type _type, std::string&& _value, + url_pattern_part_modifier _modifier, std::string&& _name, + std::string&& _prefix, std::string&& _suffix) + : type(_type), + value(std::move(_value)), + modifier(_modifier), + name(std::move(_name)), + prefix(std::move(_prefix)), + suffix(std::move(_suffix)) {} + // A part has an associated type, a string, which must be set upon creation. + url_pattern_part_type type; + // A part has an associated value, a string, which must be set upon creation. + std::string value; + // A part has an associated modifier a string, which must be set upon + // creation. + url_pattern_part_modifier modifier; + // A part has an associated name, a string, initially the empty string. + std::string name{}; + // A part has an associated prefix, a string, initially the empty string. + std::string prefix{}; + // A part has an associated suffix, a string, initially the empty string. + std::string suffix{}; + + inline bool is_regexp() const noexcept; +}; -namespace ada { +// @see https://urlpattern.spec.whatwg.org/#options-header +struct url_pattern_compile_component_options { + url_pattern_compile_component_options() = default; + explicit url_pattern_compile_component_options( + std::optional new_delimiter = std::nullopt, + std::optional new_prefix = std::nullopt) + : delimiter(new_delimiter), prefix(new_prefix) {} -/** - * @brief Generic URL struct reliant on std::string instantiation. - * - * @details To disambiguate from a valid URL string it can also be referred to - * as a URL record. A URL is a struct that represents a universal identifier. - * Unlike the url_aggregator, the ada::url represents the different components - * of a parsed URL as independent std::string instances. This makes the - * structure heavier and more reliant on memory allocations. When getting - * components from the parsed URL, a new std::string is typically constructed. - * - * @see https://url.spec.whatwg.org/#url-representation - */ -struct url : url_base { - url() = default; - url(const url& u) = default; - url(url&& u) noexcept = default; - url& operator=(url&& u) noexcept = default; - url& operator=(const url& u) = default; - ~url() override = default; + inline std::string_view get_delimiter() const ada_warn_unused; + inline std::string_view get_prefix() const ada_warn_unused; + + // @see https://urlpattern.spec.whatwg.org/#options-ignore-case + bool ignore_case = false; + + static url_pattern_compile_component_options DEFAULT; + static url_pattern_compile_component_options HOSTNAME; + static url_pattern_compile_component_options PATHNAME; + + private: + // @see https://urlpattern.spec.whatwg.org/#options-delimiter-code-point + std::optional delimiter{}; + // @see https://urlpattern.spec.whatwg.org/#options-prefix-code-point + std::optional prefix{}; +}; + +// The default options is an options struct with delimiter code point set to +// the empty string and prefix code point set to the empty string. +inline url_pattern_compile_component_options + url_pattern_compile_component_options::DEFAULT(std::nullopt, std::nullopt); + +// The hostname options is an options struct with delimiter code point set +// "." and prefix code point set to the empty string. +inline url_pattern_compile_component_options + url_pattern_compile_component_options::HOSTNAME('.', std::nullopt); + +// The pathname options is an options struct with delimiter code point set +// "/" and prefix code point set to "/". +inline url_pattern_compile_component_options + url_pattern_compile_component_options::PATHNAME('/', '/'); + +// A struct providing the URLPattern matching results for a single +// URL component. The URLPatternComponentResult is only ever used +// as a member attribute of a URLPatternResult struct. The +// URLPatternComponentResult API is defined as part of the URLPattern +// specification. +struct url_pattern_component_result { + std::string input; + std::unordered_map> groups; + + bool operator==(const url_pattern_component_result&) const; + +#if ADA_TESTING + friend void PrintTo(const url_pattern_component_result& result, + std::ostream* os) { + *os << "input: '" << result.input << "', group: "; + for (const auto& group : result.groups) { + *os << "(" << group.first << ", " << group.second.value_or("undefined") + << ") "; + } + } +#endif // ADA_TESTING +}; + +template +class url_pattern_component { + public: + url_pattern_component() = default; + + // This function explicitly takes a std::string because it is moved. + // To avoid unnecessary copy, move each value while calling the constructor. + url_pattern_component(std::string&& new_pattern, + typename regex_provider::regex_type&& new_regexp, + std::vector&& new_group_name_list, + bool new_has_regexp_groups) + : regexp(std::move(new_regexp)), + pattern(std::move(new_pattern)), + group_name_list(std::move(new_group_name_list)), + has_regexp_groups(new_has_regexp_groups) {} + + // @see https://urlpattern.spec.whatwg.org/#compile-a-component + template + static tl::expected compile( + std::string_view input, F& encoding_callback, + url_pattern_compile_component_options& options); + + // @see https://urlpattern.spec.whatwg.org/#create-a-component-match-result + url_pattern_component_result create_component_match_result( + std::string&& input, + std::vector>&& exec_result); + +#if ADA_TESTING + friend void PrintTo(const url_pattern_component& component, + std::ostream* os) { + *os << "pattern: '" << component.pattern + << "', has_regexp_groups: " << component.has_regexp_groups + << "group_name_list: "; + for (const auto& name : component.group_name_list) { + *os << name << ", "; + } + } +#endif // ADA_TESTING + + typename regex_provider::regex_type regexp{}; + std::string pattern{}; + std::vector group_name_list{}; + bool has_regexp_groups = false; +}; + +// A URLPattern input can be either a string or a URLPatternInit object. +// If it is a string, it must be a valid UTF-8 string. +using url_pattern_input = std::variant; + +// A struct providing the URLPattern matching results for all +// components of a URL. The URLPatternResult API is defined as +// part of the URLPattern specification. +struct url_pattern_result { + std::vector inputs; + url_pattern_component_result protocol; + url_pattern_component_result username; + url_pattern_component_result password; + url_pattern_component_result hostname; + url_pattern_component_result port; + url_pattern_component_result pathname; + url_pattern_component_result search; + url_pattern_component_result hash; +}; + +struct url_pattern_options { + bool ignore_case = false; + +#if ADA_TESTING + friend void PrintTo(const url_pattern_options& options, std::ostream* os) { + *os << "ignore_case: '" << options.ignore_case; + } +#endif // ADA_TESTING +}; + +// URLPattern is a Web Platform standard API for matching URLs against a +// pattern syntax (think of it as a regular expression for URLs). It is +// defined in https://wicg.github.io/urlpattern. +// More information about the URL Pattern syntax can be found at +// https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API +// +// We require all strings to be valid UTF-8: it is the user's responsibility +// to ensure that the provided strings are valid UTF-8. +template +class url_pattern { + public: + url_pattern() = default; /** - * @private - * A URL's username is an ASCII string identifying a username. It is initially - * the empty string. + * If non-null, base_url must pointer at a valid UTF-8 string. + * @see https://urlpattern.spec.whatwg.org/#dom-urlpattern-exec */ - std::string username{}; + result> exec( + const url_pattern_input& input, + const std::string_view* base_url = nullptr); /** - * @private - * A URL's password is an ASCII string identifying a password. It is initially - * the empty string. + * If non-null, base_url must pointer at a valid UTF-8 string. + * @see https://urlpattern.spec.whatwg.org/#dom-urlpattern-test */ - std::string password{}; + result test(const url_pattern_input& input, + const std::string_view* base_url = nullptr); /** - * @private - * A URL's host is null or a host. It is initially null. + * @see https://urlpattern.spec.whatwg.org/#url-pattern-match + * This function expects a valid UTF-8 string if input is a string. */ - std::optional host{}; + result> match( + const url_pattern_input& input, + const std::string_view* base_url_string = nullptr); + + // @see https://urlpattern.spec.whatwg.org/#dom-urlpattern-protocol + [[nodiscard]] std::string_view get_protocol() const ada_lifetime_bound; + // @see https://urlpattern.spec.whatwg.org/#dom-urlpattern-username + [[nodiscard]] std::string_view get_username() const ada_lifetime_bound; + // @see https://urlpattern.spec.whatwg.org/#dom-urlpattern-password + [[nodiscard]] std::string_view get_password() const ada_lifetime_bound; + // @see https://urlpattern.spec.whatwg.org/#dom-urlpattern-hostname + [[nodiscard]] std::string_view get_hostname() const ada_lifetime_bound; + // @see https://urlpattern.spec.whatwg.org/#dom-urlpattern-port + [[nodiscard]] std::string_view get_port() const ada_lifetime_bound; + // @see https://urlpattern.spec.whatwg.org/#dom-urlpattern-pathname + [[nodiscard]] std::string_view get_pathname() const ada_lifetime_bound; + // @see https://urlpattern.spec.whatwg.org/#dom-urlpattern-search + [[nodiscard]] std::string_view get_search() const ada_lifetime_bound; + // @see https://urlpattern.spec.whatwg.org/#dom-urlpattern-hash + [[nodiscard]] std::string_view get_hash() const ada_lifetime_bound; + + // If ignoreCase is true, the JavaScript regular expression created for each + // pattern must use the `vi` flag. Otherwise, they must use the `v` flag. + [[nodiscard]] bool ignore_case() const; + + // @see https://urlpattern.spec.whatwg.org/#url-pattern-has-regexp-groups + [[nodiscard]] bool has_regexp_groups() const; + +#if ADA_TESTING + friend void PrintTo(const url_pattern& c, std::ostream* os) { + *os << "protocol_component: '" << c.get_protocol() << ", "; + *os << "username_component: '" << c.get_username() << ", "; + *os << "password_component: '" << c.get_password() << ", "; + *os << "hostname_component: '" << c.get_hostname() << ", "; + *os << "port_component: '" << c.get_port() << ", "; + *os << "pathname_component: '" << c.get_pathname() << ", "; + *os << "search_component: '" << c.get_search() << ", "; + *os << "hash_component: '" << c.get_hash(); + } +#endif // ADA_TESTING + + template + friend tl::expected, errors> parser::parse_url_pattern_impl( + std::variant&& input, + const std::string_view* base_url, const url_pattern_options* options); /** * @private - * A URL's port is either null or a 16-bit unsigned integer that identifies a - * networking port. It is initially null. + * We can not make this private due to a LLVM bug. + * Ref: https://github.com/ada-url/ada/pull/859 */ - std::optional port{}; - + url_pattern_component protocol_component{}; /** * @private - * A URL's path is either an ASCII string or a list of zero or more ASCII - * strings, usually identifying a location. + * We can not make this private due to a LLVM bug. + * Ref: https://github.com/ada-url/ada/pull/859 */ - std::string path{}; - + url_pattern_component username_component{}; /** * @private - * A URL's query is either null or an ASCII string. It is initially null. + * We can not make this private due to a LLVM bug. + * Ref: https://github.com/ada-url/ada/pull/859 */ - std::optional query{}; - + url_pattern_component password_component{}; /** * @private - * A URL's fragment is either null or an ASCII string that can be used for - * further processing on the resource the URL's other components identify. It - * is initially null. + * We can not make this private due to a LLVM bug. + * Ref: https://github.com/ada-url/ada/pull/859 */ - std::optional hash{}; - - /** @return true if it has an host but it is the empty string */ - [[nodiscard]] inline bool has_empty_hostname() const noexcept; - /** @return true if the URL has a (non default) port */ - [[nodiscard]] inline bool has_port() const noexcept; - /** @return true if it has a host (included an empty host) */ - [[nodiscard]] inline bool has_hostname() const noexcept; - [[nodiscard]] bool has_valid_domain() const noexcept override; - + url_pattern_component hostname_component{}; /** - * Returns a JSON string representation of this URL. + * @private + * We can not make this private due to a LLVM bug. + * Ref: https://github.com/ada-url/ada/pull/859 */ - [[nodiscard]] std::string to_string() const override; - + url_pattern_component port_component{}; /** - * @see https://url.spec.whatwg.org/#dom-url-href - * @see https://url.spec.whatwg.org/#concept-url-serializer + * @private + * We can not make this private due to a LLVM bug. + * Ref: https://github.com/ada-url/ada/pull/859 */ - [[nodiscard]] ada_really_inline std::string get_href() const noexcept; - + url_pattern_component pathname_component{}; /** - * The origin getter steps are to return the serialization of this's URL's - * origin. [HTML] - * @return a newly allocated string. - * @see https://url.spec.whatwg.org/#concept-url-origin + * @private + * We can not make this private due to a LLVM bug. + * Ref: https://github.com/ada-url/ada/pull/859 */ - [[nodiscard]] std::string get_origin() const noexcept override; - + url_pattern_component search_component{}; /** - * The protocol getter steps are to return this's URL's scheme, followed by - * U+003A (:). - * @return a newly allocated string. - * @see https://url.spec.whatwg.org/#dom-url-protocol + * @private + * We can not make this private due to a LLVM bug. + * Ref: https://github.com/ada-url/ada/pull/859 */ - [[nodiscard]] std::string get_protocol() const noexcept; - + url_pattern_component hash_component{}; /** - * Return url's host, serialized, followed by U+003A (:) and url's port, - * serialized. - * When there is no host, this function returns the empty string. - * @return a newly allocated string. - * @see https://url.spec.whatwg.org/#dom-url-host + * @private + * We can not make this private due to a LLVM bug. + * Ref: https://github.com/ada-url/ada/pull/859 */ - [[nodiscard]] std::string get_host() const noexcept; + bool ignore_case_ = false; +}; +} // namespace ada +#endif // ADA_INCLUDE_URL_PATTERN +#endif +/* end file include/ada/url_pattern.h */ +/* begin file include/ada/url_pattern_helpers.h */ +/** + * @file url_pattern_helpers.h + * @brief Declaration for the URLPattern helpers. + */ +#ifndef ADA_URL_PATTERN_HELPERS_H +#define ADA_URL_PATTERN_HELPERS_H - /** - * Return this's URL's host, serialized. - * When there is no host, this function returns the empty string. - * @return a newly allocated string. - * @see https://url.spec.whatwg.org/#dom-url-hostname - */ - [[nodiscard]] std::string get_hostname() const noexcept; - /** - * The pathname getter steps are to return the result of URL path serializing - * this's URL. - * @return a newly allocated string. - * @see https://url.spec.whatwg.org/#dom-url-pathname - */ - [[nodiscard]] std::string_view get_pathname() const noexcept; +#include +#include +#include - /** - * Compute the pathname length in bytes without instantiating a view or a - * string. - * @return size of the pathname in bytes - * @see https://url.spec.whatwg.org/#dom-url-pathname - */ - [[nodiscard]] ada_really_inline size_t get_pathname_length() const noexcept; +#if ADA_INCLUDE_URL_PATTERN +namespace ada { +enum class errors : uint8_t; +} + +namespace ada::url_pattern_helpers { + +// @see https://urlpattern.spec.whatwg.org/#token +enum class token_type : uint8_t { + INVALID_CHAR, // 0 + OPEN, // 1 + CLOSE, // 2 + REGEXP, // 3 + NAME, // 4 + CHAR, // 5 + ESCAPED_CHAR, // 6 + OTHER_MODIFIER, // 7 + ASTERISK, // 8 + END, // 9 +}; - /** - * Return U+003F (?), followed by this's URL's query. - * @return a newly allocated string. - * @see https://url.spec.whatwg.org/#dom-url-search - */ - [[nodiscard]] std::string get_search() const noexcept; +#ifdef ADA_TESTING +std::string to_string(token_type type); +#endif // ADA_TESTING - /** - * The username getter steps are to return this's URL's username. - * @return a constant reference to the underlying string. - * @see https://url.spec.whatwg.org/#dom-url-username - */ - [[nodiscard]] const std::string& get_username() const noexcept; +// @see https://urlpattern.spec.whatwg.org/#tokenize-policy +enum class token_policy { + strict, + lenient, +}; - /** - * @return Returns true on successful operation. - * @see https://url.spec.whatwg.org/#dom-url-username - */ - bool set_username(std::string_view input); +// @see https://urlpattern.spec.whatwg.org/#tokens +class token { + public: + token(token_type _type, size_t _index, std::string&& _value) + : type(_type), index(_index), value(std::move(_value)) {} - /** - * @return Returns true on success. - * @see https://url.spec.whatwg.org/#dom-url-password - */ - bool set_password(std::string_view input); + // A token has an associated type, a string, initially "invalid-char". + token_type type = token_type::INVALID_CHAR; - /** - * @return Returns true on success. - * @see https://url.spec.whatwg.org/#dom-url-port - */ - bool set_port(std::string_view input); + // A token has an associated index, a number, initially 0. It is the position + // of the first code point in the pattern string represented by the token. + size_t index = 0; - /** - * This function always succeeds. - * @see https://url.spec.whatwg.org/#dom-url-hash - */ - void set_hash(std::string_view input); + // A token has an associated value, a string, initially the empty string. It + // contains the code points from the pattern string represented by the token. + std::string value{}; +}; - /** - * This function always succeeds. - * @see https://url.spec.whatwg.org/#dom-url-search - */ - void set_search(std::string_view input); +// @see https://urlpattern.spec.whatwg.org/#pattern-parser +template +class url_pattern_parser { + public: + url_pattern_parser(F& encoding_callback_, + std::string_view segment_wildcard_regexp_) + : encoding_callback(encoding_callback_), + segment_wildcard_regexp(segment_wildcard_regexp_) {} + + bool can_continue() const { return index < tokens.size(); } + + // @see https://urlpattern.spec.whatwg.org/#try-to-consume-a-token + token* try_consume_token(token_type type); + // @see https://urlpattern.spec.whatwg.org/#try-to-consume-a-modifier-token + token* try_consume_modifier_token(); + // @see + // https://urlpattern.spec.whatwg.org/#try-to-consume-a-regexp-or-wildcard-token + token* try_consume_regexp_or_wildcard_token(const token* name_token); + // @see https://urlpattern.spec.whatwg.org/#consume-text + std::string consume_text(); + // @see https://urlpattern.spec.whatwg.org/#consume-a-required-token + bool consume_required_token(token_type type); + // @see + // https://urlpattern.spec.whatwg.org/#maybe-add-a-part-from-the-pending-fixed-value + std::optional maybe_add_part_from_the_pending_fixed_value() + ada_warn_unused; + // @see https://urlpattern.spec.whatwg.org/#add-a-part + std::optional add_part(std::string_view prefix, token* name_token, + token* regexp_or_wildcard_token, + std::string_view suyffix, + token* modifier_token) ada_warn_unused; + + std::vector tokens{}; + F& encoding_callback; + std::string segment_wildcard_regexp; + std::vector parts{}; + std::string pending_fixed_value{}; + size_t index = 0; + size_t next_numeric_name = 0; +}; - /** - * @return Returns true on success. - * @see https://url.spec.whatwg.org/#dom-url-search - */ - bool set_pathname(std::string_view input); +// @see https://urlpattern.spec.whatwg.org/#tokenizer +class Tokenizer { + public: + explicit Tokenizer(std::string_view new_input, token_policy new_policy) + : input(new_input), policy(new_policy) {} - /** - * @return Returns true on success. - * @see https://url.spec.whatwg.org/#dom-url-host - */ - bool set_host(std::string_view input); + // @see https://urlpattern.spec.whatwg.org/#get-the-next-code-point + constexpr void get_next_code_point(); - /** - * @return Returns true on success. - * @see https://url.spec.whatwg.org/#dom-url-hostname - */ - bool set_hostname(std::string_view input); + // @see https://urlpattern.spec.whatwg.org/#seek-and-get-the-next-code-point + constexpr void seek_and_get_next_code_point(size_t index); - /** - * @return Returns true on success. - * @see https://url.spec.whatwg.org/#dom-url-protocol - */ - bool set_protocol(std::string_view input); + // @see https://urlpattern.spec.whatwg.org/#add-a-token - /** - * @see https://url.spec.whatwg.org/#dom-url-href - */ - bool set_href(std::string_view input); + void add_token(token_type type, size_t next_position, size_t value_position, + size_t value_length); - /** - * The password getter steps are to return this's URL's password. - * @return a constant reference to the underlying string. - * @see https://url.spec.whatwg.org/#dom-url-password - */ - [[nodiscard]] const std::string& get_password() const noexcept; + // @see https://urlpattern.spec.whatwg.org/#add-a-token-with-default-length + void add_token_with_default_length(token_type type, size_t next_position, + size_t value_position); - /** - * Return this's URL's port, serialized. - * @return a newly constructed string representing the port. - * @see https://url.spec.whatwg.org/#dom-url-port - */ - [[nodiscard]] std::string get_port() const noexcept; + // @see + // https://urlpattern.spec.whatwg.org/#add-a-token-with-default-position-and-length + void add_token_with_defaults(token_type type); - /** - * Return U+0023 (#), followed by this's URL's fragment. - * @return a newly constructed string representing the hash. - * @see https://url.spec.whatwg.org/#dom-url-hash - */ - [[nodiscard]] std::string get_hash() const noexcept; + // @see https://urlpattern.spec.whatwg.org/#process-a-tokenizing-error + std::optional process_tokenizing_error( + size_t next_position, size_t value_position) ada_warn_unused; - /** - * A URL includes credentials if its username or password is not the empty - * string. - */ - [[nodiscard]] ada_really_inline bool has_credentials() const noexcept; - - /** - * Useful for implementing efficient serialization for the URL. - * - * https://user:pass@example.com:1234/foo/bar?baz#quux - * | | | | ^^^^| | | - * | | | | | | | `----- hash_start - * | | | | | | `--------- search_start - * | | | | | `----------------- pathname_start - * | | | | `--------------------- port - * | | | `----------------------- host_end - * | | `---------------------------------- host_start - * | `--------------------------------------- username_end - * `--------------------------------------------- protocol_end - * - * Inspired after servo/url - * - * @return a newly constructed component. - * - * @see - * https://github.com/servo/rust-url/blob/b65a45515c10713f6d212e6726719a020203cc98/url/src/quirks.rs#L31 - */ - [[nodiscard]] ada_really_inline ada::url_components get_components() - const noexcept; - /** @return true if the URL has a hash component */ - [[nodiscard]] inline bool has_hash() const noexcept override; - /** @return true if the URL has a search component */ - [[nodiscard]] inline bool has_search() const noexcept override; + friend tl::expected, errors> tokenize( + std::string_view input, token_policy policy); private: - friend ada::url ada::parser::parse_url(std::string_view, - const ada::url*); - friend ada::url_aggregator ada::parser::parse_url( - std::string_view, const ada::url_aggregator*); - friend void ada::helpers::strip_trailing_spaces_from_opaque_path( - ada::url& url) noexcept; + // has an associated input, a pattern string, initially the empty string. + std::string input; + // has an associated policy, a tokenize policy, initially "strict". + token_policy policy; + // has an associated token list, a token list, initially an empty list. + std::vector token_list{}; + // has an associated index, a number, initially 0. + size_t index = 0; + // has an associated next index, a number, initially 0. + size_t next_index = 0; + // has an associated code point, a Unicode code point, initially null. + char32_t code_point{}; +}; - friend ada::url ada::parser::parse_url_impl(std::string_view, - const ada::url*); - friend ada::url_aggregator ada::parser::parse_url_impl< - ada::url_aggregator, true>(std::string_view, const ada::url_aggregator*); +// @see https://urlpattern.spec.whatwg.org/#constructor-string-parser +template +struct constructor_string_parser { + explicit constructor_string_parser(std::string_view new_input, + std::vector&& new_token_list) + : input(new_input), token_list(std::move(new_token_list)) {} + // @see https://urlpattern.spec.whatwg.org/#parse-a-constructor-string + static tl::expected parse(std::string_view input); + + // @see https://urlpattern.spec.whatwg.org/#constructor-string-parser-state + enum class State { + INIT, + PROTOCOL, + AUTHORITY, + USERNAME, + PASSWORD, + HOSTNAME, + PORT, + PATHNAME, + SEARCH, + HASH, + DONE, + }; - inline void update_unencoded_base_hash(std::string_view input); - inline void update_base_hostname(std::string_view input); - inline void update_base_search(std::string_view input); - inline void update_base_search(std::string_view input, - const uint8_t query_percent_encode_set[]); - inline void update_base_search(std::optional input); - inline void update_base_pathname(std::string_view input); - inline void update_base_username(std::string_view input); - inline void update_base_password(std::string_view input); - inline void update_base_port(std::optional input); + // @see + // https://urlpattern.spec.whatwg.org/#compute-protocol-matches-a-special-scheme-flag + std::optional compute_protocol_matches_special_scheme_flag(); - /** - * Sets the host or hostname according to override condition. - * Return true on success. - * @see https://url.spec.whatwg.org/#hostname-state - */ - template - bool set_host_or_hostname(std::string_view input); + private: + // @see https://urlpattern.spec.whatwg.org/#rewind + constexpr void rewind(); + + // @see https://urlpattern.spec.whatwg.org/#is-a-hash-prefix + constexpr bool is_hash_prefix(); + + // @see https://urlpattern.spec.whatwg.org/#is-a-search-prefix + constexpr bool is_search_prefix(); + + // @see https://urlpattern.spec.whatwg.org/#change-state + void change_state(State state, size_t skip); + + // @see https://urlpattern.spec.whatwg.org/#is-a-group-open + constexpr bool is_group_open() const; + + // @see https://urlpattern.spec.whatwg.org/#is-a-group-close + constexpr bool is_group_close() const; + + // @see https://urlpattern.spec.whatwg.org/#is-a-protocol-suffix + constexpr bool is_protocol_suffix() const; + + // @see https://urlpattern.spec.whatwg.org/#next-is-authority-slashes + constexpr bool next_is_authority_slashes() const; + + // @see https://urlpattern.spec.whatwg.org/#is-an-identity-terminator + constexpr bool is_an_identity_terminator() const; + + // @see https://urlpattern.spec.whatwg.org/#is-a-pathname-start + constexpr bool is_pathname_start() const; + + // @see https://urlpattern.spec.whatwg.org/#is-a-password-prefix + constexpr bool is_password_prefix() const; + + // @see https://urlpattern.spec.whatwg.org/#is-an-ipv6-open + constexpr bool is_an_ipv6_open() const; + + // @see https://urlpattern.spec.whatwg.org/#is-an-ipv6-close + constexpr bool is_an_ipv6_close() const; + + // @see https://urlpattern.spec.whatwg.org/#is-a-port-prefix + constexpr bool is_port_prefix() const; + + // @see https://urlpattern.spec.whatwg.org/#is-a-non-special-pattern-char + constexpr bool is_non_special_pattern_char(size_t index, + uint32_t value) const; + + // @see https://urlpattern.spec.whatwg.org/#get-a-safe-token + constexpr const token* get_safe_token(size_t index) const; + + // @see https://urlpattern.spec.whatwg.org/#make-a-component-string + std::string make_component_string(); + // has an associated input, a string, which must be set upon creation. + std::string input; + // has an associated token list, a token list, which must be set upon + // creation. + std::vector token_list; + // has an associated result, a URLPatternInit, initially set to a new + // URLPatternInit. + url_pattern_init result{}; + // has an associated component start, a number, initially set to 0. + size_t component_start = 0; + // has an associated token index, a number, initially set to 0. + size_t token_index = 0; + // has an associated token increment, a number, initially set to 1. + size_t token_increment = 1; + // has an associated group depth, a number, initially set to 0. + size_t group_depth = 0; + // has an associated hostname IPv6 bracket depth, a number, initially set to + // 0. + size_t hostname_ipv6_bracket_depth = 0; + // has an associated protocol matches a special scheme flag, a boolean, + // initially set to false. + bool protocol_matches_a_special_scheme_flag = false; + // has an associated state, a string, initially set to "init". + State state = State::INIT; +}; - /** - * Return true on success. - * @see https://url.spec.whatwg.org/#concept-ipv4-parser - */ - [[nodiscard]] bool parse_ipv4(std::string_view input); +// @see https://urlpattern.spec.whatwg.org/#canonicalize-a-protocol +tl::expected canonicalize_protocol(std::string_view input); - /** - * Return true on success. - * @see https://url.spec.whatwg.org/#concept-ipv6-parser - */ - [[nodiscard]] bool parse_ipv6(std::string_view input); +// @see https://wicg.github.io/urlpattern/#canonicalize-a-username +tl::expected canonicalize_username(std::string_view input); - /** - * Return true on success. - * @see https://url.spec.whatwg.org/#concept-opaque-host-parser - */ - [[nodiscard]] bool parse_opaque_host(std::string_view input); +// @see https://wicg.github.io/urlpattern/#canonicalize-a-password +tl::expected canonicalize_password(std::string_view input); - /** - * A URL's scheme is an ASCII string that identifies the type of URL and can - * be used to dispatch a URL for further processing after parsing. It is - * initially the empty string. We only set non_special_scheme when the scheme - * is non-special, otherwise we avoid constructing string. - * - * Special schemes are stored in ada::scheme::details::is_special_list so we - * typically do not need to store them in each url instance. - */ - std::string non_special_scheme{}; +// @see https://wicg.github.io/urlpattern/#canonicalize-a-password +tl::expected canonicalize_hostname(std::string_view input); - /** - * A URL cannot have a username/password/port if its host is null or the empty - * string, or its scheme is "file". - */ - [[nodiscard]] inline bool cannot_have_credentials_or_port() const; +// @see https://wicg.github.io/urlpattern/#canonicalize-an-ipv6-hostname +tl::expected canonicalize_ipv6_hostname( + std::string_view input); - ada_really_inline size_t parse_port( - std::string_view view, bool check_trailing_content) noexcept override; +// @see https://wicg.github.io/urlpattern/#canonicalize-a-port +tl::expected canonicalize_port(std::string_view input); - ada_really_inline size_t parse_port(std::string_view view) noexcept override { - return this->parse_port(view, false); - } +// @see https://wicg.github.io/urlpattern/#canonicalize-a-port +tl::expected canonicalize_port_with_protocol( + std::string_view input, std::string_view protocol); - /** - * Take the scheme from another URL. The scheme string is copied from the - * provided url. - */ - inline void copy_scheme(const ada::url& u); +// @see https://wicg.github.io/urlpattern/#canonicalize-a-pathname +tl::expected canonicalize_pathname(std::string_view input); - /** - * Parse the host from the provided input. We assume that - * the input does not contain spaces or tabs. Control - * characters and spaces are not trimmed (they should have - * been removed if needed). - * Return true on success. - * @see https://url.spec.whatwg.org/#host-parsing - */ - [[nodiscard]] ada_really_inline bool parse_host(std::string_view input); +// @see https://wicg.github.io/urlpattern/#canonicalize-an-opaque-pathname +tl::expected canonicalize_opaque_pathname( + std::string_view input); - template - [[nodiscard]] ada_really_inline bool parse_scheme(std::string_view input); +// @see https://wicg.github.io/urlpattern/#canonicalize-a-search +tl::expected canonicalize_search(std::string_view input); - inline void clear_pathname() override; - inline void clear_search() override; - inline void set_protocol_as_file(); +// @see https://wicg.github.io/urlpattern/#canonicalize-a-hash +tl::expected canonicalize_hash(std::string_view input); - /** - * Parse the path from the provided input. - * Return true on success. Control characters not - * trimmed from the ends (they should have - * been removed if needed). - * - * The input is expected to be UTF-8. - * - * @see https://url.spec.whatwg.org/ - */ - ada_really_inline void parse_path(std::string_view input); +// @see https://urlpattern.spec.whatwg.org/#tokenize +tl::expected, errors> tokenize(std::string_view input, + token_policy policy); - /** - * Set the scheme for this URL. The provided scheme should be a valid - * scheme string, be lower-cased, not contain spaces or tabs. It should - * have no spurious trailing or leading content. - */ - inline void set_scheme(std::string&& new_scheme) noexcept; +// @see https://urlpattern.spec.whatwg.org/#process-a-base-url-string +std::string process_base_url_string(std::string_view input, + url_pattern_init::process_type type); - /** - * Take the scheme from another URL. The scheme string is moved from the - * provided url. - */ - inline void copy_scheme(ada::url&& u) noexcept; +// @see https://urlpattern.spec.whatwg.org/#escape-a-pattern-string +std::string escape_pattern_string(std::string_view input); -}; // struct url +// @see https://urlpattern.spec.whatwg.org/#escape-a-regexp-string +std::string escape_regexp_string(std::string_view input); -inline std::ostream& operator<<(std::ostream& out, const ada::url& u); -} // namespace ada +// @see https://urlpattern.spec.whatwg.org/#is-an-absolute-pathname +constexpr bool is_absolute_pathname( + std::string_view input, url_pattern_init::process_type type) noexcept; -#endif // ADA_URL_H -/* end file include/ada/url.h */ +// @see https://urlpattern.spec.whatwg.org/#parse-a-pattern-string +template +tl::expected, errors> parse_pattern_string( + std::string_view input, url_pattern_compile_component_options& options, + F& encoding_callback); -#include -#include -#if ADA_REGULAR_VISUAL_STUDIO -#include -#endif // ADA_REGULAR_VISUAL_STUDIO +// @see https://urlpattern.spec.whatwg.org/#generate-a-pattern-string +std::string generate_pattern_string( + std::vector& part_list, + url_pattern_compile_component_options& options); -namespace ada { +// @see +// https://urlpattern.spec.whatwg.org/#generate-a-regular-expression-and-name-list +std::tuple> +generate_regular_expression_and_name_list( + const std::vector& part_list, + url_pattern_compile_component_options options); -[[nodiscard]] ada_really_inline bool url_base::is_special() const noexcept { - return type != ada::scheme::NOT_SPECIAL; -} +// @see https://urlpattern.spec.whatwg.org/#hostname-pattern-is-an-ipv6-address +bool is_ipv6_address(std::string_view input) noexcept; -[[nodiscard]] inline uint16_t url_base::get_special_port() const noexcept { - return ada::scheme::get_special_port(type); -} +// @see +// https://urlpattern.spec.whatwg.org/#protocol-component-matches-a-special-scheme +template +bool protocol_component_matches_special_scheme( + ada::url_pattern_component& input); -[[nodiscard]] ada_really_inline uint16_t -url_base::scheme_default_port() const noexcept { - return scheme::get_special_port(type); -} +// @see https://urlpattern.spec.whatwg.org/#convert-a-modifier-to-a-string +std::string convert_modifier_to_string(url_pattern_part_modifier modifier); -} // namespace ada +// @see https://urlpattern.spec.whatwg.org/#generate-a-segment-wildcard-regexp +std::string generate_segment_wildcard_regexp( + url_pattern_compile_component_options options); -#endif // ADA_URL_BASE_INL_H -/* end file include/ada/url_base-inl.h */ -/* begin file include/ada/url-inl.h */ -/** - * @file url-inl.h - * @brief Definitions for the URL - */ -#ifndef ADA_URL_INL_H -#define ADA_URL_INL_H +} // namespace ada::url_pattern_helpers +#endif // ADA_INCLUDE_URL_PATTERN +#endif +/* end file include/ada/url_pattern_helpers.h */ -#include #include -#if ADA_REGULAR_VISUAL_STUDIO -#include -#endif // ADA_REGULAR_VISUAL_STUDIO - -namespace ada { -[[nodiscard]] ada_really_inline bool url::has_credentials() const noexcept { - return !username.empty() || !password.empty(); -} -[[nodiscard]] ada_really_inline bool url::has_port() const noexcept { - return port.has_value(); -} -[[nodiscard]] inline bool url::cannot_have_credentials_or_port() const { - return !host.has_value() || host.value().empty() || - type == ada::scheme::type::FILE; -} -[[nodiscard]] inline bool url::has_empty_hostname() const noexcept { - if (!host.has_value()) { - return false; - } - return host.value().empty(); -} -[[nodiscard]] inline bool url::has_hostname() const noexcept { - return host.has_value(); -} -inline std::ostream& operator<<(std::ostream& out, const ada::url& u) { - return out << u.to_string(); -} - -[[nodiscard]] size_t url::get_pathname_length() const noexcept { - return path.size(); -} - -[[nodiscard]] ada_really_inline ada::url_components url::get_components() - const noexcept { - url_components out{}; - - // protocol ends with ':'. for example: "https:" - out.protocol_end = uint32_t(get_protocol().size()); - - // Trailing index is always the next character of the current one. - size_t running_index = out.protocol_end; - - if (host.has_value()) { - // 2 characters for "//" and 1 character for starting index - out.host_start = out.protocol_end + 2; - - if (has_credentials()) { - out.username_end = uint32_t(out.host_start + username.size()); - - out.host_start += uint32_t(username.size()); - - if (!password.empty()) { - out.host_start += uint32_t(password.size() + 1); - } - - out.host_end = uint32_t(out.host_start + host.value().size()); - } else { - out.username_end = out.host_start; +#include +#include - // Host does not start with "@" if it does not include credentials. - out.host_end = uint32_t(out.host_start + host.value().size()) - 1; +namespace ada::parser { +#if ADA_INCLUDE_URL_PATTERN +template +tl::expected, errors> parse_url_pattern_impl( + std::variant&& input, + const std::string_view* base_url, const url_pattern_options* options) { + // Let init be null. + url_pattern_init init; + + // If input is a scalar value string then: + if (std::holds_alternative(input)) { + // Set init to the result of running parse a constructor string given input. + auto parse_result = + url_pattern_helpers::constructor_string_parser::parse( + std::get(input)); + if (!parse_result) { + ada_log("constructor_string_parser::parse failed"); + return tl::unexpected(parse_result.error()); + } + init = std::move(*parse_result); + // If baseURL is null and init["protocol"] does not exist, then throw a + // TypeError. + if (!base_url && !init.protocol) { + ada_log("base url is null and protocol is not set"); + return tl::unexpected(errors::type_error); } - running_index = out.host_end + 1; + // If baseURL is not null, set init["baseURL"] to baseURL. + if (base_url) { + init.base_url = std::string(*base_url); + } } else { - // Update host start and end date to the same index, since it does not - // exist. - out.host_start = out.protocol_end; - out.host_end = out.host_start; - - if (!has_opaque_path && checkers::begins_with(path, "//")) { - // If url's host is null, url does not have an opaque path, url's path's - // size is greater than 1, and url's path[0] is the empty string, then - // append U+002F (/) followed by U+002E (.) to output. - running_index = out.protocol_end + 2; - } else { - running_index = out.protocol_end; + // Assert: input is a URLPatternInit. + ADA_ASSERT_TRUE(std::holds_alternative(input)); + // If baseURL is not null, then throw a TypeError. + if (base_url) { + ada_log("base url is not null"); + return tl::unexpected(errors::type_error); + } + // Optimization: Avoid copy by moving the input value. + // Set init to input. + init = std::move(std::get(input)); + } + + // Let processedInit be the result of process a URLPatternInit given init, + // "pattern", null, null, null, null, null, null, null, and null. + auto processed_init = + url_pattern_init::process(init, url_pattern_init::process_type::pattern); + if (!processed_init) { + ada_log("url_pattern_init::process failed for init and 'pattern'"); + return tl::unexpected(processed_init.error()); + } + + // For each componentName of "protocol", "username", "password", "hostname", + // "port", "pathname", "search", "hash" If processedInit[componentName] does + // not exist, then set processedInit[componentName] to "*". + ADA_ASSERT_TRUE(processed_init.has_value()); + if (!processed_init->protocol) processed_init->protocol = "*"; + if (!processed_init->username) processed_init->username = "*"; + if (!processed_init->password) processed_init->password = "*"; + if (!processed_init->hostname) processed_init->hostname = "*"; + if (!processed_init->port) processed_init->port = "*"; + if (!processed_init->pathname) processed_init->pathname = "*"; + if (!processed_init->search) processed_init->search = "*"; + if (!processed_init->hash) processed_init->hash = "*"; + + ada_log("-- processed_init->protocol: ", processed_init->protocol.value()); + ada_log("-- processed_init->username: ", processed_init->username.value()); + ada_log("-- processed_init->password: ", processed_init->password.value()); + ada_log("-- processed_init->hostname: ", processed_init->hostname.value()); + ada_log("-- processed_init->port: ", processed_init->port.value()); + ada_log("-- processed_init->pathname: ", processed_init->pathname.value()); + ada_log("-- processed_init->search: ", processed_init->search.value()); + ada_log("-- processed_init->hash: ", processed_init->hash.value()); + + // If processedInit["protocol"] is a special scheme and processedInit["port"] + // is a string which represents its corresponding default port in radix-10 + // using ASCII digits then set processedInit["port"] to the empty string. + // TODO: Optimization opportunity. + if (scheme::is_special(*processed_init->protocol)) { + std::string_view port = processed_init->port.value(); + if (std::to_string(scheme::get_special_port(*processed_init->protocol)) == + port) { + processed_init->port->clear(); } } - if (port.has_value()) { - out.port = *port; - running_index += helpers::fast_digit_count(*port) + 1; // Port omits ':' - } - - out.pathname_start = uint32_t(running_index); - - running_index += path.size(); + // Let urlPattern be a new URL pattern. + url_pattern url_pattern_{}; + + // Set urlPattern's protocol component to the result of compiling a component + // given processedInit["protocol"], canonicalize a protocol, and default + // options. + auto protocol_component = url_pattern_component::compile( + processed_init->protocol.value(), + url_pattern_helpers::canonicalize_protocol, + url_pattern_compile_component_options::DEFAULT); + if (!protocol_component) { + ada_log("url_pattern_component::compile failed for protocol ", + processed_init->protocol.value()); + return tl::unexpected(protocol_component.error()); + } + url_pattern_.protocol_component = std::move(*protocol_component); + + // Set urlPattern's username component to the result of compiling a component + // given processedInit["username"], canonicalize a username, and default + // options. + auto username_component = url_pattern_component::compile( + processed_init->username.value(), + url_pattern_helpers::canonicalize_username, + url_pattern_compile_component_options::DEFAULT); + if (!username_component) { + ada_log("url_pattern_component::compile failed for username ", + processed_init->username.value()); + return tl::unexpected(username_component.error()); + } + url_pattern_.username_component = std::move(*username_component); + + // Set urlPattern's password component to the result of compiling a component + // given processedInit["password"], canonicalize a password, and default + // options. + auto password_component = url_pattern_component::compile( + processed_init->password.value(), + url_pattern_helpers::canonicalize_password, + url_pattern_compile_component_options::DEFAULT); + if (!password_component) { + ada_log("url_pattern_component::compile failed for password ", + processed_init->password.value()); + return tl::unexpected(password_component.error()); + } + url_pattern_.password_component = std::move(*password_component); + + // TODO: Optimization opportunity. The following if statement can be + // simplified. + // If the result running hostname pattern is an IPv6 address given + // processedInit["hostname"] is true, then set urlPattern's hostname component + // to the result of compiling a component given processedInit["hostname"], + // canonicalize an IPv6 hostname, and hostname options. + if (url_pattern_helpers::is_ipv6_address(processed_init->hostname.value())) { + ada_log("processed_init->hostname is ipv6 address"); + // then set urlPattern's hostname component to the result of compiling a + // component given processedInit["hostname"], canonicalize an IPv6 hostname, + // and hostname options. + auto hostname_component = url_pattern_component::compile( + processed_init->hostname.value(), + url_pattern_helpers::canonicalize_ipv6_hostname, + url_pattern_compile_component_options::DEFAULT); + if (!hostname_component) { + ada_log("url_pattern_component::compile failed for ipv6 hostname ", + processed_init->hostname.value()); + return tl::unexpected(hostname_component.error()); + } + url_pattern_.hostname_component = std::move(*hostname_component); + } else { + // Otherwise, set urlPattern's hostname component to the result of compiling + // a component given processedInit["hostname"], canonicalize a hostname, and + // hostname options. + auto hostname_component = url_pattern_component::compile( + processed_init->hostname.value(), + url_pattern_helpers::canonicalize_hostname, + url_pattern_compile_component_options::HOSTNAME); + if (!hostname_component) { + ada_log("url_pattern_component::compile failed for hostname ", + processed_init->hostname.value()); + return tl::unexpected(hostname_component.error()); + } + url_pattern_.hostname_component = std::move(*hostname_component); + } + + // Set urlPattern's port component to the result of compiling a component + // given processedInit["port"], canonicalize a port, and default options. + auto port_component = url_pattern_component::compile( + processed_init->port.value(), url_pattern_helpers::canonicalize_port, + url_pattern_compile_component_options::DEFAULT); + if (!port_component) { + ada_log("url_pattern_component::compile failed for port ", + processed_init->port.value()); + return tl::unexpected(port_component.error()); + } + url_pattern_.port_component = std::move(*port_component); + + // Let compileOptions be a copy of the default options with the ignore case + // property set to options["ignoreCase"]. + auto compile_options = url_pattern_compile_component_options::DEFAULT; + if (options) { + compile_options.ignore_case = options->ignore_case; + } + + // TODO: Optimization opportunity: Simplify this if statement. + // If the result of running protocol component matches a special scheme given + // urlPattern's protocol component is true, then: + if (url_pattern_helpers::protocol_component_matches_special_scheme< + regex_provider>(url_pattern_.protocol_component)) { + // Let pathCompileOptions be copy of the pathname options with the ignore + // case property set to options["ignoreCase"]. + auto path_compile_options = url_pattern_compile_component_options::PATHNAME; + if (options) { + path_compile_options.ignore_case = options->ignore_case; + } - if (query.has_value()) { - out.search_start = uint32_t(running_index); - running_index += get_search().size(); - if (get_search().empty()) { - running_index++; + // Set urlPattern's pathname component to the result of compiling a + // component given processedInit["pathname"], canonicalize a pathname, and + // pathCompileOptions. + auto pathname_component = url_pattern_component::compile( + processed_init->pathname.value(), + url_pattern_helpers::canonicalize_pathname, path_compile_options); + if (!pathname_component) { + ada_log("url_pattern_component::compile failed for pathname ", + processed_init->pathname.value()); + return tl::unexpected(pathname_component.error()); + } + url_pattern_.pathname_component = std::move(*pathname_component); + } else { + // Otherwise set urlPattern's pathname component to the result of compiling + // a component given processedInit["pathname"], canonicalize an opaque + // pathname, and compileOptions. + auto pathname_component = url_pattern_component::compile( + processed_init->pathname.value(), + url_pattern_helpers::canonicalize_opaque_pathname, compile_options); + if (!pathname_component) { + ada_log("url_pattern_component::compile failed for opaque pathname ", + processed_init->pathname.value()); + return tl::unexpected(pathname_component.error()); } + url_pattern_.pathname_component = std::move(*pathname_component); } - if (hash.has_value()) { - out.hash_start = uint32_t(running_index); + // Set urlPattern's search component to the result of compiling a component + // given processedInit["search"], canonicalize a search, and compileOptions. + auto search_component = url_pattern_component::compile( + processed_init->search.value(), url_pattern_helpers::canonicalize_search, + compile_options); + if (!search_component) { + ada_log("url_pattern_component::compile failed for search ", + processed_init->search.value()); + return tl::unexpected(search_component.error()); } + url_pattern_.search_component = std::move(*search_component); - return out; + // Set urlPattern's hash component to the result of compiling a component + // given processedInit["hash"], canonicalize a hash, and compileOptions. + auto hash_component = url_pattern_component::compile( + processed_init->hash.value(), url_pattern_helpers::canonicalize_hash, + compile_options); + if (!hash_component) { + ada_log("url_pattern_component::compile failed for hash ", + processed_init->hash.value()); + return tl::unexpected(hash_component.error()); + } + url_pattern_.hash_component = std::move(*hash_component); + + // Return urlPattern. + return url_pattern_; } +#endif // ADA_INCLUDE_URL_PATTERN -inline void url::update_base_hostname(std::string_view input) { host = input; } +} // namespace ada::parser + +#endif // ADA_PARSER_INL_H +/* end file include/ada/parser-inl.h */ +/* begin file include/ada/scheme-inl.h */ +/** + * @file scheme-inl.h + * @brief Definitions for the URL scheme. + */ +#ifndef ADA_SCHEME_INL_H +#define ADA_SCHEME_INL_H + + +namespace ada::scheme { + +/** + * @namespace ada::scheme::details + * @brief Includes the definitions for scheme specific entities + */ +namespace details { +// for use with is_special and get_special_port +// Spaces, if present, are removed from URL. +constexpr std::string_view is_special_list[] = {"http", " ", "https", "ws", + "ftp", "wss", "file", " "}; +// for use with get_special_port +constexpr uint16_t special_ports[] = {80, 0, 443, 80, 21, 443, 0, 0}; +} // namespace details + +/**** + * @private + * In is_special, get_scheme_type, and get_special_port, we + * use a standard hashing technique to find the index of the scheme in + * the is_special_list. The hashing technique is based on the size of + * the scheme and the first character of the scheme. It ensures that we + * do at most one string comparison per call. If the protocol is + * predictible (e.g., it is always "http"), we can get a better average + * performance by using a simpler approach where we loop and compare + * scheme with all possible protocols starting with the most likely + * protocol. Doing multiple comparisons may have a poor worst case + * performance, however. In this instance, we choose a potentially + * slightly lower best-case performance for a better worst-case + * performance. We can revisit this choice at any time. + * + * Reference: + * Schmidt, Douglas C. "Gperf: A perfect hash function generator." + * More C++ gems 17 (2000). + * + * Reference: https://en.wikipedia.org/wiki/Perfect_hash_function + * + * Reference: https://github.com/ada-url/ada/issues/617 + ****/ + +ada_really_inline constexpr bool is_special(std::string_view scheme) { + if (scheme.empty()) { + return false; + } + int hash_value = (2 * scheme.size() + (unsigned)(scheme[0])) & 7; + const std::string_view target = details::is_special_list[hash_value]; + return (target[0] == scheme[0]) && (target.substr(1) == scheme.substr(1)); +} +constexpr uint16_t get_special_port(std::string_view scheme) noexcept { + if (scheme.empty()) { + return 0; + } + int hash_value = (2 * scheme.size() + (unsigned)(scheme[0])) & 7; + const std::string_view target = details::is_special_list[hash_value]; + if ((target[0] == scheme[0]) && (target.substr(1) == scheme.substr(1))) { + return details::special_ports[hash_value]; + } else { + return 0; + } +} +constexpr uint16_t get_special_port(ada::scheme::type type) noexcept { + return details::special_ports[int(type)]; +} +constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept { + if (scheme.empty()) { + return ada::scheme::NOT_SPECIAL; + } + int hash_value = (2 * scheme.size() + (unsigned)(scheme[0])) & 7; + const std::string_view target = details::is_special_list[hash_value]; + if ((target[0] == scheme[0]) && (target.substr(1) == scheme.substr(1))) { + return ada::scheme::type(hash_value); + } else { + return ada::scheme::NOT_SPECIAL; + } +} + +} // namespace ada::scheme + +#endif // ADA_SCHEME_INL_H +/* end file include/ada/scheme-inl.h */ +/* begin file include/ada/serializers.h */ +/** + * @file serializers.h + * @brief Definitions for the URL serializers. + */ +#ifndef ADA_SERIALIZERS_H +#define ADA_SERIALIZERS_H + + +#include +#include + +/** + * @namespace ada::serializers + * @brief Includes the definitions for URL serializers + */ +namespace ada::serializers { + +/** + * Finds and returns the longest sequence of 0 values in a ipv6 input. + */ +void find_longest_sequence_of_ipv6_pieces( + const std::array& address, size_t& compress, + size_t& compress_length) noexcept; + +/** + * Serializes an ipv6 address. + * @details An IPv6 address is a 128-bit unsigned integer that identifies a + * network address. + * @see https://url.spec.whatwg.org/#concept-ipv6-serializer + */ +std::string ipv6(const std::array& address) noexcept; + +/** + * Serializes an ipv4 address. + * @details An IPv4 address is a 32-bit unsigned integer that identifies a + * network address. + * @see https://url.spec.whatwg.org/#concept-ipv4-serializer + */ +std::string ipv4(uint64_t address) noexcept; + +} // namespace ada::serializers + +#endif // ADA_SERIALIZERS_H +/* end file include/ada/serializers.h */ +/* begin file include/ada/state.h */ +/** + * @file state.h + * @brief Definitions for the states of the URL state machine. + */ +#ifndef ADA_STATE_H +#define ADA_STATE_H + + +#include + +namespace ada { + +/** + * @see https://url.spec.whatwg.org/#url-parsing + */ +enum class state { + /** + * @see https://url.spec.whatwg.org/#authority-state + */ + AUTHORITY, + + /** + * @see https://url.spec.whatwg.org/#scheme-start-state + */ + SCHEME_START, + + /** + * @see https://url.spec.whatwg.org/#scheme-state + */ + SCHEME, + + /** + * @see https://url.spec.whatwg.org/#host-state + */ + HOST, + + /** + * @see https://url.spec.whatwg.org/#no-scheme-state + */ + NO_SCHEME, + + /** + * @see https://url.spec.whatwg.org/#fragment-state + */ + FRAGMENT, + + /** + * @see https://url.spec.whatwg.org/#relative-state + */ + RELATIVE_SCHEME, + + /** + * @see https://url.spec.whatwg.org/#relative-slash-state + */ + RELATIVE_SLASH, + + /** + * @see https://url.spec.whatwg.org/#file-state + */ + FILE, + + /** + * @see https://url.spec.whatwg.org/#file-host-state + */ + FILE_HOST, + + /** + * @see https://url.spec.whatwg.org/#file-slash-state + */ + FILE_SLASH, + + /** + * @see https://url.spec.whatwg.org/#path-or-authority-state + */ + PATH_OR_AUTHORITY, + + /** + * @see https://url.spec.whatwg.org/#special-authority-ignore-slashes-state + */ + SPECIAL_AUTHORITY_IGNORE_SLASHES, + + /** + * @see https://url.spec.whatwg.org/#special-authority-slashes-state + */ + SPECIAL_AUTHORITY_SLASHES, + + /** + * @see https://url.spec.whatwg.org/#special-relative-or-authority-state + */ + SPECIAL_RELATIVE_OR_AUTHORITY, + + /** + * @see https://url.spec.whatwg.org/#query-state + */ + QUERY, + + /** + * @see https://url.spec.whatwg.org/#path-state + */ + PATH, + + /** + * @see https://url.spec.whatwg.org/#path-start-state + */ + PATH_START, + + /** + * @see https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state + */ + OPAQUE_PATH, + + /** + * @see https://url.spec.whatwg.org/#port-state + */ + PORT, +}; + +/** + * Stringify a URL state machine state. + */ +ada_warn_unused std::string to_string(ada::state s); + +} // namespace ada + +#endif // ADA_STATE_H +/* end file include/ada/state.h */ +/* begin file include/ada/unicode.h */ +/** + * @file unicode.h + * @brief Definitions for all unicode specific functions. + */ +#ifndef ADA_UNICODE_H +#define ADA_UNICODE_H + + +#include +#include +#include + +/** + * Unicode operations. These functions are not part of our public API and may + * change at any time. + * + * @private + * @namespace ada::unicode + * @brief Includes the definitions for unicode operations + */ +namespace ada::unicode { + +/** + * @private + * We receive a UTF-8 string representing a domain name. + * If the string is percent encoded, we apply percent decoding. + * + * Given a domain, we need to identify its labels. + * They are separated by label-separators: + * + * U+002E (.) FULL STOP + * U+FF0E FULLWIDTH FULL STOP + * U+3002 IDEOGRAPHIC FULL STOP + * U+FF61 HALFWIDTH IDEOGRAPHIC FULL STOP + * + * They are all mapped to U+002E. + * + * We process each label into a string that should not exceed 63 octets. + * If the string is already punycode (starts with "xn--"), then we must + * scan it to look for unallowed code points. + * Otherwise, if the string is not pure ASCII, we need to transcode it + * to punycode by following RFC 3454 which requires us to + * - Map characters (see section 3), + * - Normalize (see section 4), + * - Reject forbidden characters, + * - Check for right-to-left characters and if so, check all requirements (see + * section 6), + * - Optionally reject based on unassigned code points (section 7). + * + * The Unicode standard provides a table of code points with a mapping, a list + * of forbidden code points and so forth. This table is subject to change and + * will vary based on the implementation. For Unicode 15, the table is at + * https://www.unicode.org/Public/idna/15.0.0/IdnaMappingTable.txt + * If you use ICU, they parse this table and map it to code using a Python + * script. + * + * The resulting strings should not exceed 255 octets according to RFC 1035 + * section 2.3.4. ICU checks for label size and domain size, but these errors + * are ignored. + * + * @see https://url.spec.whatwg.org/#concept-domain-to-ascii + * + */ +bool to_ascii(std::optional& out, std::string_view plain, + size_t first_percent); + +/** + * @private + * Checks if the input has tab or newline characters. + * + * @attention The has_tabs_or_newline function is a bottleneck and it is simple + * enough that compilers like GCC can 'autovectorize it'. + */ +ada_really_inline bool has_tabs_or_newline( + std::string_view user_input) noexcept; + +/** + * @private + * Checks if the input is a forbidden host code point. + * @see https://url.spec.whatwg.org/#forbidden-host-code-point + */ +ada_really_inline constexpr bool is_forbidden_host_code_point(char c) noexcept; + +/** + * @private + * Checks if the input contains a forbidden domain code point. + * @see https://url.spec.whatwg.org/#forbidden-domain-code-point + */ +ada_really_inline constexpr bool contains_forbidden_domain_code_point( + const char* input, size_t length) noexcept; + +/** + * @private + * Checks if the input contains a forbidden domain code point in which case + * the first bit is set to 1. If the input contains an upper case ASCII letter, + * then the second bit is set to 1. + * @see https://url.spec.whatwg.org/#forbidden-domain-code-point + */ +ada_really_inline constexpr uint8_t +contains_forbidden_domain_code_point_or_upper(const char* input, + size_t length) noexcept; + +/** + * @private + * Checks if the input is a forbidden domain code point. + * @see https://url.spec.whatwg.org/#forbidden-domain-code-point + */ +ada_really_inline constexpr bool is_forbidden_domain_code_point( + char c) noexcept; + +/** + * @private + * Checks if the input is alphanumeric, '+', '-' or '.' + */ +ada_really_inline constexpr bool is_alnum_plus(char c) noexcept; + +/** + * @private + * @details An ASCII hex digit is an ASCII upper hex digit or ASCII lower hex + * digit. An ASCII upper hex digit is an ASCII digit or a code point in the + * range U+0041 (A) to U+0046 (F), inclusive. An ASCII lower hex digit is an + * ASCII digit or a code point in the range U+0061 (a) to U+0066 (f), inclusive. + */ +ada_really_inline constexpr bool is_ascii_hex_digit(char c) noexcept; + +/** + * @private + * An ASCII digit is a code point in the range U+0030 (0) to U+0039 (9), + * inclusive. + */ +ada_really_inline constexpr bool is_ascii_digit(char c) noexcept; + +/** + * @private + * @details If a char is between U+0000 and U+007F inclusive, then it's an ASCII + * character. + */ +ada_really_inline constexpr bool is_ascii(char32_t c) noexcept; + +/** + * @private + * Checks if the input is a C0 control or space character. + * + * @details A C0 control or space is a C0 control or U+0020 SPACE. + * A C0 control is a code point in the range U+0000 NULL to U+001F INFORMATION + * SEPARATOR ONE, inclusive. + */ +ada_really_inline constexpr bool is_c0_control_or_space(char c) noexcept; + +/** + * @private + * Checks if the input is a ASCII tab or newline character. + * + * @details An ASCII tab or newline is U+0009 TAB, U+000A LF, or U+000D CR. + */ +ada_really_inline constexpr bool is_ascii_tab_or_newline(char c) noexcept; + +/** + * @private + * @details A double-dot path segment must be ".." or an ASCII case-insensitive + * match for ".%2e", "%2e.", or "%2e%2e". + */ +ada_really_inline constexpr bool is_double_dot_path_segment( + std::string_view input) noexcept; + +/** + * @private + * @details A single-dot path segment must be "." or an ASCII case-insensitive + * match for "%2e". + */ +ada_really_inline constexpr bool is_single_dot_path_segment( + std::string_view input) noexcept; + +/** + * @private + * @details ipv4 character might contain 0-9 or a-f character ranges. + */ +ada_really_inline constexpr bool is_lowercase_hex(char c) noexcept; + +/** + * @private + * @details Convert hex to binary. Caller is responsible to ensure that + * the parameter is an hexadecimal digit (0-9, A-F, a-f). + */ +ada_really_inline unsigned constexpr convert_hex_to_binary(char c) noexcept; + +/** + * @private + * first_percent should be = input.find('%') + * + * @todo It would be faster as noexcept maybe, but it could be unsafe since. + * @author Node.js + * @see https://github.com/nodejs/node/blob/main/src/node_url.cc#L245 + * @see https://encoding.spec.whatwg.org/#utf-8-decode-without-bom + */ +std::string percent_decode(std::string_view input, size_t first_percent); + +/** + * @private + * Returns a percent-encoding string whether percent encoding was needed or not. + * @see https://github.com/nodejs/node/blob/main/src/node_url.cc#L226 + */ +std::string percent_encode(std::string_view input, + const uint8_t character_set[]); +/** + * @private + * Returns a percent-encoded string version of input, while starting the percent + * encoding at the provided index. + * @see https://github.com/nodejs/node/blob/main/src/node_url.cc#L226 + */ +std::string percent_encode(std::string_view input, + const uint8_t character_set[], size_t index); +/** + * @private + * Returns true if percent encoding was needed, in which case, we store + * the percent-encoded content in 'out'. If the boolean 'append' is set to + * true, the content is appended to 'out'. + * If percent encoding is not needed, out is left unchanged. + * @see https://github.com/nodejs/node/blob/main/src/node_url.cc#L226 + */ +template +bool percent_encode(std::string_view input, const uint8_t character_set[], + std::string& out); +/** + * @private + * Returns the index at which percent encoding should start, or (equivalently), + * the length of the prefix that does not require percent encoding. + */ +ada_really_inline size_t percent_encode_index(std::string_view input, + const uint8_t character_set[]); +/** + * @private + * Lowers the string in-place, assuming that the content is ASCII. + * Return true if the content was ASCII. + */ +constexpr bool to_lower_ascii(char* input, size_t length) noexcept; +} // namespace ada::unicode + +#endif // ADA_UNICODE_H +/* end file include/ada/unicode.h */ +/* begin file include/ada/url_base-inl.h */ +/** + * @file url_base-inl.h + * @brief Inline functions for url base + */ +#ifndef ADA_URL_BASE_INL_H +#define ADA_URL_BASE_INL_H + + +#include +#if ADA_REGULAR_VISUAL_STUDIO +#include +#endif // ADA_REGULAR_VISUAL_STUDIO + +namespace ada { + +[[nodiscard]] ada_really_inline constexpr bool url_base::is_special() + const noexcept { + return type != ada::scheme::NOT_SPECIAL; +} + +[[nodiscard]] inline uint16_t url_base::get_special_port() const noexcept { + return ada::scheme::get_special_port(type); +} + +[[nodiscard]] ada_really_inline uint16_t +url_base::scheme_default_port() const noexcept { + return scheme::get_special_port(type); +} + +} // namespace ada + +#endif // ADA_URL_BASE_INL_H +/* end file include/ada/url_base-inl.h */ +/* begin file include/ada/url-inl.h */ +/** + * @file url-inl.h + * @brief Definitions for the URL + */ +#ifndef ADA_URL_INL_H +#define ADA_URL_INL_H + + +#include +#include +#include +#if ADA_REGULAR_VISUAL_STUDIO +#include +#endif // ADA_REGULAR_VISUAL_STUDIO + +namespace ada { +[[nodiscard]] ada_really_inline bool url::has_credentials() const noexcept { + return !username.empty() || !password.empty(); +} +[[nodiscard]] ada_really_inline bool url::has_port() const noexcept { + return port.has_value(); +} +[[nodiscard]] inline bool url::cannot_have_credentials_or_port() const { + return !host.has_value() || host.value().empty() || + type == ada::scheme::type::FILE; +} +[[nodiscard]] inline bool url::has_empty_hostname() const noexcept { + if (!host.has_value()) { + return false; + } + return host.value().empty(); +} +[[nodiscard]] inline bool url::has_hostname() const noexcept { + return host.has_value(); +} +inline std::ostream &operator<<(std::ostream &out, const ada::url &u) { + return out << u.to_string(); +} + +[[nodiscard]] size_t url::get_pathname_length() const noexcept { + return path.size(); +} + +[[nodiscard]] constexpr std::string_view url::get_pathname() const noexcept { + return path; +} + +[[nodiscard]] ada_really_inline ada::url_components url::get_components() + const noexcept { + url_components out{}; + + // protocol ends with ':'. for example: "https:" + out.protocol_end = uint32_t(get_protocol().size()); + + // Trailing index is always the next character of the current one. + // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores) + size_t running_index = out.protocol_end; + + if (host.has_value()) { + // 2 characters for "//" and 1 character for starting index + out.host_start = out.protocol_end + 2; + + if (has_credentials()) { + out.username_end = uint32_t(out.host_start + username.size()); + + out.host_start += uint32_t(username.size()); + + if (!password.empty()) { + out.host_start += uint32_t(password.size() + 1); + } + + out.host_end = uint32_t(out.host_start + host.value().size()); + } else { + out.username_end = out.host_start; + + // Host does not start with "@" if it does not include credentials. + out.host_end = uint32_t(out.host_start + host.value().size()) - 1; + } + + running_index = out.host_end + 1; + } else { + // Update host start and end date to the same index, since it does not + // exist. + out.host_start = out.protocol_end; + out.host_end = out.host_start; + + if (!has_opaque_path && path.starts_with("//")) { + // If url's host is null, url does not have an opaque path, url's path's + // size is greater than 1, and url's path[0] is the empty string, then + // append U+002F (/) followed by U+002E (.) to output. + running_index = out.protocol_end + 2; + } else { + running_index = out.protocol_end; + } + } + + if (port.has_value()) { + out.port = *port; + running_index += helpers::fast_digit_count(*port) + 1; // Port omits ':' + } + + out.pathname_start = uint32_t(running_index); + + running_index += path.size(); + + if (query.has_value()) { + out.search_start = uint32_t(running_index); + running_index += get_search().size(); + if (get_search().empty()) { + running_index++; + } + } + + if (hash.has_value()) { + out.hash_start = uint32_t(running_index); + } + + return out; +} + +inline void url::update_base_hostname(std::string_view input) { host = input; } inline void url::update_unencoded_base_hash(std::string_view input) { // We do the percent encoding @@ -5763,130 +6714,556 @@ inline void url::update_unencoded_base_hash(std::string_view input) { ada::character_sets::FRAGMENT_PERCENT_ENCODE); } -inline void url::update_base_search(std::string_view input, - const uint8_t query_percent_encode_set[]) { - query = ada::unicode::percent_encode(input, query_percent_encode_set); +inline void url::update_base_search(std::string_view input, + const uint8_t query_percent_encode_set[]) { + query = ada::unicode::percent_encode(input, query_percent_encode_set); +} + +inline void url::update_base_search(std::optional &&input) { + query = std::move(input); +} + +inline void url::update_base_pathname(const std::string_view input) { + path = input; +} + +inline void url::update_base_username(const std::string_view input) { + username = input; +} + +inline void url::update_base_password(const std::string_view input) { + password = input; +} + +inline void url::update_base_port(std::optional input) { + port = input; +} + +constexpr void url::clear_pathname() { path.clear(); } + +constexpr void url::clear_search() { query = std::nullopt; } + +[[nodiscard]] constexpr bool url::has_hash() const noexcept { + return hash.has_value(); +} + +[[nodiscard]] constexpr bool url::has_search() const noexcept { + return query.has_value(); +} + +constexpr void url::set_protocol_as_file() { type = ada::scheme::type::FILE; } + +inline void url::set_scheme(std::string &&new_scheme) noexcept { + type = ada::scheme::get_scheme_type(new_scheme); + // We only move the 'scheme' if it is non-special. + if (!is_special()) { + non_special_scheme = std::move(new_scheme); + } +} + +constexpr void url::copy_scheme(ada::url &&u) noexcept { + non_special_scheme = u.non_special_scheme; + type = u.type; +} + +constexpr void url::copy_scheme(const ada::url &u) { + non_special_scheme = u.non_special_scheme; + type = u.type; +} + +[[nodiscard]] ada_really_inline std::string url::get_href() const noexcept { + std::string output = get_protocol(); + + if (host.has_value()) { + output += "//"; + if (has_credentials()) { + output += username; + if (!password.empty()) { + output += ":" + get_password(); + } + output += "@"; + } + output += host.value(); + if (port.has_value()) { + output += ":" + get_port(); + } + } else if (!has_opaque_path && path.starts_with("//")) { + // If url's host is null, url does not have an opaque path, url's path's + // size is greater than 1, and url's path[0] is the empty string, then + // append U+002F (/) followed by U+002E (.) to output. + output += "/."; + } + output += path; + if (query.has_value()) { + output += "?" + query.value(); + } + if (hash.has_value()) { + output += "#" + hash.value(); + } + return output; +} + +ada_really_inline size_t url::parse_port(std::string_view view, + bool check_trailing_content) noexcept { + ada_log("parse_port('", view, "') ", view.size()); + if (!view.empty() && view[0] == '-') { + ada_log("parse_port: view[0] == '0' && view.size() > 1"); + is_valid = false; + return 0; + } + uint16_t parsed_port{}; + auto r = std::from_chars(view.data(), view.data() + view.size(), parsed_port); + if (r.ec == std::errc::result_out_of_range) { + ada_log("parse_port: r.ec == std::errc::result_out_of_range"); + is_valid = false; + return 0; + } + ada_log("parse_port: ", parsed_port); + const auto consumed = size_t(r.ptr - view.data()); + ada_log("parse_port: consumed ", consumed); + if (check_trailing_content) { + is_valid &= + (consumed == view.size() || view[consumed] == '/' || + view[consumed] == '?' || (is_special() && view[consumed] == '\\')); + } + ada_log("parse_port: is_valid = ", is_valid); + if (is_valid) { + // scheme_default_port can return 0, and we should allow 0 as a base port. + auto default_port = scheme_default_port(); + bool is_port_valid = (default_port == 0 && parsed_port == 0) || + (default_port != parsed_port); + port = (r.ec == std::errc() && is_port_valid) ? std::optional(parsed_port) + : std::nullopt; + } + return consumed; +} + +} // namespace ada + +#endif // ADA_URL_H +/* end file include/ada/url-inl.h */ +/* begin file include/ada/url_components-inl.h */ +/** + * @file url_components.h + * @brief Declaration for the URL Components + */ +#ifndef ADA_URL_COMPONENTS_INL_H +#define ADA_URL_COMPONENTS_INL_H + + +namespace ada { + +[[nodiscard]] constexpr bool url_components::check_offset_consistency() + const noexcept { + /** + * https://user:pass@example.com:1234/foo/bar?baz#quux + * | | | | ^^^^| | | + * | | | | | | | `----- hash_start + * | | | | | | `--------- search_start + * | | | | | `----------------- pathname_start + * | | | | `--------------------- port + * | | | `----------------------- host_end + * | | `---------------------------------- host_start + * | `--------------------------------------- username_end + * `--------------------------------------------- protocol_end + */ + // These conditions can be made more strict. + if (protocol_end == url_components::omitted) { + return false; + } + uint32_t index = protocol_end; + + if (username_end == url_components::omitted) { + return false; + } + if (username_end < index) { + return false; + } + index = username_end; + + if (host_start == url_components::omitted) { + return false; + } + if (host_start < index) { + return false; + } + index = host_start; + + if (port != url_components::omitted) { + if (port > 0xffff) { + return false; + } + uint32_t port_length = helpers::fast_digit_count(port) + 1; + if (index + port_length < index) { + return false; + } + index += port_length; + } + + if (pathname_start == url_components::omitted) { + return false; + } + if (pathname_start < index) { + return false; + } + index = pathname_start; + + if (search_start != url_components::omitted) { + if (search_start < index) { + return false; + } + index = search_start; + } + + if (hash_start != url_components::omitted) { + if (hash_start < index) { + return false; + } + } + + return true; } -inline void url::update_base_search(std::optional input) { - query = input; -} +} // namespace ada +#endif +/* end file include/ada/url_components-inl.h */ +/* begin file include/ada/url_aggregator.h */ +/** + * @file url_aggregator.h + * @brief Declaration for the basic URL definitions + */ +#ifndef ADA_URL_AGGREGATOR_H +#define ADA_URL_AGGREGATOR_H + +#include +#include +#include +#include + + +namespace ada { + +namespace parser {} + +/** + * @brief Lightweight URL struct. + * + * @details The url_aggregator class aims to minimize temporary memory + * allocation while representing a parsed URL. Internally, it contains a single + * normalized URL (the href), and it makes available the components, mostly + * using std::string_view. + */ +struct url_aggregator : url_base { + url_aggregator() = default; + url_aggregator(const url_aggregator &u) = default; + url_aggregator(url_aggregator &&u) noexcept = default; + url_aggregator &operator=(url_aggregator &&u) noexcept = default; + url_aggregator &operator=(const url_aggregator &u) = default; + ~url_aggregator() override = default; + + bool set_href(std::string_view input); + bool set_host(std::string_view input); + bool set_hostname(std::string_view input); + bool set_protocol(std::string_view input); + bool set_username(std::string_view input); + bool set_password(std::string_view input); + bool set_port(std::string_view input); + bool set_pathname(std::string_view input); + void set_search(std::string_view input); + void set_hash(std::string_view input); + + [[nodiscard]] bool has_valid_domain() const noexcept override; + /** + * The origin getter steps are to return the serialization of this's URL's + * origin. [HTML] + * @return a newly allocated string. + * @see https://url.spec.whatwg.org/#concept-url-origin + */ + [[nodiscard]] std::string get_origin() const noexcept override; + /** + * Return the normalized string. + * This function does not allocate memory. + * It is highly efficient. + * @return a constant reference to the underlying normalized URL. + * @see https://url.spec.whatwg.org/#dom-url-href + * @see https://url.spec.whatwg.org/#concept-url-serializer + */ + [[nodiscard]] constexpr std::string_view get_href() const noexcept + ada_lifetime_bound; + /** + * The username getter steps are to return this's URL's username. + * This function does not allocate memory. + * @return a lightweight std::string_view. + * @see https://url.spec.whatwg.org/#dom-url-username + */ + [[nodiscard]] std::string_view get_username() const noexcept + ada_lifetime_bound; + /** + * The password getter steps are to return this's URL's password. + * This function does not allocate memory. + * @return a lightweight std::string_view. + * @see https://url.spec.whatwg.org/#dom-url-password + */ + [[nodiscard]] std::string_view get_password() const noexcept + ada_lifetime_bound; + /** + * Return this's URL's port, serialized. + * This function does not allocate memory. + * @return a lightweight std::string_view. + * @see https://url.spec.whatwg.org/#dom-url-port + */ + [[nodiscard]] std::string_view get_port() const noexcept ada_lifetime_bound; + /** + * Return U+0023 (#), followed by this's URL's fragment. + * This function does not allocate memory. + * @return a lightweight std::string_view.. + * @see https://url.spec.whatwg.org/#dom-url-hash + */ + [[nodiscard]] std::string_view get_hash() const noexcept ada_lifetime_bound; + /** + * Return url's host, serialized, followed by U+003A (:) and url's port, + * serialized. + * This function does not allocate memory. + * When there is no host, this function returns the empty view. + * @return a lightweight std::string_view. + * @see https://url.spec.whatwg.org/#dom-url-host + */ + [[nodiscard]] std::string_view get_host() const noexcept ada_lifetime_bound; + /** + * Return this's URL's host, serialized. + * This function does not allocate memory. + * When there is no host, this function returns the empty view. + * @return a lightweight std::string_view. + * @see https://url.spec.whatwg.org/#dom-url-hostname + */ + [[nodiscard]] std::string_view get_hostname() const noexcept + ada_lifetime_bound; + /** + * The pathname getter steps are to return the result of URL path serializing + * this's URL. + * This function does not allocate memory. + * @return a lightweight std::string_view. + * @see https://url.spec.whatwg.org/#dom-url-pathname + */ + [[nodiscard]] constexpr std::string_view get_pathname() const noexcept + ada_lifetime_bound; + /** + * Compute the pathname length in bytes without instantiating a view or a + * string. + * @return size of the pathname in bytes + * @see https://url.spec.whatwg.org/#dom-url-pathname + */ + [[nodiscard]] ada_really_inline uint32_t get_pathname_length() const noexcept; + /** + * Return U+003F (?), followed by this's URL's query. + * This function does not allocate memory. + * @return a lightweight std::string_view. + * @see https://url.spec.whatwg.org/#dom-url-search + */ + [[nodiscard]] std::string_view get_search() const noexcept ada_lifetime_bound; + /** + * The protocol getter steps are to return this's URL's scheme, followed by + * U+003A (:). + * This function does not allocate memory. + * @return a lightweight std::string_view. + * @see https://url.spec.whatwg.org/#dom-url-protocol + */ + [[nodiscard]] std::string_view get_protocol() const noexcept + ada_lifetime_bound; + + /** + * A URL includes credentials if its username or password is not the empty + * string. + */ + [[nodiscard]] ada_really_inline constexpr bool has_credentials() + const noexcept; + + /** + * Useful for implementing efficient serialization for the URL. + * + * https://user:pass@example.com:1234/foo/bar?baz#quux + * | | | | ^^^^| | | + * | | | | | | | `----- hash_start + * | | | | | | `--------- search_start + * | | | | | `----------------- pathname_start + * | | | | `--------------------- port + * | | | `----------------------- host_end + * | | `---------------------------------- host_start + * | `--------------------------------------- username_end + * `--------------------------------------------- protocol_end + * + * Inspired after servo/url + * + * @return a constant reference to the underlying component attribute. + * + * @see + * https://github.com/servo/rust-url/blob/b65a45515c10713f6d212e6726719a020203cc98/url/src/quirks.rs#L31 + */ + [[nodiscard]] ada_really_inline const url_components &get_components() + const noexcept; + /** + * Returns a string representation of this URL. + */ + [[nodiscard]] std::string to_string() const override; + /** + * Returns a string diagram of this URL. + */ + [[nodiscard]] std::string to_diagram() const; + + /** + * Verifies that the parsed URL could be valid. Useful for debugging purposes. + * @return true if the URL is valid, otherwise return true of the offsets are + * possible. + */ + [[nodiscard]] constexpr bool validate() const noexcept; + + /** @return true if it has an host but it is the empty string */ + [[nodiscard]] constexpr bool has_empty_hostname() const noexcept; + /** @return true if it has a host (included an empty host) */ + [[nodiscard]] constexpr bool has_hostname() const noexcept; + /** @return true if the URL has a non-empty username */ + [[nodiscard]] constexpr bool has_non_empty_username() const noexcept; + /** @return true if the URL has a non-empty password */ + [[nodiscard]] constexpr bool has_non_empty_password() const noexcept; + /** @return true if the URL has a (non default) port */ + [[nodiscard]] constexpr bool has_port() const noexcept; + /** @return true if the URL has a password */ + [[nodiscard]] constexpr bool has_password() const noexcept; + /** @return true if the URL has a hash component */ + [[nodiscard]] constexpr bool has_hash() const noexcept override; + /** @return true if the URL has a search component */ + [[nodiscard]] constexpr bool has_search() const noexcept override; + + inline void clear_port(); + inline void clear_hash(); + inline void clear_search() override; + + private: + // helper methods + friend void helpers::strip_trailing_spaces_from_opaque_path( + url_aggregator &url) noexcept; + // parse_url methods + friend url_aggregator parser::parse_url( + std::string_view, const url_aggregator *); + + friend url_aggregator parser::parse_url_impl( + std::string_view, const url_aggregator *); + friend url_aggregator parser::parse_url_impl( + std::string_view, const url_aggregator *); + +#if ADA_INCLUDE_URL_PATTERN + // url_pattern methods + template + friend tl::expected, errors> + parse_url_pattern_impl( + std::variant &&input, + const std::string_view *base_url, const url_pattern_options *options); +#endif // ADA_INCLUDE_URL_PATTERN + + std::string buffer{}; + url_components components{}; -inline void url::update_base_pathname(const std::string_view input) { - path = input; -} + /** + * Returns true if neither the search, nor the hash nor the pathname + * have been set. + * @return true if the buffer is ready to receive the path. + */ + [[nodiscard]] ada_really_inline bool is_at_path() const noexcept; -inline void url::update_base_username(const std::string_view input) { - username = input; -} + inline void add_authority_slashes_if_needed() noexcept; -inline void url::update_base_password(const std::string_view input) { - password = input; -} + /** + * To optimize performance, you may indicate how much memory to allocate + * within this instance. + */ + constexpr void reserve(uint32_t capacity); -inline void url::update_base_port(std::optional input) { - port = input; -} + ada_really_inline size_t parse_port( + std::string_view view, bool check_trailing_content) noexcept override; -inline void url::clear_pathname() { path.clear(); } + ada_really_inline size_t parse_port(std::string_view view) noexcept override { + return this->parse_port(view, false); + } -inline void url::clear_search() { query = std::nullopt; } + /** + * Return true on success. The 'in_place' parameter indicates whether the + * the string_view input is pointing in the buffer. When in_place is false, + * we must nearly always update the buffer. + * @see https://url.spec.whatwg.org/#concept-ipv4-parser + */ + [[nodiscard]] bool parse_ipv4(std::string_view input, bool in_place); -[[nodiscard]] inline bool url::has_hash() const noexcept { - return hash.has_value(); -} + /** + * Return true on success. + * @see https://url.spec.whatwg.org/#concept-ipv6-parser + */ + [[nodiscard]] bool parse_ipv6(std::string_view input); -[[nodiscard]] inline bool url::has_search() const noexcept { - return query.has_value(); -} + /** + * Return true on success. + * @see https://url.spec.whatwg.org/#concept-opaque-host-parser + */ + [[nodiscard]] bool parse_opaque_host(std::string_view input); -inline void url::set_protocol_as_file() { type = ada::scheme::type::FILE; } + ada_really_inline void parse_path(std::string_view input); -inline void url::set_scheme(std::string&& new_scheme) noexcept { - type = ada::scheme::get_scheme_type(new_scheme); - // We only move the 'scheme' if it is non-special. - if (!is_special()) { - non_special_scheme = new_scheme; - } -} + /** + * A URL cannot have a username/password/port if its host is null or the empty + * string, or its scheme is "file". + */ + [[nodiscard]] constexpr bool cannot_have_credentials_or_port() const; -inline void url::copy_scheme(ada::url&& u) noexcept { - non_special_scheme = u.non_special_scheme; - type = u.type; -} + template + bool set_host_or_hostname(std::string_view input); -inline void url::copy_scheme(const ada::url& u) { - non_special_scheme = u.non_special_scheme; - type = u.type; -} + ada_really_inline bool parse_host(std::string_view input); -[[nodiscard]] ada_really_inline std::string url::get_href() const noexcept { - std::string output = get_protocol(); + inline void update_base_authority(std::string_view base_buffer, + const url_components &base); + inline void update_unencoded_base_hash(std::string_view input); + inline void update_base_hostname(std::string_view input); + inline void update_base_search(std::string_view input); + inline void update_base_search(std::string_view input, + const uint8_t *query_percent_encode_set); + inline void update_base_pathname(std::string_view input); + inline void update_base_username(std::string_view input); + inline void append_base_username(std::string_view input); + inline void update_base_password(std::string_view input); + inline void append_base_password(std::string_view input); + inline void update_base_port(uint32_t input); + inline void append_base_pathname(std::string_view input); + [[nodiscard]] inline uint32_t retrieve_base_port() const; + constexpr void clear_hostname(); + constexpr void clear_password(); + constexpr void clear_pathname() override; + [[nodiscard]] constexpr bool has_dash_dot() const noexcept; + void delete_dash_dot(); + inline void consume_prepared_path(std::string_view input); + template + [[nodiscard]] ada_really_inline bool parse_scheme_with_colon( + std::string_view input); + ada_really_inline uint32_t replace_and_resize(uint32_t start, uint32_t end, + std::string_view input); + [[nodiscard]] constexpr bool has_authority() const noexcept; + constexpr void set_protocol_as_file(); + inline void set_scheme(std::string_view new_scheme) noexcept; + /** + * Fast function to set the scheme from a view with a colon in the + * buffer, does not change type. + */ + inline void set_scheme_from_view_with_colon( + std::string_view new_scheme_with_colon) noexcept; + inline void copy_scheme(const url_aggregator &u) noexcept; - if (host.has_value()) { - output += "//"; - if (has_credentials()) { - output += username; - if (!password.empty()) { - output += ":" + get_password(); - } - output += "@"; - } - output += host.value(); - if (port.has_value()) { - output += ":" + get_port(); - } - } else if (!has_opaque_path && checkers::begins_with(path, "//")) { - // If url's host is null, url does not have an opaque path, url's path's - // size is greater than 1, and url's path[0] is the empty string, then - // append U+002F (/) followed by U+002E (.) to output. - output += "/."; - } - output += path; - if (query.has_value()) { - output += "?" + query.value(); - } - if (hash.has_value()) { - output += "#" + hash.value(); - } - return output; -} + inline void update_host_to_base_host(const std::string_view input) noexcept; -ada_really_inline size_t url::parse_port(std::string_view view, - bool check_trailing_content) noexcept { - ada_log("parse_port('", view, "') ", view.size()); - uint16_t parsed_port{}; - auto r = std::from_chars(view.data(), view.data() + view.size(), parsed_port); - if (r.ec == std::errc::result_out_of_range) { - ada_log("parse_port: std::errc::result_out_of_range"); - is_valid = false; - return 0; - } - ada_log("parse_port: ", parsed_port); - const size_t consumed = size_t(r.ptr - view.data()); - ada_log("parse_port: consumed ", consumed); - if (check_trailing_content) { - is_valid &= - (consumed == view.size() || view[consumed] == '/' || - view[consumed] == '?' || (is_special() && view[consumed] == '\\')); - } - ada_log("parse_port: is_valid = ", is_valid); - if (is_valid) { - // scheme_default_port can return 0, and we should allow 0 as a base port. - auto default_port = scheme_default_port(); - bool is_port_valid = (default_port == 0 && parsed_port == 0) || - (default_port != parsed_port); - port = (r.ec == std::errc() && is_port_valid) - ? std::optional(parsed_port) - : std::nullopt; - } - return consumed; -} +}; // url_aggregator +inline std::ostream &operator<<(std::ostream &out, const url &u); } // namespace ada -#endif // ADA_URL_H -/* end file include/ada/url-inl.h */ +#endif +/* end file include/ada/url_aggregator.h */ /* begin file include/ada/url_aggregator-inl.h */ /** * @file url_aggregator-inl.h @@ -5902,7 +7279,6 @@ ada_really_inline size_t url::parse_port(std::string_view view, */ #ifndef ADA_UNICODE_INL_H #define ADA_UNICODE_INL_H -#include /** * Unicode operations. These functions are not part of our public API and may @@ -5915,29 +7291,51 @@ ada_really_inline size_t url::parse_port(std::string_view view, namespace ada::unicode { ada_really_inline size_t percent_encode_index(const std::string_view input, const uint8_t character_set[]) { - return std::distance( - input.begin(), - std::find_if(input.begin(), input.end(), [character_set](const char c) { - return character_sets::bit_at(character_set, c); - })); + const char* data = input.data(); + const size_t size = input.size(); + + // Process 8 bytes at a time using unrolled loop + size_t i = 0; + for (; i + 8 <= size; i += 8) { + unsigned char chunk[8]; + std::memcpy(&chunk, data + i, + 8); // entices compiler to unconditionally process 8 characters + + // Check 8 characters at once + for (size_t j = 0; j < 8; j++) { + if (character_sets::bit_at(character_set, chunk[j])) { + return i + j; + } + } + } + + // Handle remaining bytes + for (; i < size; i++) { + if (character_sets::bit_at(character_set, data[i])) { + return i; + } + } + + return size; } } // namespace ada::unicode #endif // ADA_UNICODE_INL_H /* end file include/ada/unicode-inl.h */ -#include +#include +#include #include namespace ada { inline void url_aggregator::update_base_authority( - std::string_view base_buffer, const ada::url_components& base) { + std::string_view base_buffer, const ada::url_components &base) { std::string_view input = base_buffer.substr( base.protocol_end, base.host_start - base.protocol_end); ada_log("url_aggregator::update_base_authority ", input); - bool input_starts_with_dash = checkers::begins_with(input, "//"); + bool input_starts_with_dash = input.starts_with("//"); uint32_t diff = components.host_start - components.protocol_end; buffer.erase(components.protocol_end, @@ -6177,9 +7575,8 @@ inline void url_aggregator::update_base_pathname(const std::string_view input) { ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); ADA_ASSERT_TRUE(validate()); - const bool begins_with_dashdash = checkers::begins_with(input, "//"); + const bool begins_with_dashdash = input.starts_with("//"); if (!begins_with_dashdash && has_dash_dot()) { - ada_log("url_aggregator::update_base_pathname has /.: \n", to_diagram()); // We must delete the ./ delete_dash_dot(); } @@ -6202,8 +7599,6 @@ inline void url_aggregator::update_base_pathname(const std::string_view input) { if (components.hash_start != url_components::omitted) { components.hash_start += difference; } - ada_log("url_aggregator::update_base_pathname end '", input, "' [", - input.size(), " bytes] \n", to_diagram()); ADA_ASSERT_TRUE(validate()); } @@ -6322,8 +7717,8 @@ inline void url_aggregator::append_base_username(const std::string_view input) { ADA_ASSERT_TRUE(validate()); } -inline void url_aggregator::clear_password() { - ada_log("url_aggregator::clear_password ", to_string(), "\n", to_diagram()); +constexpr void url_aggregator::clear_password() { + ada_log("url_aggregator::clear_password ", to_string()); ADA_ASSERT_TRUE(validate()); if (!has_password()) { return; @@ -6544,7 +7939,7 @@ inline void url_aggregator::clear_hash() { ADA_ASSERT_TRUE(validate()); } -inline void url_aggregator::clear_pathname() { +constexpr void url_aggregator::clear_pathname() { ada_log("url_aggregator::clear_pathname"); ADA_ASSERT_TRUE(validate()); uint32_t ending_index = uint32_t(buffer.size()); @@ -6579,7 +7974,7 @@ inline void url_aggregator::clear_pathname() { ada_log("url_aggregator::clear_pathname completed, running checks... ok"); } -inline void url_aggregator::clear_hostname() { +constexpr void url_aggregator::clear_hostname() { ada_log("url_aggregator::clear_hostname"); ADA_ASSERT_TRUE(validate()); if (!has_authority()) { @@ -6616,33 +8011,34 @@ inline void url_aggregator::clear_hostname() { ADA_ASSERT_TRUE(validate()); } -[[nodiscard]] inline bool url_aggregator::has_hash() const noexcept { +[[nodiscard]] constexpr bool url_aggregator::has_hash() const noexcept { ada_log("url_aggregator::has_hash"); return components.hash_start != url_components::omitted; } -[[nodiscard]] inline bool url_aggregator::has_search() const noexcept { +[[nodiscard]] constexpr bool url_aggregator::has_search() const noexcept { ada_log("url_aggregator::has_search"); return components.search_start != url_components::omitted; } -ada_really_inline bool url_aggregator::has_credentials() const noexcept { +constexpr bool url_aggregator::has_credentials() const noexcept { ada_log("url_aggregator::has_credentials"); return has_non_empty_username() || has_non_empty_password(); } -inline bool url_aggregator::cannot_have_credentials_or_port() const { +constexpr bool url_aggregator::cannot_have_credentials_or_port() const { ada_log("url_aggregator::cannot_have_credentials_or_port"); return type == ada::scheme::type::FILE || components.host_start == components.host_end; } -[[nodiscard]] ada_really_inline const ada::url_components& +[[nodiscard]] ada_really_inline const ada::url_components & url_aggregator::get_components() const noexcept { return components; } -[[nodiscard]] inline bool ada::url_aggregator::has_authority() const noexcept { +[[nodiscard]] constexpr bool ada::url_aggregator::has_authority() + const noexcept { ada_log("url_aggregator::has_authority"); // Performance: instead of doing this potentially expensive check, we could // have a boolean in the struct. @@ -6677,28 +8073,28 @@ inline void ada::url_aggregator::add_authority_slashes_if_needed() noexcept { ADA_ASSERT_TRUE(validate()); } -inline void ada::url_aggregator::reserve(uint32_t capacity) { +constexpr void ada::url_aggregator::reserve(uint32_t capacity) { buffer.reserve(capacity); } -inline bool url_aggregator::has_non_empty_username() const noexcept { +constexpr bool url_aggregator::has_non_empty_username() const noexcept { ada_log("url_aggregator::has_non_empty_username"); return components.protocol_end + 2 < components.username_end; } -inline bool url_aggregator::has_non_empty_password() const noexcept { +constexpr bool url_aggregator::has_non_empty_password() const noexcept { ada_log("url_aggregator::has_non_empty_password"); return components.host_start - components.username_end > 0; } -inline bool url_aggregator::has_password() const noexcept { +constexpr bool url_aggregator::has_password() const noexcept { ada_log("url_aggregator::has_password"); // This function does not care about the length of the password return components.host_start > components.username_end && buffer[components.username_end] == ':'; } -inline bool url_aggregator::has_empty_hostname() const noexcept { +constexpr bool url_aggregator::has_empty_hostname() const noexcept { if (!has_hostname()) { return false; } @@ -6711,18 +8107,18 @@ inline bool url_aggregator::has_empty_hostname() const noexcept { return components.username_end != components.host_start; } -inline bool url_aggregator::has_hostname() const noexcept { +constexpr bool url_aggregator::has_hostname() const noexcept { return has_authority(); } -inline bool url_aggregator::has_port() const noexcept { +constexpr bool url_aggregator::has_port() const noexcept { ada_log("url_aggregator::has_port"); // A URL cannot have a username/password/port if its host is null or the empty // string, or its scheme is "file". return has_hostname() && components.pathname_start != components.host_end; } -[[nodiscard]] inline bool url_aggregator::has_dash_dot() const noexcept { +[[nodiscard]] constexpr bool url_aggregator::has_dash_dot() const noexcept { // If url's host is null, url does not have an opaque path, url's path's size // is greater than 1, and url's path[0] is the empty string, then append // U+002F (/) followed by U+002E (.) to output. @@ -6754,8 +8150,8 @@ inline bool url_aggregator::has_port() const noexcept { buffer[components.host_end + 1] == '.'; } -[[nodiscard]] inline std::string_view url_aggregator::get_href() - const noexcept { +[[nodiscard]] constexpr std::string_view url_aggregator::get_href() + const noexcept ada_lifetime_bound { ada_log("url_aggregator::get_href"); return buffer; } @@ -6763,10 +8159,15 @@ inline bool url_aggregator::has_port() const noexcept { ada_really_inline size_t url_aggregator::parse_port( std::string_view view, bool check_trailing_content) noexcept { ada_log("url_aggregator::parse_port('", view, "') ", view.size()); + if (!view.empty() && view[0] == '-') { + ada_log("parse_port: view[0] == '0' && view.size() > 1"); + is_valid = false; + return 0; + } uint16_t parsed_port{}; auto r = std::from_chars(view.data(), view.data() + view.size(), parsed_port); if (r.ec == std::errc::result_out_of_range) { - ada_log("parse_port: std::errc::result_out_of_range"); + ada_log("parse_port: r.ec == std::errc::result_out_of_range"); is_valid = false; return 0; } @@ -6794,7 +8195,7 @@ ada_really_inline size_t url_aggregator::parse_port( return consumed; } -inline void url_aggregator::set_protocol_as_file() { +constexpr void url_aggregator::set_protocol_as_file() { ada_log("url_aggregator::set_protocol_as_file "); ADA_ASSERT_TRUE(validate()); type = ada::scheme::type::FILE; @@ -6822,11 +8223,218 @@ inline void url_aggregator::set_protocol_as_file() { components.hash_start += new_difference; } ADA_ASSERT_TRUE(validate()); -} - -inline std::ostream& operator<<(std::ostream& out, - const ada::url_aggregator& u) { - return out << u.to_string(); +} + +[[nodiscard]] constexpr bool url_aggregator::validate() const noexcept { + if (!is_valid) { + return true; + } + if (!components.check_offset_consistency()) { + ada_log("url_aggregator::validate inconsistent components \n", + to_diagram()); + return false; + } + // We have a credible components struct, but let us investivate more + // carefully: + /** + * https://user:pass@example.com:1234/foo/bar?baz#quux + * | | | | ^^^^| | | + * | | | | | | | `----- hash_start + * | | | | | | `--------- search_start + * | | | | | `----------------- pathname_start + * | | | | `--------------------- port + * | | | `----------------------- host_end + * | | `---------------------------------- host_start + * | `--------------------------------------- username_end + * `--------------------------------------------- protocol_end + */ + if (components.protocol_end == url_components::omitted) { + ada_log("url_aggregator::validate omitted protocol_end \n", to_diagram()); + return false; + } + if (components.username_end == url_components::omitted) { + ada_log("url_aggregator::validate omitted username_end \n", to_diagram()); + return false; + } + if (components.host_start == url_components::omitted) { + ada_log("url_aggregator::validate omitted host_start \n", to_diagram()); + return false; + } + if (components.host_end == url_components::omitted) { + ada_log("url_aggregator::validate omitted host_end \n", to_diagram()); + return false; + } + if (components.pathname_start == url_components::omitted) { + ada_log("url_aggregator::validate omitted pathname_start \n", to_diagram()); + return false; + } + + if (components.protocol_end > buffer.size()) { + ada_log("url_aggregator::validate protocol_end overflow \n", to_diagram()); + return false; + } + if (components.username_end > buffer.size()) { + ada_log("url_aggregator::validate username_end overflow \n", to_diagram()); + return false; + } + if (components.host_start > buffer.size()) { + ada_log("url_aggregator::validate host_start overflow \n", to_diagram()); + return false; + } + if (components.host_end > buffer.size()) { + ada_log("url_aggregator::validate host_end overflow \n", to_diagram()); + return false; + } + if (components.pathname_start > buffer.size()) { + ada_log("url_aggregator::validate pathname_start overflow \n", + to_diagram()); + return false; + } + + if (components.protocol_end > 0) { + if (buffer[components.protocol_end - 1] != ':') { + ada_log( + "url_aggregator::validate missing : at the end of the protocol \n", + to_diagram()); + return false; + } + } + + if (components.username_end != buffer.size() && + components.username_end > components.protocol_end + 2) { + if (buffer[components.username_end] != ':' && + buffer[components.username_end] != '@') { + ada_log( + "url_aggregator::validate missing : or @ at the end of the username " + "\n", + to_diagram()); + return false; + } + } + + if (components.host_start != buffer.size()) { + if (components.host_start > components.username_end) { + if (buffer[components.host_start] != '@') { + ada_log( + "url_aggregator::validate missing @ at the end of the password \n", + to_diagram()); + return false; + } + } else if (components.host_start == components.username_end && + components.host_end > components.host_start) { + if (components.host_start == components.protocol_end + 2) { + if (buffer[components.protocol_end] != '/' || + buffer[components.protocol_end + 1] != '/') { + ada_log( + "url_aggregator::validate missing // between protocol and host " + "\n", + to_diagram()); + return false; + } + } else { + if (components.host_start > components.protocol_end && + buffer[components.host_start] != '@') { + ada_log( + "url_aggregator::validate missing @ at the end of the username " + "\n", + to_diagram()); + return false; + } + } + } else { + if (components.host_end != components.host_start) { + ada_log("url_aggregator::validate expected omitted host \n", + to_diagram()); + return false; + } + } + } + if (components.host_end != buffer.size() && + components.pathname_start > components.host_end) { + if (components.pathname_start == components.host_end + 2 && + buffer[components.host_end] == '/' && + buffer[components.host_end + 1] == '.') { + if (components.pathname_start + 1 >= buffer.size() || + buffer[components.pathname_start] != '/' || + buffer[components.pathname_start + 1] != '/') { + ada_log( + "url_aggregator::validate expected the path to begin with // \n", + to_diagram()); + return false; + } + } else if (buffer[components.host_end] != ':') { + ada_log("url_aggregator::validate missing : at the port \n", + to_diagram()); + return false; + } + } + if (components.pathname_start != buffer.size() && + components.pathname_start < components.search_start && + components.pathname_start < components.hash_start && !has_opaque_path) { + if (buffer[components.pathname_start] != '/') { + ada_log("url_aggregator::validate missing / at the path \n", + to_diagram()); + return false; + } + } + if (components.search_start != url_components::omitted) { + if (buffer[components.search_start] != '?') { + ada_log("url_aggregator::validate missing ? at the search \n", + to_diagram()); + return false; + } + } + if (components.hash_start != url_components::omitted) { + if (buffer[components.hash_start] != '#') { + ada_log("url_aggregator::validate missing # at the hash \n", + to_diagram()); + return false; + } + } + + return true; +} + +[[nodiscard]] constexpr std::string_view url_aggregator::get_pathname() + const noexcept ada_lifetime_bound { + ada_log("url_aggregator::get_pathname pathname_start = ", + components.pathname_start, " buffer.size() = ", buffer.size(), + " components.search_start = ", components.search_start, + " components.hash_start = ", components.hash_start); + auto ending_index = uint32_t(buffer.size()); + if (components.search_start != url_components::omitted) { + ending_index = components.search_start; + } else if (components.hash_start != url_components::omitted) { + ending_index = components.hash_start; + } + return helpers::substring(buffer, components.pathname_start, ending_index); +} + +inline std::ostream &operator<<(std::ostream &out, + const ada::url_aggregator &u) { + return out << u.to_string(); +} + +void url_aggregator::update_host_to_base_host( + const std::string_view input) noexcept { + ada_log("url_aggregator::update_host_to_base_host ", input); + ADA_ASSERT_TRUE(validate()); + ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); + if (type != ada::scheme::type::FILE) { + // Let host be the result of host parsing host_view with url is not special. + if (input.empty() && !is_special()) { + if (has_hostname()) { + clear_hostname(); + } else if (has_dash_dot()) { + add_authority_slashes_if_needed(); + delete_dash_dot(); + } + return; + } + } + update_base_hostname(input); + ADA_ASSERT_TRUE(validate()); + return; } } // namespace ada @@ -6868,6 +8476,8 @@ using url_search_params_entries_iter = url_search_params_iter_type::ENTRIES>; /** + * We require all strings to be valid UTF-8. It is the user's responsibility to + * ensure that the provided strings are valid UTF-8. * @see https://url.spec.whatwg.org/#interface-urlsearchparams */ struct url_search_params { @@ -6877,17 +8487,20 @@ struct url_search_params { * @see * https://github.com/web-platform-tests/wpt/blob/master/url/urlsearchparams-constructor.any.js */ - url_search_params(const std::string_view input) { initialize(input); } + explicit url_search_params(const std::string_view input) { + initialize(input); + } - url_search_params(const url_search_params& u) = default; - url_search_params(url_search_params&& u) noexcept = default; - url_search_params& operator=(url_search_params&& u) noexcept = default; - url_search_params& operator=(const url_search_params& u) = default; + url_search_params(const url_search_params &u) = default; + url_search_params(url_search_params &&u) noexcept = default; + url_search_params &operator=(url_search_params &&u) noexcept = default; + url_search_params &operator=(const url_search_params &u) = default; ~url_search_params() = default; [[nodiscard]] inline size_t size() const noexcept; /** + * Both key and value must be valid UTF-8. * @see https://url.spec.whatwg.org/#dom-urlsearchparams-append */ inline void append(std::string_view key, std::string_view value); @@ -6915,6 +8528,7 @@ struct url_search_params { inline bool has(std::string_view key, std::string_view value) noexcept; /** + * Both key and value must be valid UTF-8. * @see https://url.spec.whatwg.org/#dom-urlsearchparams-set */ inline void set(std::string_view key, std::string_view value); @@ -6978,6 +8592,7 @@ struct url_search_params { std::vector params{}; /** + * The init parameter must be valid UTF-8. * @see https://url.spec.whatwg.org/#concept-urlencoded-parser */ void initialize(std::string_view init); @@ -6995,11 +8610,11 @@ struct url_search_params { template struct url_search_params_iter { inline url_search_params_iter() : params(EMPTY) {} - url_search_params_iter(const url_search_params_iter& u) = default; - url_search_params_iter(url_search_params_iter&& u) noexcept = default; - url_search_params_iter& operator=(url_search_params_iter&& u) noexcept = + url_search_params_iter(const url_search_params_iter &u) = default; + url_search_params_iter(url_search_params_iter &&u) noexcept = default; + url_search_params_iter &operator=(url_search_params_iter &&u) noexcept = default; - url_search_params_iter& operator=(const url_search_params_iter& u) = default; + url_search_params_iter &operator=(const url_search_params_iter &u) = default; ~url_search_params_iter() = default; /** @@ -7007,13 +8622,13 @@ struct url_search_params_iter { */ inline std::optional next(); - inline bool has_next(); + inline bool has_next() const; private: static url_search_params EMPTY; - inline url_search_params_iter(url_search_params& params_) : params(params_) {} + inline url_search_params_iter(url_search_params ¶ms_) : params(params_) {} - url_search_params& params; + url_search_params ¶ms; size_t pos = 0; friend struct url_search_params; @@ -7030,8 +8645,10 @@ struct url_search_params_iter { #ifndef ADA_URL_SEARCH_PARAMS_INL_H #define ADA_URL_SEARCH_PARAMS_INL_H + #include #include +#include #include #include #include @@ -7057,14 +8674,14 @@ inline void url_search_params::initialize(std::string_view input) { if (equal == std::string_view::npos) { std::string name(current); - std::replace(name.begin(), name.end(), '+', ' '); + std::ranges::replace(name, '+', ' '); params.emplace_back(unicode::percent_decode(name, name.find('%')), ""); } else { std::string name(current.substr(0, equal)); std::string value(current.substr(equal + 1)); - std::replace(name.begin(), name.end(), '+', ' '); - std::replace(value.begin(), value.end(), '+', ' '); + std::ranges::replace(name, '+', ' '); + std::ranges::replace(value, '+', ' '); params.emplace_back(unicode::percent_decode(name, name.find('%')), unicode::percent_decode(value, value.find('%'))); @@ -7096,8 +8713,8 @@ inline size_t url_search_params::size() const noexcept { return params.size(); } inline std::optional url_search_params::get( const std::string_view key) { - auto entry = std::find_if(params.begin(), params.end(), - [&key](auto& param) { return param.first == key; }); + auto entry = std::ranges::find_if( + params, [&key](const auto ¶m) { return param.first == key; }); if (entry == params.end()) { return std::nullopt; @@ -7110,7 +8727,7 @@ inline std::vector url_search_params::get_all( const std::string_view key) { std::vector out{}; - for (auto& param : params) { + for (auto ¶m : params) { if (param.first == key) { out.emplace_back(param.second); } @@ -7120,17 +8737,16 @@ inline std::vector url_search_params::get_all( } inline bool url_search_params::has(const std::string_view key) noexcept { - auto entry = std::find_if(params.begin(), params.end(), - [&key](auto& param) { return param.first == key; }); + auto entry = std::ranges::find_if( + params, [&key](const auto ¶m) { return param.first == key; }); return entry != params.end(); } inline bool url_search_params::has(std::string_view key, std::string_view value) noexcept { - auto entry = - std::find_if(params.begin(), params.end(), [&key, &value](auto& param) { - return param.first == key && param.second == value; - }); + auto entry = std::ranges::find_if(params, [&key, &value](const auto ¶m) { + return param.first == key && param.second == value; + }); return entry != params.end(); } @@ -7142,8 +8758,8 @@ inline std::string url_search_params::to_string() const { auto value = ada::unicode::percent_encode(params[i].second, character_set); // Performance optimization: Move this inside percent_encode. - std::replace(key.begin(), key.end(), ' ', '+'); - std::replace(value.begin(), value.end(), ' ', '+'); + std::ranges::replace(key, ' ', '+'); + std::ranges::replace(value, ' ', '+'); if (i != 0) { out += "&"; @@ -7157,9 +8773,9 @@ inline std::string url_search_params::to_string() const { inline void url_search_params::set(const std::string_view key, const std::string_view value) { - const auto find = [&key](auto& param) { return param.first == key; }; + const auto find = [&key](const auto ¶m) { return param.first == key; }; - auto it = std::find_if(params.begin(), params.end(), find); + auto it = std::ranges::find_if(params, find); if (it == params.end()) { params.emplace_back(key, value); @@ -7171,27 +8787,92 @@ inline void url_search_params::set(const std::string_view key, } inline void url_search_params::remove(const std::string_view key) { - params.erase( - std::remove_if(params.begin(), params.end(), - [&key](auto& param) { return param.first == key; }), - params.end()); + std::erase_if(params, + [&key](const auto ¶m) { return param.first == key; }); } inline void url_search_params::remove(const std::string_view key, const std::string_view value) { - params.erase(std::remove_if(params.begin(), params.end(), - [&key, &value](auto& param) { - return param.first == key && - param.second == value; - }), - params.end()); + std::erase_if(params, [&key, &value](const auto ¶m) { + return param.first == key && param.second == value; + }); } inline void url_search_params::sort() { - std::stable_sort(params.begin(), params.end(), - [](const key_value_pair& lhs, const key_value_pair& rhs) { - return lhs.first < rhs.first; - }); + // We rely on the fact that the content is valid UTF-8. + std::ranges::stable_sort(params, [](const key_value_pair &lhs, + const key_value_pair &rhs) { + size_t i = 0, j = 0; + uint32_t low_surrogate1 = 0, low_surrogate2 = 0; + while ((i < lhs.first.size() || low_surrogate1 != 0) && + (j < rhs.first.size() || low_surrogate2 != 0)) { + uint32_t codePoint1 = 0, codePoint2 = 0; + + if (low_surrogate1 != 0) { + codePoint1 = low_surrogate1; + low_surrogate1 = 0; + } else { + uint8_t c1 = uint8_t(lhs.first[i]); + if (c1 <= 0x7F) { + codePoint1 = c1; + i++; + } else if (c1 <= 0xDF) { + codePoint1 = ((c1 & 0x1F) << 6) | (uint8_t(lhs.first[i + 1]) & 0x3F); + i += 2; + } else if (c1 <= 0xEF) { + codePoint1 = ((c1 & 0x0F) << 12) | + ((uint8_t(lhs.first[i + 1]) & 0x3F) << 6) | + (uint8_t(lhs.first[i + 2]) & 0x3F); + i += 3; + } else { + codePoint1 = ((c1 & 0x07) << 18) | + ((uint8_t(lhs.first[i + 1]) & 0x3F) << 12) | + ((uint8_t(lhs.first[i + 2]) & 0x3F) << 6) | + (uint8_t(lhs.first[i + 3]) & 0x3F); + i += 4; + + codePoint1 -= 0x10000; + uint16_t high_surrogate = uint16_t(0xD800 + (codePoint1 >> 10)); + low_surrogate1 = uint16_t(0xDC00 + (codePoint1 & 0x3FF)); + codePoint1 = high_surrogate; + } + } + + if (low_surrogate2 != 0) { + codePoint2 = low_surrogate2; + low_surrogate2 = 0; + } else { + uint8_t c2 = uint8_t(rhs.first[j]); + if (c2 <= 0x7F) { + codePoint2 = c2; + j++; + } else if (c2 <= 0xDF) { + codePoint2 = ((c2 & 0x1F) << 6) | (uint8_t(rhs.first[j + 1]) & 0x3F); + j += 2; + } else if (c2 <= 0xEF) { + codePoint2 = ((c2 & 0x0F) << 12) | + ((uint8_t(rhs.first[j + 1]) & 0x3F) << 6) | + (uint8_t(rhs.first[j + 2]) & 0x3F); + j += 3; + } else { + codePoint2 = ((c2 & 0x07) << 18) | + ((uint8_t(rhs.first[j + 1]) & 0x3F) << 12) | + ((uint8_t(rhs.first[j + 2]) & 0x3F) << 6) | + (uint8_t(rhs.first[j + 3]) & 0x3F); + j += 4; + codePoint2 -= 0x10000; + uint16_t high_surrogate = uint16_t(0xD800 + (codePoint2 >> 10)); + low_surrogate2 = uint16_t(0xDC00 + (codePoint2 & 0x3FF)); + codePoint2 = high_surrogate; + } + } + + if (codePoint1 != codePoint2) { + return (codePoint1 < codePoint2); + } + } + return (j < rhs.first.size() || low_surrogate2 != 0); + }); } inline url_search_params_keys_iter url_search_params::get_keys() { @@ -7213,7 +8894,7 @@ inline url_search_params_entries_iter url_search_params::get_entries() { } template -inline bool url_search_params_iter::has_next() { +inline bool url_search_params_iter::has_next() const { return pos < params.params.size(); } @@ -7247,6 +8928,1584 @@ url_search_params_entries_iter::next() { #endif // ADA_URL_SEARCH_PARAMS_INL_H /* end file include/ada/url_search_params-inl.h */ +/* begin file include/ada/url_pattern-inl.h */ +/** + * @file url_pattern-inl.h + * @brief Declaration for the URLPattern inline functions. + */ +#ifndef ADA_URL_PATTERN_INL_H +#define ADA_URL_PATTERN_INL_H + + +#include +#include +#include + +#if ADA_INCLUDE_URL_PATTERN +namespace ada { + +inline bool url_pattern_init::operator==(const url_pattern_init& other) const { + return protocol == other.protocol && username == other.username && + password == other.password && hostname == other.hostname && + port == other.port && search == other.search && hash == other.hash && + pathname == other.pathname; +} + +inline bool url_pattern_component_result::operator==( + const url_pattern_component_result& other) const { + return input == other.input && groups == other.groups; +} + +template +url_pattern_component_result +url_pattern_component::create_component_match_result( + std::string&& input, + std::vector>&& exec_result) { + // Let result be a new URLPatternComponentResult. + // Set result["input"] to input. + // Let groups be a record. + auto result = + url_pattern_component_result{.input = std::move(input), .groups = {}}; + + // Optimization: Let's reserve the size. + result.groups.reserve(exec_result.size()); + + // We explicitly start iterating from 0 even though the spec + // says we should start from 1. This case is handled by the + // std_regex_provider. + for (size_t index = 0; index < exec_result.size(); index++) { + result.groups.insert({ + group_name_list[index], + std::move(exec_result[index]), + }); + } + return result; +} + +template +std::string_view url_pattern::get_protocol() const + ada_lifetime_bound { + // Return this's associated URL pattern's protocol component's pattern string. + return protocol_component.pattern; +} +template +std::string_view url_pattern::get_username() const + ada_lifetime_bound { + // Return this's associated URL pattern's username component's pattern string. + return username_component.pattern; +} +template +std::string_view url_pattern::get_password() const + ada_lifetime_bound { + // Return this's associated URL pattern's password component's pattern string. + return password_component.pattern; +} +template +std::string_view url_pattern::get_hostname() const + ada_lifetime_bound { + // Return this's associated URL pattern's hostname component's pattern string. + return hostname_component.pattern; +} +template +std::string_view url_pattern::get_port() const + ada_lifetime_bound { + // Return this's associated URL pattern's port component's pattern string. + return port_component.pattern; +} +template +std::string_view url_pattern::get_pathname() const + ada_lifetime_bound { + // Return this's associated URL pattern's pathname component's pattern string. + return pathname_component.pattern; +} +template +std::string_view url_pattern::get_search() const + ada_lifetime_bound { + // Return this's associated URL pattern's search component's pattern string. + return search_component.pattern; +} +template +std::string_view url_pattern::get_hash() const + ada_lifetime_bound { + // Return this's associated URL pattern's hash component's pattern string. + return hash_component.pattern; +} +template +bool url_pattern::ignore_case() const { + return ignore_case_; +} +template +bool url_pattern::has_regexp_groups() const { + // If this's associated URL pattern's has regexp groups, then return true. + return protocol_component.has_regexp_groups || + username_component.has_regexp_groups || + password_component.has_regexp_groups || + hostname_component.has_regexp_groups || + port_component.has_regexp_groups || + pathname_component.has_regexp_groups || + search_component.has_regexp_groups || hash_component.has_regexp_groups; +} + +inline bool url_pattern_part::is_regexp() const noexcept { + return type == url_pattern_part_type::REGEXP; +} + +inline std::string_view url_pattern_compile_component_options::get_delimiter() + const { + if (delimiter) { + return {&delimiter.value(), 1}; + } + return {}; +} + +inline std::string_view url_pattern_compile_component_options::get_prefix() + const { + if (prefix) { + return {&prefix.value(), 1}; + } + return {}; +} + +template +template +tl::expected, errors> +url_pattern_component::compile( + std::string_view input, F& encoding_callback, + url_pattern_compile_component_options& options) { + ada_log("url_pattern_component::compile input: ", input); + // Let part list be the result of running parse a pattern string given input, + // options, and encoding callback. + auto part_list = url_pattern_helpers::parse_pattern_string(input, options, + encoding_callback); + + if (!part_list) { + ada_log("parse_pattern_string failed"); + return tl::unexpected(part_list.error()); + } + + // Let (regular expression string, name list) be the result of running + // generate a regular expression and name list given part list and options. + auto [regular_expression_string, name_list] = + url_pattern_helpers::generate_regular_expression_and_name_list(*part_list, + options); + + ada_log("regular expression string: ", regular_expression_string); + + // Let pattern string be the result of running generate a pattern + // string given part list and options. + auto pattern_string = + url_pattern_helpers::generate_pattern_string(*part_list, options); + + // Let regular expression be RegExpCreate(regular expression string, + // flags). If this throws an exception, catch it, and throw a + // TypeError. + std::optional regular_expression = + regex_provider::create_instance(regular_expression_string, + options.ignore_case); + + if (!regular_expression) { + return tl::unexpected(errors::type_error); + } + + // For each part of part list: + // - If part's type is "regexp", then set has regexp groups to true. + const auto has_regexp = [](const auto& part) { return part.is_regexp(); }; + const bool has_regexp_groups = std::ranges::any_of(*part_list, has_regexp); + + ada_log("has regexp groups: ", has_regexp_groups); + + // Return a new component whose pattern string is pattern string, regular + // expression is regular expression, group name list is name list, and has + // regexp groups is has regexp groups. + return url_pattern_component( + std::move(pattern_string), std::move(*regular_expression), + std::move(name_list), has_regexp_groups); +} + +template +result> url_pattern::exec( + const url_pattern_input& input, const std::string_view* base_url) { + // Return the result of match given this's associated URL pattern, input, and + // baseURL if given. + return match(input, base_url); +} + +template +result url_pattern::test( + const url_pattern_input& input, const std::string_view* base_url) { + // TODO: Optimization opportunity. Rather than returning `url_pattern_result` + // Implement a fast path just like `can_parse()` in ada_url. + // Let result be the result of match given this's associated URL pattern, + // input, and baseURL if given. + // If result is null, return false. + if (auto result = match(input, base_url); result.has_value()) { + return result->has_value(); + } + return tl::unexpected(errors::type_error); +} + +template +result> url_pattern::match( + const url_pattern_input& input, const std::string_view* base_url_string) { + std::string protocol{}; + std::string username{}; + std::string password{}; + std::string hostname{}; + std::string port{}; + std::string pathname{}; + std::string search{}; + std::string hash{}; + + // Let inputs be an empty list. + // Append input to inputs. + std::vector inputs{input}; + + // If input is a URLPatternInit then: + if (std::holds_alternative(input)) { + ada_log( + "url_pattern::match called with url_pattern_init and base_url_string=", + base_url_string); + // If baseURLString was given, throw a TypeError. + if (base_url_string) { + ada_log("failed to match because base_url_string was given"); + return tl::unexpected(errors::type_error); + } + + // Let applyResult be the result of process a URLPatternInit given input, + // "url", protocol, username, password, hostname, port, pathname, search, + // and hash. + auto apply_result = url_pattern_init::process( + std::get(input), url_pattern_init::process_type::url, + protocol, username, password, hostname, port, pathname, search, hash); + + // If this throws an exception, catch it, and return null. + if (!apply_result.has_value()) { + ada_log("match returned std::nullopt because process threw"); + return std::nullopt; + } + + // Set protocol to applyResult["protocol"]. + ADA_ASSERT_TRUE(apply_result->protocol.has_value()); + protocol = std::move(apply_result->protocol.value()); + + // Set username to applyResult["username"]. + ADA_ASSERT_TRUE(apply_result->username.has_value()); + username = std::move(apply_result->username.value()); + + // Set password to applyResult["password"]. + ADA_ASSERT_TRUE(apply_result->password.has_value()); + password = std::move(apply_result->password.value()); + + // Set hostname to applyResult["hostname"]. + ADA_ASSERT_TRUE(apply_result->hostname.has_value()); + hostname = std::move(apply_result->hostname.value()); + + // Set port to applyResult["port"]. + ADA_ASSERT_TRUE(apply_result->port.has_value()); + port = std::move(apply_result->port.value()); + + // Set pathname to applyResult["pathname"]. + ADA_ASSERT_TRUE(apply_result->pathname.has_value()); + pathname = std::move(apply_result->pathname.value()); + + // Set search to applyResult["search"]. + ADA_ASSERT_TRUE(apply_result->search.has_value()); + if (apply_result->search->starts_with("?")) { + search = apply_result->search->substr(1); + } else { + search = std::move(apply_result->search.value()); + } + + // Set hash to applyResult["hash"]. + ADA_ASSERT_TRUE(apply_result->hash.has_value()); + ADA_ASSERT_TRUE(!apply_result->hash->starts_with("#")); + hash = std::move(apply_result->hash.value()); + } else { + ADA_ASSERT_TRUE(std::holds_alternative(input)); + + // Let baseURL be null. + result base_url; + + // If baseURLString was given, then: + if (base_url_string) { + // Let baseURL be the result of parsing baseURLString. + base_url = ada::parse(*base_url_string, nullptr); + + // If baseURL is failure, return null. + if (!base_url) { + ada_log("match returned std::nullopt because failed to parse base_url=", + *base_url_string); + return std::nullopt; + } + + // Append baseURLString to inputs. + inputs.emplace_back(*base_url_string); + } + + url_aggregator* base_url_value = + base_url.has_value() ? &*base_url : nullptr; + + // Set url to the result of parsing input given baseURL. + auto url = ada::parse(std::get(input), + base_url_value); + + // If url is failure, return null. + if (!url) { + ada_log("match returned std::nullopt because url failed"); + return std::nullopt; + } + + // Set protocol to url's scheme. + // IMPORTANT: Not documented on the URLPattern spec, but protocol suffix ':' + // is removed. Similar work was done on workerd: + // https://github.com/cloudflare/workerd/blob/8620d14012513a6ce04d079e401d3becac3c67bd/src/workerd/jsg/url.c%2B%2B#L2038 + protocol = url->get_protocol().substr(0, url->get_protocol().size() - 1); + // Set username to url's username. + username = url->get_username(); + // Set password to url's password. + password = url->get_password(); + // Set hostname to url's host, serialized, or the empty string if the value + // is null. + hostname = url->get_hostname(); + // Set port to url's port, serialized, or the empty string if the value is + // null. + port = url->get_port(); + // Set pathname to the result of URL path serializing url. + pathname = url->get_pathname(); + // Set search to url's query or the empty string if the value is null. + // IMPORTANT: Not documented on the URLPattern spec, but search prefix '?' + // is removed. Similar work was done on workerd: + // https://github.com/cloudflare/workerd/blob/8620d14012513a6ce04d079e401d3becac3c67bd/src/workerd/jsg/url.c%2B%2B#L2232 + if (url->has_search()) { + auto view = url->get_search(); + search = view.starts_with("?") ? url->get_search().substr(1) : view; + } + // Set hash to url's fragment or the empty string if the value is null. + // IMPORTANT: Not documented on the URLPattern spec, but hash prefix '#' is + // removed. Similar work was done on workerd: + // https://github.com/cloudflare/workerd/blob/8620d14012513a6ce04d079e401d3becac3c67bd/src/workerd/jsg/url.c%2B%2B#L2242 + if (url->has_hash()) { + auto view = url->get_hash(); + hash = view.starts_with("#") ? url->get_hash().substr(1) : view; + } + } + + // Let protocolExecResult be RegExpBuiltinExec(urlPattern's protocol + // component's regular expression, protocol). + auto protocol_exec_result = + regex_provider::regex_search(protocol, protocol_component.regexp); + + if (!protocol_exec_result) { + return std::nullopt; + } + + // Let usernameExecResult be RegExpBuiltinExec(urlPattern's username + // component's regular expression, username). + auto username_exec_result = + regex_provider::regex_search(username, username_component.regexp); + + if (!username_exec_result) { + return std::nullopt; + } + + // Let passwordExecResult be RegExpBuiltinExec(urlPattern's password + // component's regular expression, password). + auto password_exec_result = + regex_provider::regex_search(password, password_component.regexp); + + if (!password_exec_result) { + return std::nullopt; + } + + // Let hostnameExecResult be RegExpBuiltinExec(urlPattern's hostname + // component's regular expression, hostname). + auto hostname_exec_result = + regex_provider::regex_search(hostname, hostname_component.regexp); + + if (!hostname_exec_result) { + return std::nullopt; + } + + // Let portExecResult be RegExpBuiltinExec(urlPattern's port component's + // regular expression, port). + auto port_exec_result = + regex_provider::regex_search(port, port_component.regexp); + + if (!port_exec_result) { + return std::nullopt; + } + + // Let pathnameExecResult be RegExpBuiltinExec(urlPattern's pathname + // component's regular expression, pathname). + auto pathname_exec_result = + regex_provider::regex_search(pathname, pathname_component.regexp); + + if (!pathname_exec_result) { + return std::nullopt; + } + + // Let searchExecResult be RegExpBuiltinExec(urlPattern's search component's + // regular expression, search). + auto search_exec_result = + regex_provider::regex_search(search, search_component.regexp); + + if (!search_exec_result) { + return std::nullopt; + } + + // Let hashExecResult be RegExpBuiltinExec(urlPattern's hash component's + // regular expression, hash). + auto hash_exec_result = + regex_provider::regex_search(hash, hash_component.regexp); + + if (!hash_exec_result) { + return std::nullopt; + } + + // Let result be a new URLPatternResult. + auto result = url_pattern_result{}; + // Set result["inputs"] to inputs. + result.inputs = std::move(inputs); + // Set result["protocol"] to the result of creating a component match result + // given urlPattern's protocol component, protocol, and protocolExecResult. + result.protocol = protocol_component.create_component_match_result( + std::move(protocol), std::move(*protocol_exec_result)); + + // Set result["username"] to the result of creating a component match result + // given urlPattern's username component, username, and usernameExecResult. + result.username = username_component.create_component_match_result( + std::move(username), std::move(*username_exec_result)); + + // Set result["password"] to the result of creating a component match result + // given urlPattern's password component, password, and passwordExecResult. + result.password = password_component.create_component_match_result( + std::move(password), std::move(*password_exec_result)); + + // Set result["hostname"] to the result of creating a component match result + // given urlPattern's hostname component, hostname, and hostnameExecResult. + result.hostname = hostname_component.create_component_match_result( + std::move(hostname), std::move(*hostname_exec_result)); + + // Set result["port"] to the result of creating a component match result given + // urlPattern's port component, port, and portExecResult. + result.port = port_component.create_component_match_result( + std::move(port), std::move(*port_exec_result)); + + // Set result["pathname"] to the result of creating a component match result + // given urlPattern's pathname component, pathname, and pathnameExecResult. + result.pathname = pathname_component.create_component_match_result( + std::move(pathname), std::move(*pathname_exec_result)); + + // Set result["search"] to the result of creating a component match result + // given urlPattern's search component, search, and searchExecResult. + result.search = search_component.create_component_match_result( + std::move(search), std::move(*search_exec_result)); + + // Set result["hash"] to the result of creating a component match result given + // urlPattern's hash component, hash, and hashExecResult. + result.hash = hash_component.create_component_match_result( + std::move(hash), std::move(*hash_exec_result)); + + return result; +} + +} // namespace ada +#endif // ADA_INCLUDE_URL_PATTERN +#endif +/* end file include/ada/url_pattern-inl.h */ +/* begin file include/ada/url_pattern_helpers-inl.h */ +/** + * @file url_pattern_helpers-inl.h + * @brief Declaration for the URLPattern helpers. + */ +#ifndef ADA_URL_PATTERN_HELPERS_INL_H +#define ADA_URL_PATTERN_HELPERS_INL_H + +#include +#include + + +#if ADA_INCLUDE_URL_PATTERN +namespace ada::url_pattern_helpers { +#if defined(ADA_TESTING) || defined(ADA_LOGGING) +inline std::string to_string(token_type type) { + switch (type) { + case token_type::INVALID_CHAR: + return "INVALID_CHAR"; + case token_type::OPEN: + return "OPEN"; + case token_type::CLOSE: + return "CLOSE"; + case token_type::REGEXP: + return "REGEXP"; + case token_type::NAME: + return "NAME"; + case token_type::CHAR: + return "CHAR"; + case token_type::ESCAPED_CHAR: + return "ESCAPED_CHAR"; + case token_type::OTHER_MODIFIER: + return "OTHER_MODIFIER"; + case token_type::ASTERISK: + return "ASTERISK"; + case token_type::END: + return "END"; + default: + ada::unreachable(); + } +} +#endif // defined(ADA_TESTING) || defined(ADA_LOGGING) + +template +constexpr void constructor_string_parser::rewind() { + // Set parser's token index to parser's component start. + token_index = component_start; + // Set parser's token increment to 0. + token_increment = 0; +} + +template +constexpr bool constructor_string_parser::is_hash_prefix() { + // Return the result of running is a non-special pattern char given parser, + // parser's token index and "#". + return is_non_special_pattern_char(token_index, '#'); +} + +template +constexpr bool constructor_string_parser::is_search_prefix() { + // If result of running is a non-special pattern char given parser, parser's + // token index and "?" is true, then return true. + if (is_non_special_pattern_char(token_index, '?')) { + return true; + } + + // If parser's token list[parser's token index]'s value is not "?", then + // return false. + if (token_list[token_index].value != "?") { + return false; + } + + // If previous index is less than 0, then return true. + if (token_index == 0) return true; + // Let previous index be parser's token index - 1. + auto previous_index = token_index - 1; + // Let previous token be the result of running get a safe token given parser + // and previous index. + auto previous_token = get_safe_token(previous_index); + ADA_ASSERT_TRUE(previous_token); + // If any of the following are true, then return false: + // - previous token's type is "name". + // - previous token's type is "regexp". + // - previous token's type is "close". + // - previous token's type is "asterisk". + return !(previous_token->type == token_type::NAME || + previous_token->type == token_type::REGEXP || + previous_token->type == token_type::CLOSE || + previous_token->type == token_type::ASTERISK); +} + +template +constexpr bool +constructor_string_parser::is_non_special_pattern_char( + size_t index, uint32_t value) const { + // Let token be the result of running get a safe token given parser and index. + auto token = get_safe_token(index); + ADA_ASSERT_TRUE(token); + + // If token's value is not value, then return false. + // TODO: Remove this once we make sure get_safe_token returns a non-empty + // string. + if (!token->value.empty() && + static_cast(token->value[0]) != value) { + return false; + } + + // If any of the following are true: + // - token's type is "char"; + // - token's type is "escaped-char"; or + // - token's type is "invalid-char", + // - then return true. + return token->type == token_type::CHAR || + token->type == token_type::ESCAPED_CHAR || + token->type == token_type::INVALID_CHAR; +} + +template +constexpr const token* +constructor_string_parser::get_safe_token(size_t index) const { + // If index is less than parser's token list's size, then return parser's + // token list[index]. + if (index < token_list.size()) [[likely]] { + return &token_list[index]; + } + + // Assert: parser's token list's size is greater than or equal to 1. + ADA_ASSERT_TRUE(!token_list.empty()); + + // Let token be parser's token list[last index]. + // Assert: token's type is "end". + ADA_ASSERT_TRUE(token_list.back().type == token_type::END); + + // Return token. + return &token_list.back(); +} + +template +constexpr bool constructor_string_parser::is_group_open() + const { + // If parser's token list[parser's token index]'s type is "open", then return + // true. + return token_list[token_index].type == token_type::OPEN; +} + +template +constexpr bool constructor_string_parser::is_group_close() + const { + // If parser's token list[parser's token index]'s type is "close", then return + // true. + return token_list[token_index].type == token_type::CLOSE; +} + +template +constexpr bool +constructor_string_parser::next_is_authority_slashes() const { + // If the result of running is a non-special pattern char given parser, + // parser's token index + 1, and "/" is false, then return false. + if (!is_non_special_pattern_char(token_index + 1, '/')) { + return false; + } + // If the result of running is a non-special pattern char given parser, + // parser's token index + 2, and "/" is false, then return false. + if (!is_non_special_pattern_char(token_index + 2, '/')) { + return false; + } + return true; +} + +template +constexpr bool constructor_string_parser::is_protocol_suffix() + const { + // Return the result of running is a non-special pattern char given parser, + // parser's token index, and ":". + return is_non_special_pattern_char(token_index, ':'); +} + +template +void constructor_string_parser::change_state(State new_state, + size_t skip) { + // If parser's state is not "init", not "authority", and not "done", then set + // parser's result[parser's state] to the result of running make a component + // string given parser. + if (state != State::INIT && state != State::AUTHORITY && + state != State::DONE) { + auto value = make_component_string(); + // TODO: Simplify this. + switch (state) { + case State::PROTOCOL: { + result.protocol = value; + break; + } + case State::USERNAME: { + result.username = value; + break; + } + case State::PASSWORD: { + result.password = value; + break; + } + case State::HOSTNAME: { + result.hostname = value; + break; + } + case State::PORT: { + result.port = value; + break; + } + case State::PATHNAME: { + result.pathname = value; + break; + } + case State::SEARCH: { + result.search = value; + break; + } + case State::HASH: { + result.hash = value; + break; + } + default: + ada::unreachable(); + } + } + + // If parser's state is not "init" and new state is not "done", then: + if (state != State::INIT && new_state != State::DONE) { + // If parser's state is "protocol", "authority", "username", or "password"; + // new state is "port", "pathname", "search", or "hash"; and parser's + // result["hostname"] does not exist, then set parser's result["hostname"] + // to the empty string. + if ((state == State::PROTOCOL || state == State::AUTHORITY || + state == State::USERNAME || state == State::PASSWORD) && + (new_state == State::PORT || new_state == State::PATHNAME || + new_state == State::SEARCH || new_state == State::HASH) && + !result.hostname) + result.hostname = ""; + } + + // If parser's state is "protocol", "authority", "username", "password", + // "hostname", or "port"; new state is "search" or "hash"; and parser's + // result["pathname"] does not exist, then: + if ((state == State::PROTOCOL || state == State::AUTHORITY || + state == State::USERNAME || state == State::PASSWORD || + state == State::HOSTNAME || state == State::PORT) && + (new_state == State::SEARCH || new_state == State::HASH) && + !result.pathname) { + if (protocol_matches_a_special_scheme_flag) { + result.pathname = "/"; + } else { + // Otherwise, set parser's result["pathname"] to the empty string. + result.pathname = ""; + } + } + + // If parser's state is "protocol", "authority", "username", "password", + // "hostname", "port", or "pathname"; new state is "hash"; and parser's + // result["search"] does not exist, then set parser's result["search"] to + // the empty string. + if ((state == State::PROTOCOL || state == State::AUTHORITY || + state == State::USERNAME || state == State::PASSWORD || + state == State::HOSTNAME || state == State::PORT || + state == State::PATHNAME) && + new_state == State::HASH && !result.search) { + result.search = ""; + } + + // Set parser's state to new state. + state = new_state; + // Increment parser's token index by skip. + token_index += skip; + // Set parser's component start to parser's token index. + component_start = token_index; + // Set parser's token increment to 0. + token_increment = 0; +} + +template +std::string constructor_string_parser::make_component_string() { + // Assert: parser's token index is less than parser's token list's size. + ADA_ASSERT_TRUE(token_index < token_list.size()); + + // Let token be parser's token list[parser's token index]. + // Let end index be token's index. + const auto end_index = token_list[token_index].index; + // Let component start token be the result of running get a safe token given + // parser and parser's component start. + const auto component_start_token = get_safe_token(component_start); + ADA_ASSERT_TRUE(component_start_token); + // Let component start input index be component start token's index. + const auto component_start_input_index = component_start_token->index; + // Return the code point substring from component start input index to end + // index within parser's input. + return input.substr(component_start_input_index, + end_index - component_start_input_index); +} + +template +constexpr bool +constructor_string_parser::is_an_identity_terminator() const { + // Return the result of running is a non-special pattern char given parser, + // parser's token index, and "@". + return is_non_special_pattern_char(token_index, '@'); +} + +template +constexpr bool constructor_string_parser::is_pathname_start() + const { + // Return the result of running is a non-special pattern char given parser, + // parser's token index, and "/". + return is_non_special_pattern_char(token_index, '/'); +} + +template +constexpr bool constructor_string_parser::is_password_prefix() + const { + // Return the result of running is a non-special pattern char given parser, + // parser's token index, and ":". + return is_non_special_pattern_char(token_index, ':'); +} + +template +constexpr bool constructor_string_parser::is_an_ipv6_open() + const { + // Return the result of running is a non-special pattern char given parser, + // parser's token index, and "[". + return is_non_special_pattern_char(token_index, '['); +} + +template +constexpr bool constructor_string_parser::is_an_ipv6_close() + const { + // Return the result of running is a non-special pattern char given parser, + // parser's token index, and "]". + return is_non_special_pattern_char(token_index, ']'); +} + +template +constexpr bool constructor_string_parser::is_port_prefix() + const { + // Return the result of running is a non-special pattern char given parser, + // parser's token index, and ":". + return is_non_special_pattern_char(token_index, ':'); +} + +constexpr void Tokenizer::get_next_code_point() { + ada_log("Tokenizer::get_next_code_point called with index=", next_index); + ADA_ASSERT_TRUE(next_index < input.size()); + // this assumes that we have a valid, non-truncated UTF-8 stream. + code_point = 0; + size_t number_bytes = 0; + unsigned char first_byte = input[next_index]; + + if ((first_byte & 0x80) == 0) { + // 1-byte character (ASCII) + next_index++; + code_point = first_byte; + ada_log("Tokenizer::get_next_code_point returning ASCII code point=", + uint32_t(code_point)); + ada_log("Tokenizer::get_next_code_point next_index =", next_index, + " input.size()=", input.size()); + return; + } + ada_log("Tokenizer::get_next_code_point read first byte=", + uint32_t(first_byte)); + if ((first_byte & 0xE0) == 0xC0) { + code_point = first_byte & 0x1F; + number_bytes = 2; + ada_log("Tokenizer::get_next_code_point two bytes"); + } else if ((first_byte & 0xF0) == 0xE0) { + code_point = first_byte & 0x0F; + number_bytes = 3; + ada_log("Tokenizer::get_next_code_point three bytes"); + } else if ((first_byte & 0xF8) == 0xF0) { + code_point = first_byte & 0x07; + number_bytes = 4; + ada_log("Tokenizer::get_next_code_point four bytes"); + } + ADA_ASSERT_TRUE(number_bytes + next_index <= input.size()); + + for (size_t i = 1 + next_index; i < number_bytes + next_index; ++i) { + unsigned char byte = input[i]; + ada_log("Tokenizer::get_next_code_point read byte=", uint32_t(byte)); + code_point = (code_point << 6) | (byte & 0x3F); + } + ada_log("Tokenizer::get_next_code_point returning non-ASCII code point=", + uint32_t(code_point)); + ada_log("Tokenizer::get_next_code_point next_index =", next_index, + " input.size()=", input.size()); + next_index += number_bytes; +} + +constexpr void Tokenizer::seek_and_get_next_code_point(size_t new_index) { + ada_log("Tokenizer::seek_and_get_next_code_point called with new_index=", + new_index); + // Set tokenizer's next index to index. + next_index = new_index; + // Run get the next code point given tokenizer. + get_next_code_point(); +} + +inline void Tokenizer::add_token(token_type type, size_t next_position, + size_t value_position, size_t value_length) { + ada_log("Tokenizer::add_token called with type=", to_string(type), + " next_position=", next_position, " value_position=", value_position); + ADA_ASSERT_TRUE(next_position >= value_position); + + // Let token be a new token. + // Set token's type to type. + // Set token's index to tokenizer's index. + // Set token's value to the code point substring from value position with + // length value length within tokenizer's input. + // Append token to the back of tokenizer's token list. + token_list.emplace_back(type, index, + input.substr(value_position, value_length)); + // Set tokenizer's index to next position. + index = next_position; +} + +inline void Tokenizer::add_token_with_default_length(token_type type, + size_t next_position, + size_t value_position) { + // Let computed length be next position - value position. + auto computed_length = next_position - value_position; + // Run add a token given tokenizer, type, next position, value position, and + // computed length. + add_token(type, next_position, value_position, computed_length); +} + +inline void Tokenizer::add_token_with_defaults(token_type type) { + ada_log("Tokenizer::add_token_with_defaults called with type=", + to_string(type)); + // Run add a token with default length given tokenizer, type, tokenizer's next + // index, and tokenizer's index. + add_token_with_default_length(type, next_index, index); +} + +inline ada_warn_unused std::optional +Tokenizer::process_tokenizing_error(size_t next_position, + size_t value_position) { + // If tokenizer's policy is "strict", then throw a TypeError. + if (policy == token_policy::strict) { + ada_log("process_tokenizing_error failed with next_position=", + next_position, " value_position=", value_position); + return errors::type_error; + } + // Assert: tokenizer's policy is "lenient". + ADA_ASSERT_TRUE(policy == token_policy::lenient); + // Run add a token with default length given tokenizer, "invalid-char", next + // position, and value position. + add_token_with_default_length(token_type::INVALID_CHAR, next_position, + value_position); + return std::nullopt; +} + +template +token* url_pattern_parser::try_consume_modifier_token() { + // Let token be the result of running try to consume a token given parser and + // "other-modifier". + auto token = try_consume_token(token_type::OTHER_MODIFIER); + // If token is not null, then return token. + if (token) return token; + // Set token to the result of running try to consume a token given parser and + // "asterisk". + // Return token. + return try_consume_token(token_type::ASTERISK); +} + +template +token* url_pattern_parser::try_consume_regexp_or_wildcard_token( + const token* name_token) { + // Let token be the result of running try to consume a token given parser and + // "regexp". + auto token = try_consume_token(token_type::REGEXP); + // If name token is null and token is null, then set token to the result of + // running try to consume a token given parser and "asterisk". + if (!name_token && !token) { + token = try_consume_token(token_type::ASTERISK); + } + // Return token. + return token; +} + +template +token* url_pattern_parser::try_consume_token(token_type type) { + ada_log("url_pattern_parser::try_consume_token called with type=", + to_string(type)); + // Assert: parser's index is less than parser's token list size. + ADA_ASSERT_TRUE(index < tokens.size()); + // Let next token be parser's token list[parser's index]. + auto& next_token = tokens[index]; + // If next token's type is not type return null. + if (next_token.type != type) return nullptr; + // Increase parser's index by 1. + index++; + // Return next token. + return &next_token; +} + +template +std::string url_pattern_parser::consume_text() { + // Let result be the empty string. + std::string result{}; + // While true: + while (true) { + // Let token be the result of running try to consume a token given parser + // and "char". + auto token = try_consume_token(token_type::CHAR); + // If token is null, then set token to the result of running try to consume + // a token given parser and "escaped-char". + if (!token) token = try_consume_token(token_type::ESCAPED_CHAR); + // If token is null, then break. + if (!token) break; + // Append token's value to the end of result. + result.append(token->value); + } + // Return result. + return result; +} + +template +bool url_pattern_parser::consume_required_token(token_type type) { + ada_log("url_pattern_parser::consume_required_token called with type=", + to_string(type)); + // Let result be the result of running try to consume a token given parser and + // type. + return try_consume_token(type) != nullptr; +} + +template +std::optional +url_pattern_parser::maybe_add_part_from_the_pending_fixed_value() { + // If parser's pending fixed value is the empty string, then return. + if (pending_fixed_value.empty()) { + ada_log("pending_fixed_value is empty"); + return std::nullopt; + } + // Let encoded value be the result of running parser's encoding callback given + // parser's pending fixed value. + auto encoded_value = encoding_callback(pending_fixed_value); + if (!encoded_value) { + ada_log("failed to encode pending_fixed_value: ", pending_fixed_value); + return encoded_value.error(); + } + // Set parser's pending fixed value to the empty string. + pending_fixed_value.clear(); + // Let part be a new part whose type is "fixed-text", value is encoded value, + // and modifier is "none". + // Append part to parser's part list. + parts.emplace_back(url_pattern_part_type::FIXED_TEXT, + std::move(*encoded_value), + url_pattern_part_modifier::none); + return std::nullopt; +} + +template +std::optional url_pattern_parser::add_part( + std::string_view prefix, token* name_token, token* regexp_or_wildcard_token, + std::string_view suffix, token* modifier_token) { + // Let modifier be "none". + auto modifier = url_pattern_part_modifier::none; + // If modifier token is not null: + if (modifier_token) { + // If modifier token's value is "?" then set modifier to "optional". + if (modifier_token->value == "?") { + modifier = url_pattern_part_modifier::optional; + } else if (modifier_token->value == "*") { + // Otherwise if modifier token's value is "*" then set modifier to + // "zero-or-more". + modifier = url_pattern_part_modifier::zero_or_more; + } else if (modifier_token->value == "+") { + // Otherwise if modifier token's value is "+" then set modifier to + // "one-or-more". + modifier = url_pattern_part_modifier::one_or_more; + } + } + // If name token is null and regexp or wildcard token is null and modifier + // is "none": + if (!name_token && !regexp_or_wildcard_token && + modifier == url_pattern_part_modifier::none) { + // Append prefix to the end of parser's pending fixed value. + pending_fixed_value.append(prefix); + return std::nullopt; + } + // Run maybe add a part from the pending fixed value given parser. + if (auto error = maybe_add_part_from_the_pending_fixed_value()) { + return *error; + } + // If name token is null and regexp or wildcard token is null: + if (!name_token && !regexp_or_wildcard_token) { + // Assert: suffix is the empty string. + ADA_ASSERT_TRUE(suffix.empty()); + // If prefix is the empty string, then return. + if (prefix.empty()) return std::nullopt; + // Let encoded value be the result of running parser's encoding callback + // given prefix. + auto encoded_value = encoding_callback(prefix); + if (!encoded_value) { + return encoded_value.error(); + } + // Let part be a new part whose type is "fixed-text", value is encoded + // value, and modifier is modifier. + // Append part to parser's part list. + parts.emplace_back(url_pattern_part_type::FIXED_TEXT, + std::move(*encoded_value), modifier); + return std::nullopt; + } + // Let regexp value be the empty string. + std::string regexp_value{}; + // If regexp or wildcard token is null, then set regexp value to parser's + // segment wildcard regexp. + if (!regexp_or_wildcard_token) { + regexp_value = segment_wildcard_regexp; + } else if (regexp_or_wildcard_token->type == token_type::ASTERISK) { + // Otherwise if regexp or wildcard token's type is "asterisk", then set + // regexp value to the full wildcard regexp value. + regexp_value = ".*"; + } else { + // Otherwise set regexp value to regexp or wildcard token's value. + regexp_value = regexp_or_wildcard_token->value; + } + // Let type be "regexp". + auto type = url_pattern_part_type::REGEXP; + // If regexp value is parser's segment wildcard regexp: + if (regexp_value == segment_wildcard_regexp) { + // Set type to "segment-wildcard". + type = url_pattern_part_type::SEGMENT_WILDCARD; + // Set regexp value to the empty string. + regexp_value.clear(); + } else if (regexp_value == ".*") { + // Otherwise if regexp value is the full wildcard regexp value: + // Set type to "full-wildcard". + type = url_pattern_part_type::FULL_WILDCARD; + // Set regexp value to the empty string. + regexp_value.clear(); + } + // Let name be the empty string. + std::string name{}; + // If name token is not null, then set name to name token's value. + if (name_token) { + name = name_token->value; + } else if (regexp_or_wildcard_token != nullptr) { + // Otherwise if regexp or wildcard token is not null: + // Set name to parser's next numeric name, serialized. + name = std::to_string(next_numeric_name); + // Increment parser's next numeric name by 1. + next_numeric_name++; + } + // If the result of running is a duplicate name given parser and name is + // true, then throw a TypeError. + if (std::ranges::any_of( + parts, [&name](const auto& part) { return part.name == name; })) { + return errors::type_error; + } + // Let encoded prefix be the result of running parser's encoding callback + // given prefix. + auto encoded_prefix = encoding_callback(prefix); + if (!encoded_prefix) return encoded_prefix.error(); + // Let encoded suffix be the result of running parser's encoding callback + // given suffix. + auto encoded_suffix = encoding_callback(suffix); + if (!encoded_suffix) return encoded_suffix.error(); + // Let part be a new part whose type is type, value is regexp value, + // modifier is modifier, name is name, prefix is encoded prefix, and suffix + // is encoded suffix. + // Append part to parser's part list. + parts.emplace_back(type, std::move(regexp_value), modifier, std::move(name), + std::move(*encoded_prefix), std::move(*encoded_suffix)); + return std::nullopt; +} + +template +tl::expected, errors> parse_pattern_string( + std::string_view input, url_pattern_compile_component_options& options, + F& encoding_callback) { + ada_log("parse_pattern_string input=", input); + // Let parser be a new pattern parser whose encoding callback is encoding + // callback and segment wildcard regexp is the result of running generate a + // segment wildcard regexp given options. + auto parser = url_pattern_parser( + encoding_callback, generate_segment_wildcard_regexp(options)); + // Set parser's token list to the result of running tokenize given input and + // "strict". + auto tokenize_result = tokenize(input, token_policy::strict); + if (!tokenize_result) { + ada_log("parse_pattern_string tokenize failed"); + return tl::unexpected(tokenize_result.error()); + } + parser.tokens = std::move(*tokenize_result); + + // While parser's index is less than parser's token list's size: + while (parser.can_continue()) { + // Let char token be the result of running try to consume a token given + // parser and "char". + auto char_token = parser.try_consume_token(token_type::CHAR); + // Let name token be the result of running try to consume a token given + // parser and "name". + auto name_token = parser.try_consume_token(token_type::NAME); + // Let regexp or wildcard token be the result of running try to consume a + // regexp or wildcard token given parser and name token. + auto regexp_or_wildcard_token = + parser.try_consume_regexp_or_wildcard_token(name_token); + // If name token is not null or regexp or wildcard token is not null: + if (name_token || regexp_or_wildcard_token) { + // Let prefix be the empty string. + std::string prefix{}; + // If char token is not null then set prefix to char token's value. + if (char_token) prefix = char_token->value; + // If prefix is not the empty string and not options's prefix code point: + if (!prefix.empty() && prefix != options.get_prefix()) { + // Append prefix to the end of parser's pending fixed value. + parser.pending_fixed_value.append(prefix); + // Set prefix to the empty string. + prefix.clear(); + } + // Run maybe add a part from the pending fixed value given parser. + if (auto error = parser.maybe_add_part_from_the_pending_fixed_value()) { + ada_log("maybe_add_part_from_the_pending_fixed_value failed"); + return tl::unexpected(*error); + } + // Let modifier token be the result of running try to consume a modifier + // token given parser. + auto modifier_token = parser.try_consume_modifier_token(); + // Run add a part given parser, prefix, name token, regexp or wildcard + // token, the empty string, and modifier token. + if (auto error = + parser.add_part(prefix, name_token, regexp_or_wildcard_token, "", + modifier_token)) { + ada_log("parser.add_part failed"); + return tl::unexpected(*error); + } + // Continue. + continue; + } + + // Let fixed token be char token. + auto fixed_token = char_token; + // If fixed token is null, then set fixed token to the result of running try + // to consume a token given parser and "escaped-char". + if (!fixed_token) + fixed_token = parser.try_consume_token(token_type::ESCAPED_CHAR); + // If fixed token is not null: + if (fixed_token) { + // Append fixed token's value to parser's pending fixed value. + parser.pending_fixed_value.append(fixed_token->value); + // Continue. + continue; + } + // Let open token be the result of running try to consume a token given + // parser and "open". + auto open_token = parser.try_consume_token(token_type::OPEN); + // If open token is not null: + if (open_token) { + // Set prefix be the result of running consume text given parser. + auto prefix_ = parser.consume_text(); + // Set name token to the result of running try to consume a token given + // parser and "name". + name_token = parser.try_consume_token(token_type::NAME); + // Set regexp or wildcard token to the result of running try to consume a + // regexp or wildcard token given parser and name token. + regexp_or_wildcard_token = + parser.try_consume_regexp_or_wildcard_token(name_token); + // Let suffix be the result of running consume text given parser. + auto suffix_ = parser.consume_text(); + // Run consume a required token given parser and "close". + if (!parser.consume_required_token(token_type::CLOSE)) { + ada_log("parser.consume_required_token failed"); + return tl::unexpected(errors::type_error); + } + // Set modifier token to the result of running try to consume a modifier + // token given parser. + auto modifier_token = parser.try_consume_modifier_token(); + // Run add a part given parser, prefix, name token, regexp or wildcard + // token, suffix, and modifier token. + if (auto error = + parser.add_part(prefix_, name_token, regexp_or_wildcard_token, + suffix_, modifier_token)) { + return tl::unexpected(*error); + } + // Continue. + continue; + } + // Run maybe add a part from the pending fixed value given parser. + if (auto error = parser.maybe_add_part_from_the_pending_fixed_value()) { + ada_log("maybe_add_part_from_the_pending_fixed_value failed on line 992"); + return tl::unexpected(*error); + } + // Run consume a required token given parser and "end". + if (!parser.consume_required_token(token_type::END)) { + return tl::unexpected(errors::type_error); + } + } + ada_log("parser.parts size is: ", parser.parts.size()); + // Return parser's part list. + return parser.parts; +} + +template +bool protocol_component_matches_special_scheme( + url_pattern_component& component) { + // let's avoid unnecessary copy here. + auto& regex = component.regexp; + return regex_provider::regex_match("http", regex) || + regex_provider::regex_match("https", regex) || + regex_provider::regex_match("ws", regex) || + regex_provider::regex_match("wss", regex) || + regex_provider::regex_match("ftp", regex); +} + +template +inline std::optional constructor_string_parser< + regex_provider>::compute_protocol_matches_special_scheme_flag() { + ada_log( + "constructor_string_parser::compute_protocol_matches_special_scheme_" + "flag"); + // Let protocol string be the result of running make a component string given + // parser. + auto protocol_string = make_component_string(); + // Let protocol component be the result of compiling a component given + // protocol string, canonicalize a protocol, and default options. + auto protocol_component = url_pattern_component::compile( + protocol_string, canonicalize_protocol, + url_pattern_compile_component_options::DEFAULT); + if (!protocol_component) { + ada_log("url_pattern_component::compile failed for protocol_string ", + protocol_string); + return protocol_component.error(); + } + // If the result of running protocol component matches a special scheme given + // protocol component is true, then set parser's protocol matches a special + // scheme flag to true. + if (protocol_component_matches_special_scheme(*protocol_component)) { + protocol_matches_a_special_scheme_flag = true; + } + return std::nullopt; +} + +template +tl::expected +constructor_string_parser::parse(std::string_view input) { + ada_log("constructor_string_parser::parse input=", input); + // Let parser be a new constructor string parser whose input is input and + // token list is the result of running tokenize given input and "lenient". + auto token_list = tokenize(input, token_policy::lenient); + if (!token_list) { + return tl::unexpected(token_list.error()); + } + auto parser = constructor_string_parser(input, std::move(*token_list)); + + // While parser's token index is less than parser's token list size: + while (parser.token_index < parser.token_list.size()) { + // Set parser's token increment to 1. + parser.token_increment = 1; + + // If parser's token list[parser's token index]'s type is "end" then: + if (parser.token_list[parser.token_index].type == token_type::END) { + // If parser's state is "init": + if (parser.state == State::INIT) { + // Run rewind given parser. + parser.rewind(); + // If the result of running is a hash prefix given parser is true, then + // run change state given parser, "hash" and 1. + if (parser.is_hash_prefix()) { + parser.change_state(State::HASH, 1); + } else if (parser.is_search_prefix()) { + // Otherwise if the result of running is a search prefix given parser + // is true: Run change state given parser, "search" and 1. + parser.change_state(State::SEARCH, 1); + } else { + // Run change state given parser, "pathname" and 0. + parser.change_state(State::PATHNAME, 0); + } + // Increment parser's token index by parser's token increment. + parser.token_index += parser.token_increment; + // Continue. + continue; + } + + if (parser.state == State::AUTHORITY) { + // If parser's state is "authority": + // Run rewind and set state given parser, and "hostname". + parser.rewind(); + parser.change_state(State::HOSTNAME, 0); + // Increment parser's token index by parser's token increment. + parser.token_index += parser.token_increment; + // Continue. + continue; + } + + // Run change state given parser, "done" and 0. + parser.change_state(State::DONE, 0); + // Break. + break; + } + + // If the result of running is a group open given parser is true: + if (parser.is_group_open()) { + // Increment parser's group depth by 1. + parser.group_depth += 1; + // Increment parser's token index by parser's token increment. + parser.token_index += parser.token_increment; + } + + // If parser's group depth is greater than 0: + if (parser.group_depth > 0) { + // If the result of running is a group close given parser is true, then + // decrement parser's group depth by 1. + if (parser.is_group_close()) { + parser.group_depth -= 1; + } else { + // Increment parser's token index by parser's token increment. + parser.token_index += parser.token_increment; + continue; + } + } + + // Switch on parser's state and run the associated steps: + switch (parser.state) { + case State::INIT: { + // If the result of running is a protocol suffix given parser is true: + if (parser.is_protocol_suffix()) { + // Run rewind and set state given parser and "protocol". + parser.rewind(); + parser.change_state(State::PROTOCOL, 0); + } + break; + } + case State::PROTOCOL: { + // If the result of running is a protocol suffix given parser is true: + if (parser.is_protocol_suffix()) { + // Run compute protocol matches a special scheme flag given parser. + if (const auto error = + parser.compute_protocol_matches_special_scheme_flag()) { + ada_log("compute_protocol_matches_special_scheme_flag failed"); + return tl::unexpected(*error); + } + // Let next state be "pathname". + auto next_state = State::PATHNAME; + // Let skip be 1. + auto skip = 1; + // If the result of running next is authority slashes given parser is + // true: + if (parser.next_is_authority_slashes()) { + // Set next state to "authority". + next_state = State::AUTHORITY; + // Set skip to 3. + skip = 3; + } else if (parser.protocol_matches_a_special_scheme_flag) { + // Otherwise if parser's protocol matches a special scheme flag is + // true, then set next state to "authority". + next_state = State::AUTHORITY; + } + + // Run change state given parser, next state, and skip. + parser.change_state(next_state, skip); + } + break; + } + case State::AUTHORITY: { + // If the result of running is an identity terminator given parser is + // true, then run rewind and set state given parser and "username". + if (parser.is_an_identity_terminator()) { + parser.rewind(); + parser.change_state(State::USERNAME, 0); + } else if (parser.is_pathname_start() || parser.is_search_prefix() || + parser.is_hash_prefix()) { + // Otherwise if any of the following are true: + // - the result of running is a pathname start given parser; + // - the result of running is a search prefix given parser; or + // - the result of running is a hash prefix given parser, + // then run rewind and set state given parser and "hostname". + parser.rewind(); + parser.change_state(State::HOSTNAME, 0); + } + break; + } + case State::USERNAME: { + // If the result of running is a password prefix given parser is true, + // then run change state given parser, "password", and 1. + if (parser.is_password_prefix()) { + parser.change_state(State::PASSWORD, 1); + } else if (parser.is_an_identity_terminator()) { + // Otherwise if the result of running is an identity terminator given + // parser is true, then run change state given parser, "hostname", + // and 1. + parser.change_state(State::HOSTNAME, 1); + } + break; + } + case State::PASSWORD: { + // If the result of running is an identity terminator given parser is + // true, then run change state given parser, "hostname", and 1. + if (parser.is_an_identity_terminator()) { + parser.change_state(State::HOSTNAME, 1); + } + break; + } + case State::HOSTNAME: { + // If the result of running is an IPv6 open given parser is true, then + // increment parser's hostname IPv6 bracket depth by 1. + if (parser.is_an_ipv6_open()) { + parser.hostname_ipv6_bracket_depth += 1; + } else if (parser.is_an_ipv6_close()) { + // Otherwise if the result of running is an IPv6 close given parser is + // true, then decrement parser's hostname IPv6 bracket depth by 1. + parser.hostname_ipv6_bracket_depth -= 1; + } else if (parser.is_port_prefix() && + parser.hostname_ipv6_bracket_depth == 0) { + // Otherwise if the result of running is a port prefix given parser is + // true and parser's hostname IPv6 bracket depth is zero, then run + // change state given parser, "port", and 1. + parser.change_state(State::PORT, 1); + } else if (parser.is_pathname_start()) { + // Otherwise if the result of running is a pathname start given parser + // is true, then run change state given parser, "pathname", and 0. + parser.change_state(State::PATHNAME, 0); + } else if (parser.is_search_prefix()) { + // Otherwise if the result of running is a search prefix given parser + // is true, then run change state given parser, "search", and 1. + parser.change_state(State::SEARCH, 1); + } else if (parser.is_hash_prefix()) { + // Otherwise if the result of running is a hash prefix given parser is + // true, then run change state given parser, "hash", and 1. + parser.change_state(State::HASH, 1); + } + + break; + } + case State::PORT: { + // If the result of running is a pathname start given parser is true, + // then run change state given parser, "pathname", and 0. + if (parser.is_pathname_start()) { + parser.change_state(State::PATHNAME, 0); + } else if (parser.is_search_prefix()) { + // Otherwise if the result of running is a search prefix given parser + // is true, then run change state given parser, "search", and 1. + parser.change_state(State::SEARCH, 1); + } else if (parser.is_hash_prefix()) { + // Otherwise if the result of running is a hash prefix given parser is + // true, then run change state given parser, "hash", and 1. + parser.change_state(State::HASH, 1); + } + break; + } + case State::PATHNAME: { + // If the result of running is a search prefix given parser is true, + // then run change state given parser, "search", and 1. + if (parser.is_search_prefix()) { + parser.change_state(State::SEARCH, 1); + } else if (parser.is_hash_prefix()) { + // Otherwise if the result of running is a hash prefix given parser is + // true, then run change state given parser, "hash", and 1. + parser.change_state(State::HASH, 1); + } + break; + } + case State::SEARCH: { + // If the result of running is a hash prefix given parser is true, then + // run change state given parser, "hash", and 1. + if (parser.is_hash_prefix()) { + parser.change_state(State::HASH, 1); + } + break; + } + case State::HASH: { + // Do nothing + break; + } + default: { + // Assert: This step is never reached. + unreachable(); + } + } + + // Increment parser's token index by parser's token increment. + parser.token_index += parser.token_increment; + } + + // If parser's result contains "hostname" and not "port", then set parser's + // result["port"] to the empty string. + if (parser.result.hostname && !parser.result.port) { + parser.result.port = ""; + } + + // Return parser's result. + return parser.result; +} + +} // namespace ada::url_pattern_helpers +#endif // ADA_INCLUDE_URL_PATTERN +#endif +/* end file include/ada/url_pattern_helpers-inl.h */ + // Public API /* begin file include/ada/ada_version.h */ /** @@ -7256,13 +10515,13 @@ url_search_params_entries_iter::next() { #ifndef ADA_ADA_VERSION_H #define ADA_ADA_VERSION_H -#define ADA_VERSION "2.9.0" +#define ADA_VERSION "3.3.0" namespace ada { enum { - ADA_VERSION_MAJOR = 2, - ADA_VERSION_MINOR = 9, + ADA_VERSION_MAJOR = 3, + ADA_VERSION_MINOR = 3, ADA_VERSION_REVISION = 0, }; @@ -7270,61 +10529,35 @@ enum { #endif // ADA_ADA_VERSION_H /* end file include/ada/ada_version.h */ -/* begin file include/ada/implementation.h */ +/* begin file include/ada/implementation-inl.h */ /** - * @file implementation.h - * @brief Definitions for user facing functions for parsing URL and it's - * components. + * @file implementation-inl.h */ -#ifndef ADA_IMPLEMENTATION_H -#define ADA_IMPLEMENTATION_H - -#include -#include +#ifndef ADA_IMPLEMENTATION_INL_H +#define ADA_IMPLEMENTATION_INL_H -namespace ada { -enum class errors { generic_error }; -template -using result = tl::expected; -/** - * The URL parser takes a scalar value string input, with an optional null or - * base URL base (default null). The parser assumes the input is a valid ASCII - * or UTF-8 string. - * - * @param input the string input to analyze (must be valid ASCII or UTF-8) - * @param base_url the optional URL input to use as a base url. - * @return a parsed URL. - */ -template -ada_warn_unused ada::result parse( - std::string_view input, const result_type* base_url = nullptr); +#include +#include -extern template ada::result parse(std::string_view input, - const url* base_url); -extern template ada::result parse( - std::string_view input, const url_aggregator* base_url); +namespace ada { -/** - * Verifies whether the URL strings can be parsed. The function assumes - * that the inputs are valid ASCII or UTF-8 strings. - * @see https://url.spec.whatwg.org/#dom-url-canparse - * @return If URL can be parsed or not. - */ -bool can_parse(std::string_view input, - const std::string_view* base_input = nullptr); +#if ADA_INCLUDE_URL_PATTERN +template +ada_warn_unused tl::expected, errors> +parse_url_pattern(std::variant&& input, + const std::string_view* base_url, + const url_pattern_options* options) { + return parser::parse_url_pattern_impl(std::move(input), + base_url, options); +} +#endif // ADA_INCLUDE_URL_PATTERN -/** - * Computes a href string from a file path. The function assumes - * that the input is a valid ASCII or UTF-8 string. - * @return a href string (starts with file:://) - */ -std::string href_from_file(std::string_view path); } // namespace ada -#endif // ADA_IMPLEMENTATION_H -/* end file include/ada/implementation.h */ +#endif // ADA_IMPLEMENTATION_INL_H +/* end file include/ada/implementation-inl.h */ #endif // ADA_H /* end file include/ada.h */ diff --git a/test-app/runtime/src/main/cpp/napi/common/js_native_api.h b/test-app/runtime/src/main/cpp/napi/common/js_native_api.h index 97715d0b..c9b43624 100644 --- a/test-app/runtime/src/main/cpp/napi/common/js_native_api.h +++ b/test-app/runtime/src/main/cpp/napi/common/js_native_api.h @@ -3,8 +3,28 @@ #include "js_native_api_types.h" -#if !defined __cplusplus || (defined(_MSC_VER) && _MSC_VER < 1900) -typedef uint16_t char16_t; +// If you need __declspec(dllimport), either include instead, or +// define NAPI_EXTERN as __declspec(dllimport) on the compiler's command line. +#ifndef NAPI_EXTERN +#ifdef _WIN32 +#define NAPI_EXTERN __declspec(dllexport) +#elif defined(__wasm__) +#define NAPI_EXTERN \ + __attribute__((visibility("default"))) \ + __attribute__((__import_module__("napi"))) +#else +#define NAPI_EXTERN __attribute__((visibility("default"))) +#endif +#endif + +#define NAPI_AUTO_LENGTH SIZE_MAX + +#ifdef __cplusplus +#define EXTERN_C_START extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C_START +#define EXTERN_C_END #endif EXTERN_C_START @@ -17,6 +37,8 @@ EXTERN_C_START #define NAPI_VERSION_EXPERIMENTAL 2147483647 #define NAPI_VERSION 8 +#define NAPI_EXPERIMENTAL 1 + NAPI_EXTERN napi_status napi_get_last_error_info(napi_env env, const napi_extended_error_info **result); // Getters for defined singletons @@ -429,7 +451,12 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_reject_deferred(napi_env env, NAPI_EXTERN napi_status NAPI_CDECL napi_is_promise(napi_env env, napi_value value, bool *is_promise); - +#ifdef __PRIMJS__ +// Running a script +NAPI_EXTERN napi_status NAPI_CDECL napi_run_script(napi_env env, const char* script, + size_t length, const char* filename, + napi_value* result); +#else // Running a script NAPI_EXTERN napi_status NAPI_CDECL napi_run_script(napi_env env, napi_value script, @@ -439,6 +466,8 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_run_script_source(napi_env env, napi_value script, const char* source_url, napi_value* result); +#endif + // Memory management NAPI_EXTERN napi_status NAPI_CDECL napi_adjust_external_memory( @@ -538,11 +567,35 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_object_seal(napi_env env, napi_value object); #ifdef USE_HOST_OBJECT -NAPI_EXTERN napi_status NAPI_CDECL napi_create_host_object(napi_env env, napi_value value, napi_finalize finalize, void* data, bool is_array, napi_value getter, napi_value setter, napi_value* result); +// Creates a host object: a transparent proxy whose property operations are +// dispatched to the native `methods` (see napi_host_object_methods). `data` is +// passed to every callback and is also retrievable via +// napi_get_host_object_data; `finalize` (optional) runs when the host object is +// garbage-collected. `methods` and its `get`/`set` members are required. +NAPI_EXTERN napi_status NAPI_CDECL +napi_create_host_object(napi_env env, + napi_finalize finalize, + void* data, + const napi_host_object_methods* methods, + napi_value* result); -NAPI_EXTERN napi_status NAPI_CDECL napi_get_host_object_data(napi_env env, napi_value object, void** data); +NAPI_EXTERN napi_status NAPI_CDECL napi_get_host_object_data(napi_env env, + napi_value object, + void** data); + +NAPI_EXTERN napi_status NAPI_CDECL napi_is_host_object(napi_env env, + napi_value object, + bool* result); +#endif -NAPI_EXTERN napi_status NAPI_CDECL napi_is_host_object(napi_env env, napi_value object, bool* result); +#ifdef NAPI_EXPERIMENTAL +// Defers `finalize_cb` to a safe pass after the GC finalizer, where reference +// and other JS/GC-state-affecting Node-API calls are allowed. Implemented for +// the V8 engine. +NAPI_EXTERN napi_status NAPI_CDECL node_api_post_finalizer(napi_env env, + napi_finalize finalize_cb, + void* finalize_data, + void* finalize_hint); #endif #endif // NAPI_VERSION >= 8 diff --git a/test-app/runtime/src/main/cpp/napi/common/js_native_api_types.h b/test-app/runtime/src/main/cpp/napi/common/js_native_api_types.h index 7bff8110..c6bc066c 100644 --- a/test-app/runtime/src/main/cpp/napi/common/js_native_api_types.h +++ b/test-app/runtime/src/main/cpp/napi/common/js_native_api_types.h @@ -1,19 +1,42 @@ #ifndef SRC_JS_NATIVE_API_TYPES_H_ #define SRC_JS_NATIVE_API_TYPES_H_ -#include +// Use INT_MAX, this should only be consumed by the pre-processor anyway. +#define NAPI_VERSION_EXPERIMENTAL 2147483647 +#ifndef NAPI_VERSION +#ifdef NAPI_EXPERIMENTAL +#define NAPI_VERSION NAPI_VERSION_EXPERIMENTAL +#else +// The baseline version for Node-API. +// NAPI_VERSION controls which version is used by default when compiling +// a native addon. If the addon developer wants to use functions from a +// newer Node-API version not yet available in all LTS versions, they can +// set NAPI_VERSION to explicitly depend on that version. +#define NAPI_VERSION 8 +#endif +#endif -#ifdef __cplusplus -#define EXTERN_C_START \ -extern "C" \ -{ -#define EXTERN_C_END } +#if defined(NAPI_EXPERIMENTAL) && \ + !defined(NODE_API_EXPERIMENTAL_NO_WARNING) && \ + !defined(NODE_WANT_INTERNALS) +#ifdef _MSC_VER +#pragma message("NAPI_EXPERIMENTAL is enabled. " \ + "Experimental features may be unstable.") #else -#define EXTERN_C_START -#define EXTERN_C_END +#warning "NAPI_EXPERIMENTAL is enabled. " \ + "Experimental features may be unstable." #endif +#endif + +// This file needs to be compatible with C compilers. +// This is a public include file, and these includes have essentially +// become part of its API. +#include // NOLINT(modernize-deprecated-headers) +#include // NOLINT(modernize-deprecated-headers) -#define NAPI_EXTERN __attribute__((visibility("default"))) +#if !defined __cplusplus || (defined(_MSC_VER) && _MSC_VER < 1900) +typedef uint16_t char16_t; +#endif #ifndef NAPI_CDECL #ifdef _WIN32 @@ -23,56 +46,69 @@ extern "C" #endif #endif -EXTERN_C_START -typedef struct napi_runtime__ *napi_runtime; -typedef struct napi_env__ *napi_env; -typedef struct napi_value__ *napi_value; -typedef struct napi_ref__ *napi_ref; -typedef struct napi_handle_scope__ *napi_handle_scope; -typedef struct napi_handle_scope__ *napi_escapable_handle_scope; -typedef struct napi_callback_info__ *napi_callback_info; -typedef struct napi_deferred__* napi_deferred; +// JSVM API types are all opaque pointers for ABI stability +// typedef undefined structs instead of void* for compile time type safety +typedef struct napi_env__* napi_env; + +// We need to mark APIs which can be called during garbage collection (GC), +// meaning that they do not affect the state of the JS engine, and can +// therefore be called synchronously from a finalizer that itself runs +// synchronously during GC. Such APIs can receive either a `napi_env` or a +// `node_api_basic_env` as their first parameter, because we should be able to +// also call them during normal, non-garbage-collecting operations, whereas +// APIs that affect the state of the JS engine can only receive a `napi_env` as +// their first parameter, because we must not call them during GC. In lieu of +// inheritance, we use the properties of the const qualifier to accomplish +// this, because both a const and a non-const value can be passed to an API +// expecting a const value, but only a non-const value can be passed to an API +// expecting a non-const value. +// +// In conjunction with appropriate CFLAGS to warn us if we're passing a const +// (basic) environment into an API that expects a non-const environment, and +// the definition of basic finalizer function pointer types below, which +// receive a basic environment as their first parameter, and can thus only call +// basic APIs (unless the user explicitly casts the environment), we achieve +// the ability to ensure at compile time that we do not call APIs that affect +// the state of the JS engine from a synchronous (basic) finalizer. +#if !defined(NAPI_EXPERIMENTAL) || \ + (defined(NAPI_EXPERIMENTAL) && \ + (defined(NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT) || \ + defined(NODE_API_EXPERIMENTAL_BASIC_ENV_OPT_OUT))) +typedef struct napi_env__* node_api_nogc_env; +#else +typedef const struct napi_env__* node_api_nogc_env; +#endif +typedef node_api_nogc_env node_api_basic_env; +typedef struct napi_value__* napi_value; +typedef struct napi_ref__* napi_ref; +typedef struct napi_handle_scope__* napi_handle_scope; +typedef struct napi_escapable_handle_scope__* napi_escapable_handle_scope; +typedef struct napi_callback_info__* napi_callback_info; +typedef struct napi_deferred__* napi_deferred; -typedef enum -{ +typedef enum { napi_default = 0, napi_writable = 1 << 0, napi_enumerable = 1 << 1, napi_configurable = 1 << 2, - + // Used with napi_define_class to distinguish static properties // from instance properties. Ignored by napi_define_properties. napi_static = 1 << 10, - + +#if NAPI_VERSION >= 8 // Default for class methods. napi_default_method = napi_writable | napi_configurable, - + // Default for object properties, like in JS obj[prop]. napi_default_jsproperty = napi_writable | napi_enumerable | napi_configurable, +#endif // NAPI_VERSION >= 8 } napi_property_attributes; -typedef napi_value (*napi_callback)(napi_env env, napi_callback_info callbackInfo); - -typedef void (*napi_finalize)(napi_env env, void *finalizeData, void *finalizeHint); - -typedef struct { - // One of utf8name or name should be NULL. - const char* utf8name; - napi_value name; - - napi_callback method; - napi_callback getter; - napi_callback setter; - napi_value value; - - napi_property_attributes attributes; - void* data; -} napi_property_descriptor; - -typedef enum -{ +typedef enum { + // ES6 types (corresponds to typeof) napi_undefined, napi_null, napi_boolean, @@ -85,6 +121,22 @@ typedef enum napi_bigint, } napi_valuetype; +typedef enum { + napi_int8_array, + napi_uint8_array, + napi_uint8_clamped_array, + napi_int16_array, + napi_uint16_array, + napi_int32_array, + napi_uint32_array, + napi_float32_array, + napi_float64_array, + napi_bigint64_array, + napi_biguint64_array, +#define NODE_API_HAS_FLOAT16_ARRAY + napi_float16_array, +} napi_typedarray_type; + typedef enum { napi_ok, napi_invalid_arg, @@ -107,60 +159,140 @@ typedef enum { napi_date_expected, napi_arraybuffer_expected, napi_detachable_arraybuffer_expected, - napi_would_deadlock, /* unused */ + napi_would_deadlock, // unused napi_no_external_buffers_allowed, napi_cannot_run_js, - // Custom errors - napi_handle_scope_empty, - napi_memory_error, - napi_promise_exception } napi_status; +// Note: when adding a new enum value to `napi_status`, please also update +// * `const int last_status` in the definition of `napi_get_last_error_info()' +// in file js_native_api_v8.cc. +// * `const char* error_messages[]` in file js_native_api_v8.cc with a brief +// message explaining the error. +// * the definition of `napi_status` in doc/api/n-api.md to reflect the newly +// added value(s). -typedef enum { - napi_int8_array, - napi_uint8_array, - napi_uint8_clamped_array, - napi_int16_array, - napi_uint16_array, - napi_int32_array, - napi_uint32_array, - napi_float32_array, - napi_float64_array, - napi_bigint64_array, - napi_biguint64_array, -} napi_typedarray_type; +typedef napi_value(NAPI_CDECL* napi_callback)(napi_env env, + napi_callback_info info); +typedef void(NAPI_CDECL* napi_finalize)(napi_env env, + void* finalize_data, + void* finalize_hint); + +#if !defined(NAPI_EXPERIMENTAL) || \ + (defined(NAPI_EXPERIMENTAL) && \ + (defined(NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT) || \ + defined(NODE_API_EXPERIMENTAL_BASIC_ENV_OPT_OUT))) +typedef napi_finalize node_api_nogc_finalize; +#else +typedef void(NAPI_CDECL* node_api_nogc_finalize)(node_api_nogc_env env, + void* finalize_data, + void* finalize_hint); +#endif +typedef node_api_nogc_finalize node_api_basic_finalize; + +// A finalizer that can be called from any thread and at any time. +typedef void(NAPI_CDECL* node_api_noenv_finalize)(void* finalize_data, + void* finalize_hint); + +typedef struct { + // One of utf8name or name should be NULL. + const char* utf8name; + napi_value name; + + napi_callback method; + napi_callback getter; + napi_callback setter; + napi_value value; + + napi_property_attributes attributes; + void* data; +} napi_property_descriptor; + +typedef struct { + const char* error_message; + void* engine_reserved; + uint32_t engine_error_code; + napi_status error_code; +} napi_extended_error_info; +#if NAPI_VERSION >= 6 typedef enum { - napi_key_include_prototypes, - napi_key_own_only + napi_key_include_prototypes, + napi_key_own_only } napi_key_collection_mode; typedef enum { - napi_key_keep_numbers, - napi_key_numbers_to_strings -} napi_key_conversion; + napi_key_all_properties = 0, + napi_key_writable = 1, + napi_key_enumerable = 1 << 1, + napi_key_configurable = 1 << 2, + napi_key_skip_strings = 1 << 3, + napi_key_skip_symbols = 1 << 4 +} napi_key_filter; typedef enum { - napi_key_all_properties = 0, - napi_key_writable = 1, - napi_key_enumerable = 1 << 1, - napi_key_configurable = 1 << 2, - napi_key_skip_strings = 1 << 3, - napi_key_skip_symbols = 1 << 4 -} napi_key_filter; + napi_key_keep_numbers, + napi_key_numbers_to_strings +} napi_key_conversion; +#endif // NAPI_VERSION >= 6 +#if NAPI_VERSION >= 8 typedef struct { - uint64_t lower; - uint64_t upper; + uint64_t lower; + uint64_t upper; } napi_type_tag; +#endif // NAPI_VERSION >= 8 + + + +#ifdef USE_HOST_OBJECT +// Native handlers for a host object. The host object is a transparent proxy: +// every property operation is dispatched to these callbacks. Each receives the +// host object itself as `host_object` and the `data` pointer given to +// napi_create_host_object. `property` is the key as a napi_value (a number for +// indexed access, a string or symbol otherwise). +// +// `get` and `set` are required; `has`, `delete_property` and `own_keys` are +// optional (NULL means the operation is not intercepted / reports absent). +typedef napi_value(NAPI_CDECL* napi_host_object_get_cb)(napi_env env, + napi_value host_object, + napi_value property, + void* data); +typedef void(NAPI_CDECL* napi_host_object_set_cb)(napi_env env, + napi_value host_object, + napi_value property, + napi_value value, + void* data); +typedef int (NAPI_CDECL* napi_host_object_has_cb)(napi_env env, + napi_value host_object, + napi_value property, + void* data); +typedef int (NAPI_CDECL* napi_host_object_delete_cb)(napi_env env, + napi_value host_object, + napi_value property, + void* data); +typedef napi_value(NAPI_CDECL* napi_host_object_own_keys_cb)( + napi_env env, napi_value host_object, void* data); + +// Optional fast paths for integer-indexed access. +typedef napi_value(NAPI_CDECL* napi_host_object_indexed_get_cb)( + napi_env env, napi_value host_object, uint32_t index, void* data); +typedef void(NAPI_CDECL* napi_host_object_indexed_set_cb)( + napi_env env, + napi_value host_object, + uint32_t index, + napi_value value, + void* data); typedef struct { - const char* error_message; - void* engine_reserved; - uint32_t engine_error_code; - napi_status error_code; -} napi_extended_error_info; + napi_host_object_get_cb get; + napi_host_object_set_cb set; + napi_host_object_has_cb has; + napi_host_object_delete_cb delete_property; + napi_host_object_own_keys_cb own_keys; + napi_host_object_indexed_get_cb indexed_get; + napi_host_object_indexed_set_cb indexed_set; +} napi_host_object_methods; +#endif -EXTERN_C_END -#endif // SRC_JS_NATIVE_API_TYPES_H_ +#endif // SRC_JS_NATIVE_API_TYPES_H_ diff --git a/test-app/runtime/src/main/cpp/napi/common/jsr_common.h b/test-app/runtime/src/main/cpp/napi/common/jsr_common.h index 76dbb466..5d635142 100644 --- a/test-app/runtime/src/main/cpp/napi/common/jsr_common.h +++ b/test-app/runtime/src/main/cpp/napi/common/jsr_common.h @@ -7,13 +7,15 @@ #include "js_native_api.h" -napi_status js_create_runtime(napi_runtime* runtime); -napi_status js_create_napi_env(napi_env* env, napi_runtime runtime); +typedef struct jsr_ns_runtime__ *jsr_ns_runtime; + +napi_status js_create_runtime(jsr_ns_runtime* runtime); +napi_status js_create_napi_env(napi_env* env, jsr_ns_runtime runtime); napi_status js_set_runtime_flags(const char* flags); napi_status js_lock_env(napi_env env); napi_status js_unlock_env(napi_env env); napi_status js_free_napi_env(napi_env env); -napi_status js_free_runtime(napi_runtime runtime); +napi_status js_free_runtime(jsr_ns_runtime runtime); napi_status js_execute_script(napi_env env, napi_value script, const char *file, diff --git a/test-app/runtime/src/main/cpp/napi/common/native_api_util.h b/test-app/runtime/src/main/cpp/napi/common/native_api_util.h index 40121280..b4ac3e1d 100644 --- a/test-app/runtime/src/main/cpp/napi/common/native_api_util.h +++ b/test-app/runtime/src/main/cpp/napi/common/native_api_util.h @@ -41,6 +41,36 @@ } \ } +// Faster varargs prologue for hot callbacks. Reads arguments into a fixed stack +// buffer with a SINGLE napi_get_cb_info call (no heap allocation, no redundant +// argc-probe call), falling back to a heap vector only when the real arity +// exceeds the inline capacity `stackn`. Exposes `napi_value *argv` + `size_t +// argc`, so call sites use `argv`/`argv[i]` (a pointer) instead of a vector. +#define NAPI_CALLBACK_BEGIN_VARGS_FAST(stackn) \ + napi_status status; \ + size_t argc = (stackn); \ + void *data; \ + napi_value jsThis; \ + napi_value __argv_stack[(stackn)]; \ + NAPI_GUARD(napi_get_cb_info(env, info, &argc, __argv_stack, &jsThis, &data)) \ + { \ + NAPI_THROW_LAST_ERROR \ + return NULL; \ + } \ + std::vector __argv_heap; \ + napi_value *argv = __argv_stack; \ + if (argc > (stackn)) \ + { \ + __argv_heap.resize(argc); \ + NAPI_GUARD( \ + napi_get_cb_info(env, info, &argc, __argv_heap.data(), nullptr, nullptr)) \ + { \ + NAPI_THROW_LAST_ERROR \ + return NULL; \ + } \ + argv = __argv_heap.data(); \ + } + #define NAPI_ERROR_INFO \ const napi_extended_error_info *error_info = \ (napi_extended_error_info *)malloc(sizeof(napi_extended_error_info)); \ diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/AsyncDebuggerAPI.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/AsyncDebuggerAPI.h index ea718dd4..7dcb79cb 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/AsyncDebuggerAPI.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/AsyncDebuggerAPI.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_ASYNCDEBUGGERAPI_H -#define HERMES_ASYNCDEBUGGERAPI_H +#pragma once #ifdef HERMES_ENABLE_DEBUGGER @@ -68,8 +67,6 @@ using DebuggerEventCallback = std::function; -using DebuggerEventCallbackID = uint32_t; -constexpr const uint32_t kInvalidDebuggerEventCallbackID = 0; using InterruptCallback = std::function; using EvalCompleteCallback = std::function< void(HermesRuntime &runtime, const debugger::EvalResult &result)>; @@ -82,36 +79,34 @@ using EvalCompleteCallback = std::function< /// functions that are safe to call on any thread. All other functions must be /// called on the runtime thread. class HERMES_EXPORT AsyncDebuggerAPI : private debugger::EventObserver { - /// Hide the constructor so users can only construct via static create - /// methods. - AsyncDebuggerAPI(HermesRuntime &runtime); - public: - /// Creates an AsyncDebuggerAPI for use with the provided HermesRuntime. This - /// should be called and created at the same time as creating HermesRuntime. - static std::unique_ptr create(HermesRuntime &runtime); + /// Constructs an AsyncDebuggerAPI for use with the provided HermesRuntime. + /// This should be called and created at the same time as creating + /// HermesRuntime. + explicit AsyncDebuggerAPI(HermesRuntime &runtime); /// Must be destroyed on the runtime thread or when you're sure nothing is /// interacting with the runtime. Must be destroyed before destroying /// HermesRuntime. ~AsyncDebuggerAPI() override; - /// Add a callback function to invoke when the runtime pauses due to various + /// Set a callback function to invoke when the runtime pauses due to various /// conditions such as hitting a "debugger;" statement. Can be called from any - /// thread. If there are no DebuggerEventCallback, then any reason that might + /// thread. If there is no DebuggerEventCallback, then any reason that might /// trigger a pause, such as a "debugger;" statement or breakpoints, will not - /// actually pause and will simply continue execution. Any caller that adds an + /// actually pause and will simply continue execution. Any caller that sets an /// event callback cannot just be observing events and never call /// \p resumeFromPaused in any of its code paths. The caller must either /// expose UI enabling human action for controlling the debugger, or it must /// have programmatic logic that controls the debugger via /// \p resumeFromPaused. - DebuggerEventCallbackID addDebuggerEventCallback_TS( - DebuggerEventCallback callback); + /// + /// The provided callback must be non-empty. Use \p + /// clearDebuggerEventCallback_TS to clear the callback. + void setDebuggerEventCallback_TS(DebuggerEventCallback callback); - /// Remove a previously added callback function. If there is no callback - /// registered using the provided \p id, the function does nothing. - void removeDebuggerEventCallback_TS(DebuggerEventCallbackID id); + /// Clear the debugger event callback. Can be called from any thread. + void clearDebuggerEventCallback_TS(); /// Whether the runtime is currently paused waiting for the next action. /// Should only be called from the runtime thread. @@ -120,7 +115,7 @@ class HERMES_EXPORT AsyncDebuggerAPI : private debugger::EventObserver { /// Whether the runtime is currently paused for any reason (e.g. script /// parsed, running interrupts, or waiting for a command). /// Should only be called from the runtime thread. - bool isPaused(); + bool isPaused() const; /// Provide the next action to perform. Should only be called from the runtime /// thread and only if the next command is expected to be set. @@ -145,11 +140,6 @@ class HERMES_EXPORT AsyncDebuggerAPI : private debugger::EventObserver { debugger::Command didPause(debugger::Debugger &debugger) override; private: - struct EventCallbackEntry { - DebuggerEventCallbackID id; - DebuggerEventCallback callback; - }; - /// This function infinite loops and uses \p signal_ to block the runtime /// thread. It gets woken up if new InterruptCallback is queued or if /// DebuggerEventCallback changes. @@ -163,11 +153,8 @@ class HERMES_EXPORT AsyncDebuggerAPI : private debugger::EventObserver { /// to run all interrupts, but will stop if any interrupt sets a next command. void runInterrupts(bool ignoreNextCommand = true); - /// Returns the next DebuggerEventCallback to execute if any. - std::optional takeNextEventCallback(); - - /// Runs every DebuggerEventCallback that has been registered. - void runEventCallbacks(DebuggerEventType event); + /// Runs the DebuggerEventCallback that has been registered (if any). + void runEventCallback(DebuggerEventType event); HermesRuntime &runtime_; @@ -186,19 +173,8 @@ class HERMES_EXPORT AsyncDebuggerAPI : private debugger::EventObserver { /// calls to didPause. bool inDidPause_ = false; - /// Next ID to use when adding a DebuggerEventCallback. - uint32_t nextEventCallbackID_ TSA_GUARDED_BY(mutex_); - - /// Callback functions to invoke to notify events in \p didPause. Using - /// std::list which requires O(N) search when removing an element, but removal - /// should be a rare event. So the choice of using std::list is to optimize - /// for typical usage. - std::list eventCallbacks_ TSA_GUARDED_BY(mutex_){}; - - /// Iterator for eventCallbacks_. Used to traverse through the list when - /// running the callbacks. - std::list::iterator eventCallbackIterator_ - TSA_GUARDED_BY(mutex_); + /// The debugger event callback to invoke when the runtime pauses. + DebuggerEventCallback eventCallback_ TSA_GUARDED_BY(mutex_){}; /// Queue of interrupt callback functions to invoke. std::queue interruptCallbacks_ TSA_GUARDED_BY(mutex_){}; @@ -257,32 +233,25 @@ using DebuggerEventCallback = std::function; -using DebuggerEventCallbackID = uint32_t; -constexpr const uint32_t kInvalidDebuggerEventCallbackID = 0; using InterruptCallback = std::function; using EvalCompleteCallback = std::function< void(HermesRuntime &runtime, const debugger::EvalResult &result)>; class HERMES_EXPORT AsyncDebuggerAPI { public: - static std::unique_ptr create(HermesRuntime &runtime) { - return nullptr; - } + explicit AsyncDebuggerAPI(HermesRuntime &) {} ~AsyncDebuggerAPI() {} - DebuggerEventCallbackID addDebuggerEventCallback_TS( - DebuggerEventCallback callback) { - return kInvalidDebuggerEventCallbackID; - } + void setDebuggerEventCallback_TS(DebuggerEventCallback callback) {} - void removeDebuggerEventCallback_TS(DebuggerEventCallbackID id) {} + void clearDebuggerEventCallback_TS() {} bool isWaitingForCommand() { return false; } - bool isPaused() { + bool isPaused() const { return false; } @@ -305,5 +274,3 @@ class HERMES_EXPORT AsyncDebuggerAPI { } // namespace facebook #endif // !HERMES_ENABLE_DEBUGGER - -#endif // HERMES_ASYNCDEBUGGERAPI_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/CompileJS.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/CompileJS.h index 562eeae7..46c7451e 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/CompileJS.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/CompileJS.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_COMPILEJS_H -#define HERMES_COMPILEJS_H +#pragma once #include #include @@ -68,6 +67,31 @@ bool compileJS( std::string &bytecode, bool optimize = true); -} // namespace hermes +/// Options for overload of compileJS that accepts CompileJSOptions. +struct CompileJSOptions { + /// If true, the bytecode will be optimized. + bool optimize{true}; + /// Maximum number of instructions (in addition to parameter handling) + /// that is allowed for inlining of small functions. + unsigned inlineMaxSize{50}; + /// If true, the bytecode will be interruptable. + bool emitAsyncBreakCheck{false}; + /// If true, debugging information will be generated in the bytecode. + bool debug{false}; + /// Enable ES6 block scoping support. + bool enableES6BlockScoping{false}; + /// Enable async generators support. + bool enableAsyncGenerators{false}; +}; -#endif +/// Like the other compileJS overloads, but takes a struct of options with some +/// additional configurability. +bool compileJS( + const std::string &str, + const std::string &sourceURL, + std::string &bytecode, + const CompileJSOptions &options, + DiagnosticHandler *diagHandler, + std::optional sourceMapBuf = std::nullopt); + +} // namespace hermes diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/DebuggerAPI.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/DebuggerAPI.h index e444c41c..fe11b0cf 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/DebuggerAPI.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/DebuggerAPI.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_DEBUGGERAPI_H -#define HERMES_DEBUGGERAPI_H +#pragma once #ifdef HERMES_ENABLE_DEBUGGER @@ -31,6 +30,9 @@ class HermesValue; namespace facebook { namespace hermes { class HermesRuntime; +// Forward declaration of the internal Root API class, which is marked as a +// friend of the Debugger. +class HermesRootAPI; namespace debugger { @@ -269,6 +271,7 @@ class HERMES_EXPORT Debugger { ::facebook::jsi::Value getThrownValue(); private: + friend HermesRootAPI; friend std::unique_ptr hermes::makeHermesRuntime( const ::hermes::vm::RuntimeConfig &); friend std::unique_ptr @@ -497,5 +500,3 @@ class EventObserver { } // namespace facebook #endif // !HERMES_ENABLE_DEBUGGER - -#endif // HERMES_DEBUGGERAPI_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/MurmurHash.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/MurmurHash.h deleted file mode 100644 index 3d2e53ee..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/MurmurHash.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -#pragma once - -#include -#include - -// Computes the hash of key using MurmurHash3 algorithm, the value is planced in the "hash" output parameter -// The function returns whether or not key is comprised of only ASCII characters (<=127) -bool murmurhash(const uint8_t *key, size_t length, uint64_t &hash); \ No newline at end of file diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/Buffer.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/Buffer.h deleted file mode 100644 index 3a4e8c26..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/Buffer.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_PUBLIC_BUFFER_H -#define HERMES_PUBLIC_BUFFER_H - -#include - -#include -#include - -namespace hermes { - -/// A generic buffer interface. E.g. for memmapped bytecode. -class HERMES_EXPORT Buffer { - public: - Buffer() : data_(nullptr), size_(0) {} - - Buffer(const uint8_t *data, size_t size) : data_(data), size_(size) {} - - virtual ~Buffer(); - - const uint8_t *data() const { - return data_; - }; - - size_t size() const { - return size_; - } - - protected: - const uint8_t *data_ = nullptr; - size_t size_ = 0; -}; - -} // namespace hermes - -#endif diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/CtorConfig.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/CtorConfig.h index aff3f398..ba213ee0 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/CtorConfig.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/CtorConfig.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_PUBLIC_CTORCONFIG_H -#define HERMES_PUBLIC_CTORCONFIG_H +#pragma once #include @@ -128,11 +127,11 @@ return TypeAsSingleToken{__VA_ARGS__}; \ } -#define _HERMES_CTORCONFIG_SETTER(CX, TYPE, NAME, ...) \ - inline auto with##NAME(TYPE NAME)->decltype(*this) { \ - config_.NAME##_ = std::move(NAME); \ - NAME##Explicit_ = true; \ - return *this; \ +#define _HERMES_CTORCONFIG_SETTER(CX, TYPE, NAME, ...) \ + inline auto with##NAME(TYPE NAME) -> decltype(*this) { \ + config_.NAME##_ = std::move(NAME); \ + NAME##Explicit_ = true; \ + return *this; \ } #define _HERMES_CTORCONFIG_BUILDER_GETTER(CX, TYPE, NAME, ...) \ @@ -144,5 +143,3 @@ if (newConfig.has##NAME()) { \ with##NAME(newConfig.config_.get##NAME()); \ } - -#endif // HERMES_PUBLIC_CTORCONFIG_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/DebuggerTypes.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/DebuggerTypes.h index 88184c07..a549e81d 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/DebuggerTypes.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/DebuggerTypes.h @@ -5,17 +5,12 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_PUBLIC_DEBUGGERTYPES_H -#define HERMES_PUBLIC_DEBUGGERTYPES_H +#pragma once #include #include #include -#pragma GCC diagnostic push -#ifdef HERMES_COMPILER_SUPPORTS_WSHORTEN_64_TO_32 -#pragma GCC diagnostic ignored "-Wshorten-64-to-32" -#endif namespace hermes { namespace vm { class Debugger; @@ -88,7 +83,7 @@ struct StackTrace { private: explicit StackTrace(std::vector frames) - : frames_(std::move(frames)){}; + : frames_(std::move(frames)) {}; friend ProgramState; friend ::hermes::vm::Debugger; std::vector frames_; @@ -196,5 +191,3 @@ struct BreakpointInfo { } // namespace debugger } // namespace hermes } // namespace facebook - -#endif diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/GCConfig.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/GCConfig.h index 8d3f316f..419305af 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/GCConfig.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/GCConfig.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_PUBLIC_GCCONFIG_H -#define HERMES_PUBLIC_GCCONFIG_H +#pragma once #include "hermes/Public/CtorConfig.h" #include "hermes/Public/GCTripwireContext.h" @@ -25,10 +24,9 @@ namespace hermes { namespace vm { /// A type big enough to accomodate the entire allocated address space. -/// Individual allocations are always 'uint32_t', but on a 64-bit machine we -/// might want to accommodate a larger total heap (or not, in which case we keep -/// it 32-bit). -using gcheapsize_t = uint32_t; +/// Individual allocations are always 'uint32_t', but on a 64-bit machine, when +/// compressed pointer is OFF, we want to accommodate a larger total heap. +using gcheapsize_t = size_t; /// Represents a value before and after an event. /// NOTE: Not a std::pair because using the names are more readable than first @@ -144,9 +142,6 @@ enum class GCEventKind { /// Parameters for GC Initialisation. Check documentation in README.md /// constexpr indicates that the default value is constexpr. #define GC_FIELDS(F) \ - /* Minimum heap size hint. */ \ - F(constexpr, gcheapsize_t, MinHeapSize, 0) \ - \ /* Initial heap size hint. */ \ F(constexpr, gcheapsize_t, InitHeapSize, 32 << 20) \ \ @@ -206,19 +201,6 @@ enum class GCEventKind { /* GC_FIELDS END */ _HERMES_CTORCONFIG_STRUCT(GCConfig, GC_FIELDS, { - if (builder.hasMinHeapSize()) { - if (builder.hasInitHeapSize()) { - // If both are specified, normalize the initial size up to the minimum, - // if necessary. - InitHeapSize_ = std::max(MinHeapSize_, InitHeapSize_); - } else { - // If the minimum is set explicitly, but the initial heap size is not, - // use the minimum as the initial size. - InitHeapSize_ = MinHeapSize_; - } - } - assert(InitHeapSize_ >= MinHeapSize_); - // Make sure the max is at least the Init. MaxHeapSize_ = std::max(InitHeapSize_, MaxHeapSize_); }) @@ -227,5 +209,3 @@ _HERMES_CTORCONFIG_STRUCT(GCConfig, GC_FIELDS, { } // namespace vm } // namespace hermes - -#endif // HERMES_PUBLIC_GCCONFIG_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/GCTripwireContext.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/GCTripwireContext.h index 4a8f500f..e7a614fc 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/GCTripwireContext.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/GCTripwireContext.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_PUBLIC_GCTRIPWIRECONTEXT_H -#define HERMES_PUBLIC_GCTRIPWIRECONTEXT_H +#pragma once #include @@ -39,5 +38,3 @@ class HERMES_EXPORT GCTripwireContext { } // namespace vm } // namespace hermes - -#endif // HERMES_PUBLIC_GCTRIPWIRECONTEXT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/JSOutOfMemoryError.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/JSOutOfMemoryError.h index 95093ab7..38f18a10 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/JSOutOfMemoryError.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/JSOutOfMemoryError.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_PUBLIC_JSOUTOFMEMORYERROR_H -#define HERMES_PUBLIC_JSOUTOFMEMORYERROR_H +#pragma once #include @@ -26,5 +25,3 @@ class HERMES_EXPORT JSOutOfMemoryError : public std::runtime_error { } // namespace vm } // namespace hermes - -#endif // HERMES_PUBLIC_JSOUTOFMEMORYERROR_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/RuntimeConfig.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/RuntimeConfig.h index 858f1f50..faa1b7e1 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/RuntimeConfig.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/RuntimeConfig.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_PUBLIC_RUNTIMECONFIG_H -#define HERMES_PUBLIC_RUNTIMECONFIG_H +#pragma once #include "hermes/Public/CrashManager.h" #include "hermes/Public/CtorConfig.h" @@ -48,6 +47,9 @@ class PinnedHermesValue; /* Native stack remaining before assuming overflow */ \ F(constexpr, unsigned, NativeStackGap, 64 * 1024) \ \ + /* Whether or not the JIT is enabled */ \ + F(constexpr, bool, EnableJIT, false) \ + \ /* Whether to allow eval and Function ctor */ \ F(constexpr, bool, EnableEval, true) \ \ @@ -60,23 +62,20 @@ class PinnedHermesValue; /* Whether to emit async break check instructions in eval code */ \ F(constexpr, bool, AsyncBreakCheckInEval, true) \ \ - /* Support for ES6 Promise. */ \ - F(constexpr, bool, ES6Promise, true) \ - \ /* Support for ES6 Proxy. */ \ F(constexpr, bool, ES6Proxy, true) \ \ - /* Support for ES6 Class. */ \ - F(constexpr, bool, ES6Class, false) \ + /* Support for ES6 block scoping. */ \ + F(constexpr, bool, ES6BlockScoping, false) \ + \ + /* Support for async generators in eval. */ \ + F(constexpr, bool, EnableAsyncGenerators, false) \ \ /* Support for ECMA-402 Intl APIs. */ \ F(constexpr, bool, Intl, true) \ \ - /* Support for ArrayBuffer, DataView and typed arrays. */ \ - F(constexpr, bool, ArrayBuffer, true) \ - \ /* Support for using microtasks. */ \ - F(constexpr, bool, MicrotaskQueue, false) \ + F(constexpr, bool, MicrotaskQueue, true) \ \ /* Runtime set up for synth trace. */ \ F(constexpr, SynthTraceMode, SynthTraceMode, SynthTraceMode::None) \ @@ -121,8 +120,17 @@ class PinnedHermesValue; /* The flags passed from a VM experiment */ \ F(constexpr, uint32_t, VMExperimentFlags, 0) \ \ - /* Whether or not block scoping is enabled */ \ - F(constexpr, bool, EnableBlockScoping, false) \ + /* Force JIT compilation on all functions. */ \ + F(constexpr, bool, ForceJIT, false) \ + \ + /* JIT compilation threshold (number of calls before JIT'ing). */ \ + F(constexpr, uint32_t, JITThreshold, 1 << 5) \ + \ + /* JIT memory limit, after which no more code will be JIT'ed. */ \ + F(constexpr, uint32_t, JITMemoryLimit, 32u << 20) \ + \ + /* Increase compliance with test262 (stricter checks at runtime). */ \ + F(constexpr, bool, Test262, false) \ /* RUNTIME_FIELDS END */ _HERMES_CTORCONFIG_STRUCT(RuntimeConfig, RUNTIME_FIELDS, {}) @@ -131,5 +139,3 @@ _HERMES_CTORCONFIG_STRUCT(RuntimeConfig, RUNTIME_FIELDS, {}) } // namespace vm } // namespace hermes - -#endif // HERMES_PUBLIC_RUNTIMECONFIG_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/SamplingProfiler.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/SamplingProfiler.h similarity index 98% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/SamplingProfiler.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/SamplingProfiler.h index 0d8583ed..5c2a3a71 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/SamplingProfiler.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/Public/SamplingProfiler.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_PUBLIC_SAMPLINGPROFILER_H -#define HERMES_PUBLIC_SAMPLINGPROFILER_H +#pragma once #include @@ -269,5 +268,3 @@ class HERMES_EXPORT Profile { } // namespace sampling_profiler } // namespace hermes } // namespace facebook - -#endif diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/RuntimeTaskRunner.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/RuntimeTaskRunner.h index 367b267a..dd1cd98a 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/RuntimeTaskRunner.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/RuntimeTaskRunner.h @@ -5,10 +5,9 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_RUNTIMETASKRUNNER_H -#define HERMES_RUNTIMETASKRUNNER_H +#pragma once -#include "AsyncDebuggerAPI.h" +#include namespace facebook { namespace hermes { @@ -63,5 +62,3 @@ class RuntimeTaskRunner } // namespace debugger } // namespace hermes } // namespace facebook - -#endif // HERMES_RUNTIMETASKRUNNER_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/ScriptStore.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/ScriptStore.h deleted file mode 100644 index e7365cc5..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/ScriptStore.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -#pragma once - -#include -#include - -namespace facebook { -namespace jsi { - -// Integer type as it's persist friendly. -using ScriptVersion_t = uint64_t; // It should be std::optional once we have c++17 available everywhere. Until - // then, 0 implies versioning not available. -using JSRuntimeVersion_t = uint64_t; // 0 implies version can't be computed. We assert whenever that happens. - -struct VersionedBuffer { - std::shared_ptr buffer; - ScriptVersion_t version; -}; - -struct ScriptSignature { - std::string url; - ScriptVersion_t version; -}; - -struct JSRuntimeSignature { - std::string runtimeName; // e.g. Chakra, V8 - JSRuntimeVersion_t version; -}; - -// Most JSI::Runtime implementation offer some form of prepared JavaScript which offers better performance -// characteristics when loading comparing to plain JavaScript. Embedders can provide an instance of this interface -// (through JSI::Runtime implementation's factory method), to enable persistance of the prepared script and retrieval on -// subsequent evaluation of a script. -struct PreparedScriptStore { - virtual ~PreparedScriptStore() = default; - - // Try to retrieve the prepared javascript for a given combination of script & runtime. - // scriptSignature : Javascript url and version - // RuntimeSignature : Javascript engine type and version - // prepareTag : Custom tag to uniquely identify JS engine specific preparation schemes. It is usually useful while - // experimentation and can be null. It is possible that no prepared script is available for a given script & runtime - // signature. This method should null if so - virtual std::shared_ptr tryGetPreparedScript( - const ScriptSignature &scriptSignature, - const JSRuntimeSignature &runtimeSignature, - const char *prepareTag // Optional tag. For e.g. eagerly evaluated vs lazy cache. - ) noexcept = 0; - - // Persist the prepared javascript for a given combination of script & runtime. - // scriptSignature : Javascript url and version - // RuntimeSignature : Javascript engine type and version - // prepareTag : Custom tag to uniquely identify JS engine specific preparation schemes. It is usually useful while - // experimentation and can be null. It is possible that no prepared script is available for a given script & runtime - // signature. This method should null if so Any failure in persistance should be identified during the subsequent - // retrieval through the integrity mechanism which must be put into the storage. - virtual void persistPreparedScript( - std::shared_ptr preparedScript, - const ScriptSignature &scriptMetadata, - const JSRuntimeSignature &runtimeMetadata, - const char *prepareTag // Optional tag. For e.g. eagerly evaluated vs lazy cache. - ) noexcept = 0; -}; - -// JSI::Runtime implementation must be provided an instance on this interface to enable version sensitive capabilities -// such as usage of pre-prepared javascript script. Alternatively, this entity can be used to directly provide the -// Javascript buffer and rich metadata to the JSI::Runtime instance. -struct ScriptStore { - virtual ~ScriptStore() = default; - - // Return the Javascript buffer and version corresponding to a given url. - virtual VersionedBuffer getVersionedScript(const std::string &url) noexcept = 0; - - // Return the version of the Javascript buffer corresponding to a given url. - virtual ScriptVersion_t getScriptVersion(const std::string &url) noexcept = 0; -}; - -} // namespace jsi -} // namespace facebook \ No newline at end of file diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/SynthTrace.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/SynthTrace.h index f8d174c8..857445a9 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/SynthTrace.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/SynthTrace.h @@ -5,15 +5,16 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_SYNTHTRACE_H -#define HERMES_SYNTHTRACE_H +#pragma once +#include "hermes/ADT/StringSetVector.h" #include "hermes/Public/RuntimeConfig.h" #include "hermes/Support/JSONEmitter.h" #include "hermes/Support/SHA1.h" -#include "hermes/Support/StringSetVector.h" #include "hermes/VM/GCExecTrace.h" +#include "jsi/jsi.h" + #include #include #include @@ -171,43 +172,71 @@ class SynthTrace { } val_; }; + /// Represents the encoding type of a String or PropNameId + enum class StringEncodingType { ASCII, UTF8, UTF16 }; + + /// Represents the type of JavaScript Error being created. + enum class JSErrorType { + Error, + EvalError, + RangeError, + ReferenceError, + SyntaxError, + TypeError, + URIError, + }; + /// A TimePoint is a time when some event occurred. using TimePoint = std::chrono::steady_clock::time_point; using TimeSinceStart = std::chrono::milliseconds; -#define SYNTH_TRACE_RECORD_TYPES(RECORD) \ - RECORD(BeginExecJS) \ - RECORD(EndExecJS) \ - RECORD(Marker) \ - RECORD(CreateObject) \ - RECORD(CreateString) \ - RECORD(CreatePropNameID) \ - RECORD(CreateHostObject) \ - RECORD(CreateHostFunction) \ - RECORD(QueueMicrotask) \ - RECORD(DrainMicrotasks) \ - RECORD(GetProperty) \ - RECORD(SetProperty) \ - RECORD(HasProperty) \ - RECORD(GetPropertyNames) \ - RECORD(CreateArray) \ - RECORD(ArrayRead) \ - RECORD(ArrayWrite) \ - RECORD(CallFromNative) \ - RECORD(ConstructFromNative) \ - RECORD(ReturnFromNative) \ - RECORD(ReturnToNative) \ - RECORD(CallToNative) \ - RECORD(GetPropertyNative) \ - RECORD(GetPropertyNativeReturn) \ - RECORD(SetPropertyNative) \ - RECORD(SetPropertyNativeReturn) \ - RECORD(GetNativePropertyNames) \ - RECORD(GetNativePropertyNamesReturn) \ - RECORD(CreateBigInt) \ - RECORD(BigIntToString) \ - RECORD(SetExternalMemoryPressure) \ - RECORD(Utf8) \ +#define SYNTH_TRACE_RECORD_TYPES(RECORD) \ + RECORD(BeginExecJS) \ + RECORD(EndExecJS) \ + RECORD(Marker) \ + RECORD(CreateObject) \ + RECORD(CreateObjectWithPrototype) \ + RECORD(CreateString) \ + RECORD(CreatePropNameID) \ + RECORD(CreatePropNameIDWithValue) \ + RECORD(CreateHostObject) \ + RECORD(CreateHostFunction) \ + RECORD(QueueMicrotask) \ + RECORD(DrainMicrotasks) \ + RECORD(GetProperty) \ + RECORD(SetProperty) \ + RECORD(HasProperty) \ + RECORD(GetPropertyNames) \ + RECORD(CreateArray) \ + RECORD(ArrayRead) \ + RECORD(ArrayWrite) \ + RECORD(ArrayPush) \ + RECORD(CallFromNative) \ + RECORD(ConstructFromNative) \ + RECORD(ReturnFromNative) \ + RECORD(ReturnToNative) \ + RECORD(CallToNative) \ + RECORD(GetPropertyNative) \ + RECORD(GetPropertyNativeReturn) \ + RECORD(SetPropertyNative) \ + RECORD(SetPropertyNativeReturn) \ + RECORD(GetNativePropertyNames) \ + RECORD(GetNativePropertyNamesReturn) \ + RECORD(CreateBigInt) \ + RECORD(BigIntToString) \ + RECORD(SetExternalMemoryPressure) \ + RECORD(Utf8) \ + RECORD(Utf16) \ + RECORD(GetStringData) \ + RECORD(GetPrototype) \ + RECORD(SetPrototype) \ + RECORD(DeleteProperty) \ + RECORD(Serialize) \ + RECORD(Deserialize) \ + RECORD(CreateUInt8Array) \ + RECORD(CreateUInt8ArrayFromArrayBuffer) \ + RECORD(GetBufferFromTypedArray) \ + RECORD(CreateJSError) \ RECORD(Global) /// RecordType is a tag used to differentiate which type of record it is. @@ -279,8 +308,12 @@ class SynthTrace { template void emplace_back(Args &&...args) { - records_.emplace_back(new T(std::forward(args)...)); - flushRecordsIfNecessary(); + if (json_) { + T record(std::forward(args)...); + record.toJSON(*json_); + } else { + records_.emplace_back(new T(std::forward(args)...)); + } } const std::vector> &records() const { @@ -315,9 +348,17 @@ class SynthTrace { /// Decodes a string into a trace value. static TraceValue decode(const std::string &); +#ifdef HERMESVM_API_TRACE_DEBUG + /// Given a Value, return a descriptive string. This should only be used to + /// provide more debugging info when creating records. + static std::string getDescriptiveString( + jsi::Runtime &runtime, + const jsi::Value &value); +#endif + /// The version of the Synth Benchmark constexpr static uint32_t synthVersion() { - return 4; + return 5; } static const char *nameFromReleaseUnused(::hermes::vm::ReleaseUnused ru); @@ -328,27 +369,14 @@ class SynthTrace { return (*traceStream_); } - /// If we're tracing to a file, and the number of accumulated - /// records has reached the limit kTraceRecordsToFlush, below, - /// flush the records to the file, and reset the accumulated records - /// to be empty. - void flushRecordsIfNecessary(); - - /// Assumes we're tracing to a file; flush accumulated records to - /// the file, and reset the accumulated records to be empty. - void flushRecords(); - - static constexpr unsigned kTraceRecordsToFlush = 100; - /// If we're tracing to a file, pointer to a stream onto /// traceFilename_. Null otherwise. std::unique_ptr traceStream_; /// If we're tracing to a file, pointer to a JSONEmitter writting /// into *traceStream_. Null otherwise. std::unique_ptr<::hermes::JSONEmitter> json_; - /// The records currently being accumulated in the trace. If we are - /// tracing to a file, these will be only the records not yet - /// written to the file. + /// The records accumulated in the trace. Only used when not tracing + /// to a file (i.e., when json_ is null). std::vector> records_; /// The id of the global object. /// Note: Keeping this as optional to support replaying the older trace @@ -557,8 +585,10 @@ class SynthTrace { /// The string that was passed to Runtime::createStringFromAscii() or /// Runtime::createStringFromUtf8() when the string was created. std::string chars_; - /// Whether the string was created from ASCII (true) or UTF8 (false). - bool ascii_; + /// The string that was passed to Runtime::createStringFromUtf16() + std::u16string chars16_; + /// Whether the String was created from ASCII, UTF-8 or UTF-16 + StringEncodingType encodingType_; // General UTF-8. CreateStringRecord( @@ -569,14 +599,27 @@ class SynthTrace { : Record(time), objID_(objID), chars_(reinterpret_cast(chars), length), - ascii_(false) {} + encodingType_(StringEncodingType::UTF8) {} // Ascii. CreateStringRecord( TimeSinceStart time, ObjectID objID, const char *chars, size_t length) - : Record(time), objID_(objID), chars_(chars, length), ascii_(true) {} + : Record(time), + objID_(objID), + chars_(chars, length), + encodingType_(StringEncodingType::ASCII) {} + // UTF-16. + CreateStringRecord( + TimeSinceStart time, + ObjectID objID, + const char16_t *chars, + size_t length) + : Record(time), + objID_(objID), + chars16_(chars, length), + encodingType_(StringEncodingType::UTF16) {} void toJSONInternal(::hermes::JSONEmitter &json) const override; RecordType getType() const override { @@ -596,19 +639,15 @@ class SynthTrace { /// created by the native code. struct CreatePropNameIDRecord : public Record { static constexpr RecordType type{RecordType::CreatePropNameID}; - /// The ObjectID of the PropNameID that was created by - /// Runtime::createPropNameIDFromXxx() functions. + /// The ObjectID of the PropNameID that was created. const ObjectID propNameID_; /// The string that was passed to Runtime::createPropNameIDFromAscii() or /// Runtime::createPropNameIDFromUtf8(). std::string chars_; - /// The String for Symbol that was passed to - /// Runtime::createPropNameIDFromString() or - /// Runtime::createPropNameIDFromSymbol(). - const TraceValue traceValue_{TraceValue::encodeUndefinedValue()}; - /// Whether the PropNameID was created from ASCII, UTF8, jsi::String - /// (TRACEVALUE) or jsi::Symbol (TRACEVALUE). - enum ValueType { ASCII, UTF8, TRACEVALUE } valueType_; + /// The string that was passed to Runtime::createPropNameIDFromUtf16() + std::u16string chars16_; + /// Whether the PropNameID was created from ASCII, UTF-8, or UTF-16 + StringEncodingType encodingType_; // General UTF-8. CreatePropNameIDRecord( @@ -619,7 +658,7 @@ class SynthTrace { : Record(time), propNameID_(propNameID), chars_(reinterpret_cast(chars), length), - valueType_(UTF8) {} + encodingType_(StringEncodingType::UTF8) {} // Ascii. CreatePropNameIDRecord( TimeSinceStart time, @@ -629,16 +668,49 @@ class SynthTrace { : Record(time), propNameID_(propNameID), chars_(chars, length), - valueType_(ASCII) {} - // jsi::String or jsi::Symbol. + encodingType_(StringEncodingType::ASCII) {} + // UTF16 CreatePropNameIDRecord( TimeSinceStart time, ObjectID propNameID, - TraceValue traceValue) + const char16_t *chars, + size_t length) : Record(time), propNameID_(propNameID), - traceValue_(traceValue), - valueType_(TRACEVALUE) {} + chars16_(chars, length), + encodingType_(StringEncodingType::UTF16) {} + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + RecordType getType() const override { + return type; + } + + std::vector defs() const override { + return {propNameID_}; + } + + std::vector uses() const override { + return {}; + } + }; + + /// A CreatePropNameIDWithValueRecord is an event where a jsi::PropNameID is + /// created by the native code from JSI Value + struct CreatePropNameIDWithValueRecord : public Record { + static constexpr RecordType type{RecordType::CreatePropNameIDWithValue}; + /// The ObjectID of the PropNameID that was created. + const ObjectID propNameID_; + /// The String or Symbol that was passed to + /// Runtime::createPropNameIDFromString() or + /// Runtime::createPropNameIDFromSymbol(). + const TraceValue traceValue_; + + // jsi::String or jsi::Symbol. + CreatePropNameIDWithValueRecord( + TimeSinceStart time, + ObjectID propNameID, + TraceValue traceValue) + : Record(time), propNameID_(propNameID), traceValue_(traceValue) {} void toJSONInternal(::hermes::JSONEmitter &json) const override; RecordType getType() const override { @@ -656,6 +728,31 @@ class SynthTrace { } }; + struct CreateObjectWithPrototypeRecord : public Record { + static constexpr RecordType type{RecordType::CreateObjectWithPrototype}; + const ObjectID objID_; + /// The prototype being assigned + const TraceValue prototype_; + + CreateObjectWithPrototypeRecord( + TimeSinceStart time, + ObjectID objID, + TraceValue prototype) + : Record(time), objID_(objID), prototype_(prototype) {} + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + + RecordType getType() const override { + return type; + } + + std::vector uses() const override { + std::vector uses{objID_}; + pushIfTrackedValue(prototype_, uses); + return uses; + } + }; + struct CreateHostObjectRecord final : public CreateObjectRecord { static constexpr RecordType type{RecordType::CreateHostObject}; using CreateObjectRecord::CreateObjectRecord; @@ -741,7 +838,7 @@ class SynthTrace { struct GetPropertyRecord : public Record { /// The ObjectID of the object that was accessed for its property. const ObjectID objID_; - /// String or PropNameID passed to getProperty. + /// String or PropNameID or Value passed to getProperty. const TraceValue propID_; #ifdef HERMESVM_API_TRACE_DEBUG std::string propNameDbg_; @@ -785,7 +882,7 @@ class SynthTrace { struct SetPropertyRecord : public Record { /// The ObjectID of the object that was accessed for its property. const ObjectID objID_; - /// String or PropNameID passed to setProperty. + /// String or PropNameID or Value passed to setProperty. const TraceValue propID_; #ifdef HERMESVM_API_TRACE_DEBUG std::string propNameDbg_; @@ -883,6 +980,71 @@ class SynthTrace { } }; + /// A SetPrototypeRecord is an event where native code sets the prototype of a + /// JS Object + struct SetPrototypeRecord : public Record { + static constexpr RecordType type{RecordType::SetPrototype}; + /// The ObjectID of the object that was accessed for its prototype. + const ObjectID objID_; + /// The custom prototype being assigned + const TraceValue value_; + SetPrototypeRecord(TimeSinceStart time, ObjectID objID, TraceValue value) + : Record(time), objID_(objID), value_(value) {} + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + + RecordType getType() const override { + return type; + } + std::vector uses() const override { + std::vector uses{objID_}; + pushIfTrackedValue(value_, uses); + return uses; + } + }; + + struct DeletePropertyRecord final : public Record { + static constexpr RecordType type{RecordType::DeleteProperty}; + /// The object ID of the object that was accessed for its property + const ObjectID objID_; + /// The name of the property being deleted + const TraceValue propID_; + + DeletePropertyRecord(TimeSinceStart time, ObjectID objID, TraceValue propID) + : Record(time), objID_(objID), propID_(propID) {} + + RecordType getType() const override { + return type; + } + + std::vector uses() const override { + std::vector uses{objID_}; + pushIfTrackedValue(propID_, uses); + return uses; + } + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + }; + + /// A GetPrototypeRecord is an event where native code gets the prototype of a + /// JS Object + struct GetPrototypeRecord : public Record { + static constexpr RecordType type{RecordType::GetPrototype}; + /// The ObjectID of the object that was accessed for its prototype. + const ObjectID objID_; + GetPrototypeRecord(TimeSinceStart time, ObjectID objID) + : Record(time), objID_(objID) {} + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + + RecordType getType() const override { + return type; + } + std::vector uses() const override { + return {objID_}; + } + }; + /// A CreateArrayRecord is an event where a new array is created of a specific /// length. struct CreateArrayRecord final : public Record { @@ -907,6 +1069,128 @@ class SynthTrace { } }; + /// A CreateUInt8ArrayRecord is an event where a new UInt8Array is created + /// with a specific length. + struct CreateUInt8ArrayRecord final : public Record { + static constexpr RecordType type{RecordType::CreateUInt8Array}; + /// The ObjectID of the UInt8Array that was created by createUint8Array(). + const ObjectID objID_; + /// The length of the UInt8Array that was passed to createUint8Array(). + const size_t length_; + + explicit CreateUInt8ArrayRecord( + TimeSinceStart time, + ObjectID objID, + size_t length) + : Record(time), objID_(objID), length_(length) {} + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + RecordType getType() const override { + return type; + } + std::vector defs() const override { + return {objID_}; + } + }; + + /// A CreateUInt8ArrayFromArrayBufferRecord is an event where a new UInt8Array + /// is created from an existing ArrayBuffer with offset and length. + struct CreateUInt8ArrayFromArrayBufferRecord final : public Record { + static constexpr RecordType type{ + RecordType::CreateUInt8ArrayFromArrayBuffer}; + /// The ObjectID of the UInt8Array that was created by createUint8Array(). + const ObjectID objID_; + /// The ObjectID of the ArrayBuffer used to create the UInt8Array. + const ObjectID bufferID_; + /// The byte offset into the ArrayBuffer. + const size_t offset_; + /// The length of the UInt8Array view. + const size_t length_; + + explicit CreateUInt8ArrayFromArrayBufferRecord( + TimeSinceStart time, + ObjectID objID, + ObjectID bufferID, + size_t offset, + size_t length) + : Record(time), + objID_(objID), + bufferID_(bufferID), + offset_(offset), + length_(length) {} + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + RecordType getType() const override { + return type; + } + std::vector defs() const override { + return {objID_}; + } + std::vector uses() const override { + return {bufferID_}; + } + }; + + /// A GetBufferFromTypedArrayRecord is an event where the underlying + /// ArrayBuffer of a TypedArray is retrieved. + struct GetBufferFromTypedArrayRecord final : public Record { + static constexpr RecordType type{RecordType::GetBufferFromTypedArray}; + /// The ObjectID of the ArrayBuffer returned by buffer(). + const ObjectID bufferID_; + /// The ObjectID of the TypedArray whose buffer was queried. + const ObjectID typedArrayID_; + + explicit GetBufferFromTypedArrayRecord( + TimeSinceStart time, + ObjectID bufferID, + ObjectID typedArrayID) + : Record(time), bufferID_(bufferID), typedArrayID_(typedArrayID) {} + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + RecordType getType() const override { + return type; + } + std::vector defs() const override { + return {bufferID_}; + } + std::vector uses() const override { + return {typedArrayID_}; + } + }; + + /// A CreateJSErrorRecord is an event where a JavaScript Error object is + /// created with a specific type and message. + struct CreateJSErrorRecord final : public Record { + static constexpr RecordType type{RecordType::CreateJSError}; + /// The ObjectID of the error Value that was created. + const ObjectID objID_; + /// The type of error being created. + const JSErrorType errorType_; + /// The ObjectID of the message String passed to create the error. + const ObjectID messageID_; + + explicit CreateJSErrorRecord( + TimeSinceStart time, + ObjectID objID, + JSErrorType errorType, + ObjectID messageID) + : Record(time), + objID_(objID), + errorType_(errorType), + messageID_(messageID) {} + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + RecordType getType() const override { + return type; + } + std::vector defs() const override { + return {objID_}; + } + std::vector uses() const override { + return {messageID_}; + } + }; + /// An ArrayReadRecord is an event where a value was read from an index /// of an array. /// It is modeled separately from GetProperty because it is more efficient to @@ -959,6 +1243,37 @@ class SynthTrace { void toJSONInternal(::hermes::JSONEmitter &json) const override; }; + struct ArrayPushRecord final : public Record { + static constexpr RecordType type{RecordType::ArrayPush}; + /// The ObjectID of the array + const ObjectID objID_; + /// The elements being pushed to the array + const std::vector elements_; + /// The returned length from calling Array.push + size_t length_; + + explicit ArrayPushRecord( + TimeSinceStart time, + ObjectID objID, + const std::vector &elements, + size_t length) + : Record(time), objID_(objID), elements_(elements), length_(length) {} + + RecordType getType() const override { + return type; + } + + std::vector uses() const override { + std::vector uses{objID_}; + for (const auto &val : elements_) { + pushIfTrackedValue(val, uses); + } + return uses; + } + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + }; + struct CallRecord : public Record { /// The ObjectID of the function JS object that was called from /// JS or native. @@ -1285,6 +1600,112 @@ class SynthTrace { void toJSONInternal(::hermes::JSONEmitter &json) const override; }; + /// A Utf16Record is an event where a PropNameID or String was converted to + /// UTF-16. + struct Utf16Record final : public Record { + static constexpr RecordType type{RecordType::Utf16}; + /// PropNameID, String passed to utf16() as an argument + const TraceValue objID_; + /// Returned string from utf16(). + const std::u16string retVal_; + + explicit Utf16Record( + TimeSinceStart time, + const TraceValue objID, + std::u16string retval) + : Record(time), objID_(objID), retVal_(std::move(retval)) {} + + RecordType getType() const override { + return type; + } + + std::vector uses() const override { + std::vector vec; + pushIfTrackedValue(objID_, vec); + return vec; + } + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + }; + + /// A GetStringData is an event where getStringData or getPropNameIdData was + /// invoked. + struct GetStringDataRecord final : public Record { + static constexpr RecordType type{RecordType::GetStringData}; + /// The String or PropNameID passed into getStringData or getPropNameIdData + const TraceValue objID_; + /// The string content in the String or PropNameID that was passed into the + /// callback + const std::u16string strData_; + + explicit GetStringDataRecord( + TimeSinceStart time, + const TraceValue objID, + std::u16string strData) + : Record(time), objID_(objID), strData_(std::move(strData)) {} + + RecordType getType() const override { + return type; + } + + std::vector uses() const override { + std::vector vec; + pushIfTrackedValue(objID_, vec); + return vec; + } + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + }; + + struct SerializeRecord final : public Record { + static constexpr RecordType type{RecordType::Serialize}; + /// The jsi::Value being serialized + const TraceValue value_; + + explicit SerializeRecord(TimeSinceStart time, TraceValue value) + : Record(time), value_(value) {} + + RecordType getType() const override { + return type; + } + + std::vector uses() const override { + std::vector uses; + pushIfTrackedValue(value_, uses); + return uses; + } + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + }; + + struct DeserializeRecord final : public Record { + static constexpr RecordType type{RecordType::Deserialize}; + /// This mirrors the structure of vm::SerializedValue + std::vector offsets_; + std::vector content_; + std::vector strings_; + + explicit DeserializeRecord( + TimeSinceStart time, + const std::vector &offsets, + const std::vector &content, + const std::vector &strings) + : Record(time), + offsets_(offsets), + content_(content), + strings_(strings) {} + + RecordType getType() const override { + return type; + } + + std::vector uses() const override { + return {}; + } + + void toJSONInternal(::hermes::JSONEmitter &json) const override; + }; + struct GlobalRecord final : public Record { static constexpr RecordType type{RecordType::Global}; const ObjectID objID_; // global's ObjectID returned from Runtime::global(). @@ -1312,5 +1733,3 @@ class SynthTrace { } // namespace tracing } // namespace hermes } // namespace facebook - -#endif // HERMES_SYNTHTRACE_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/SynthTraceParser.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/SynthTraceParser.h index 7844ee50..eee8a94a 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/SynthTraceParser.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/SynthTraceParser.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_SYNTHTRACEPARSER_H -#define HERMES_SYNTHTRACEPARSER_H +#pragma once #include @@ -36,5 +35,3 @@ parseSynthTrace(const std::string &tracefile); } // namespace tracing } // namespace hermes } // namespace facebook - -#endif // HERMES_SYNTHTRACEPARSER_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/ThreadSafetyAnalysis.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/ThreadSafetyAnalysis.h index 39e6cf66..f69df8ca 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/ThreadSafetyAnalysis.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/ThreadSafetyAnalysis.h @@ -7,8 +7,7 @@ // Based on mutex.h from https://clang.llvm.org/docs/ThreadSafetyAnalysis.html -#ifndef THREAD_SAFETY_ANALYSIS_MUTEX_H -#define THREAD_SAFETY_ANALYSIS_MUTEX_H +#pragma once // Enable thread safety attributes only with clang. // The attributes can be safely erased when compiling with other compilers. @@ -74,5 +73,3 @@ #define TSA_NO_THREAD_SAFETY_ANALYSIS \ TSA_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) - -#endif // THREAD_SAFETY_ANALYSIS_MUTEX_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/TraceInterpreter.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/TraceInterpreter.h index 0a1240c1..bcef27ce 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/TraceInterpreter.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/TraceInterpreter.h @@ -12,6 +12,8 @@ #include #include +#include +#include #include #include #include @@ -46,6 +48,13 @@ class TraceInterpreter final { /// the trace. If false, start from the default config. bool useTraceConfig{false}; + /// Enable basic block profiling. + bool basicBlockProfiling{false}; + + // If non-empty, write profiling output to this file, rather than + // to stderr. + std::string profilingOutFile; + /// Number of initial executions whose stats are discarded. int warmupReps{0}; @@ -53,10 +62,20 @@ class TraceInterpreter final { /// with the median totalTime. int reps{1}; + /// If non-null, holds statistics for every garbage collection that occurs. + const std::vector<::hermes::vm::GCAnalyticsEvent> *gcAnalyticsEvents{ + nullptr}; + /// If true, run a complete collection before printing stats. Useful for /// guaranteeing there's no garbage in heap size numbers. bool forceGCBeforeStats{false}; + /// If true, use the Hermes VM JIT during execution. + bool enableJIT{false}; + + /// If true, force JIT compilation on all functions. + bool forceJIT{false}; + /// If true, remove the requirement that the input bytecode was compiled /// from the same source used to record the trace. There must only be one /// input bytecode file in this case. If its observable behavior deviates @@ -108,6 +127,8 @@ class TraceInterpreter final { llvh::raw_ostream *traceStream_; // Map from source hash to source file to run. std::map<::hermes::SHA1, std::shared_ptr> bundles_; + // Map from source hash to shermes unit creator function. + std::map<::hermes::SHA1, SHUnitCreator> shermesUnitCreatorFns_; const SynthTrace &trace_; /// The last use of each object. @@ -151,18 +172,34 @@ class TraceInterpreter final { const std::string &traceFile, const std::vector &bytecodeFiles, const ExecuteOptions &options, - const std::function( + const std::function( const ::hermes::vm::RuntimeConfig &runtimeConfig)> &createRuntime); +#ifndef _WIN32 + /// Execute the trace given by \p traceFile, that was the trace of executing + /// the bundle from which \p shermesUnitLibFiles are generated. + /// \param shermesUnitCreatorFns A map from source hash to the shermes unit + /// creator function (i.e., sh_export_), which is defined in the + /// shermes generated C file. For each BeginExecJSRecord, the shermes unit + /// with matching source hash will be evaluated. + /// \return The stats collected by the runtime about times and memory usage. + static std::string execNativeWithRuntime( + const std::string &traceFile, + const std::map<::hermes::SHA1, SHUnitCreator> &shermesUnitCreatorFns, + const ExecuteOptions &options, + const std::function( + const ::hermes::vm::RuntimeConfig &runtimeConfig)> &createRuntime); +#endif + /// \param traceStream If non-null, write a trace of the execution into this /// stream. /// \return Tuple of GC stats and the runtime instance used for replaying. - static std::tuple> + static std::tuple> execFromMemoryBuffer( std::unique_ptr &&traceBuf, std::vector> &&codeBufs, const ExecuteOptions &options, - const std::function( + const std::function( const ::hermes::vm::RuntimeConfig &runtimeConfig)> &createRuntime); private: @@ -172,6 +209,12 @@ class TraceInterpreter final { const SynthTrace &trace, std::map<::hermes::SHA1, std::shared_ptr> bundles); + TraceInterpreter( + jsi::Runtime &rt, + const ExecuteOptions &options, + const SynthTrace &trace, + std::map<::hermes::SHA1, SHUnitCreator> shermesUnitCreatorFns); + static std::string exec( jsi::Runtime &rt, const ExecuteOptions &options, @@ -212,6 +255,13 @@ class TraceInterpreter final { /// HostObject's functions are called. void executeRecords(); + /// Execute the record. When \p bundles_ is not empty, the bundle file + /// (source or bytecode) with the matching source hash will be evaluated. + /// Otherwise, the shermes unit from \p shermesUnitCreatorFns_ with matching + /// source hash will be evaluated. + jsi::Value executeBeginExecJSRecord( + const SynthTrace::BeginExecJSRecord &bejsr); + /// Requires that \p valID is the proper id for \p val, and that a /// defining occurrence of \p valID occurs at the current \p defIndex. Decides /// whether the definition should be recorded, and, if so, adds the diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/TracingRuntime.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/TracingRuntime.h index f3d082d5..bc338c9d 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/TracingRuntime.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/TracingRuntime.h @@ -5,11 +5,9 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_TRACINGRUNTIME_H -#define HERMES_TRACINGRUNTIME_H - -#include "SynthTrace.h" +#pragma once +#include #include #include #include "llvh/Support/raw_ostream.h" @@ -18,12 +16,21 @@ namespace facebook { namespace hermes { namespace tracing { -class TracingRuntime : public jsi::RuntimeDecorator { +/// Prepare traceable builtins by installing Math wrappers into both properties +/// and static builtin slots. +void installTraceableBuiltinWrappers(jsi::Runtime &runtime); + +class TracingRuntime : public jsi::RuntimeDecorator +#ifdef JSI_UNSTABLE + , + public jsi::ISerialization +#endif +{ public: using RD = RuntimeDecorator; TracingRuntime( - std::unique_ptr runtime, + std::shared_ptr runtime, const ::hermes::vm::RuntimeConfig &conf, std::unique_ptr traceStream); @@ -37,6 +44,7 @@ class TracingRuntime : public jsi::RuntimeDecorator { /// @name jsi::Runtime methods. /// @{ + jsi::ICast *castInterface(const jsi::UUID &interfaceUUID) override; jsi::Value evaluateJavaScript( const std::shared_ptr &buffer, const std::string &sourceURL) override; @@ -47,6 +55,7 @@ class TracingRuntime : public jsi::RuntimeDecorator { jsi::Object global() override; jsi::Object createObject() override; + jsi::Object createObjectWithPrototype(const jsi::Value &prototype) override; jsi::Object createObject(std::shared_ptr ho) override; // Note that the NativeState methods do not need to be traced since they @@ -58,14 +67,32 @@ class TracingRuntime : public jsi::RuntimeDecorator { jsi::String createStringFromAscii(const char *str, size_t length) override; jsi::String createStringFromUtf8(const uint8_t *utf8, size_t length) override; + jsi::String createStringFromUtf16(const char16_t *utf16, size_t length) + override; std::string utf8(const jsi::PropNameID &) override; jsi::PropNameID createPropNameIDFromAscii(const char *str, size_t length) override; jsi::PropNameID createPropNameIDFromUtf8(const uint8_t *utf8, size_t length) override; + jsi::PropNameID createPropNameIDFromUtf16( + const char16_t *utf16, + size_t length) override; std::string utf8(const jsi::String &) override; + std::u16string utf16(const jsi::PropNameID &) override; + std::u16string utf16(const jsi::String &) override; + + void getStringData( + const jsi::String &str, + void *ctx, + void (*cb)(void *ctx, bool ascii, const void *data, size_t num)) override; + + void getPropNameIdData( + const jsi::PropNameID &sym, + void *ctx, + void (*cb)(void *ctx, bool ascii, const void *data, size_t num)) override; + std::string symbolToString(const jsi::Symbol &) override; jsi::PropNameID createPropNameIDFromString(const jsi::String &str) override; @@ -75,10 +102,13 @@ class TracingRuntime : public jsi::RuntimeDecorator { override; jsi::Value getProperty(const jsi::Object &obj, const jsi::PropNameID &name) override; + jsi::Value getProperty(const jsi::Object &obj, const jsi::Value &name) + override; bool hasProperty(const jsi::Object &obj, const jsi::String &name) override; bool hasProperty(const jsi::Object &obj, const jsi::PropNameID &name) override; + bool hasProperty(const jsi::Object &obj, const jsi::Value &name) override; void setPropertyValue( const jsi::Object &obj, @@ -88,6 +118,19 @@ class TracingRuntime : public jsi::RuntimeDecorator { const jsi::Object &obj, const jsi::PropNameID &name, const jsi::Value &value) override; + void setPropertyValue( + const jsi::Object &obj, + const jsi::Value &name, + const jsi::Value &value) override; + + void deleteProperty(const jsi::Object &obj, const jsi::PropNameID &name) + override; + void deleteProperty(const jsi::Object &obj, const jsi::String &name) override; + void deleteProperty(const jsi::Object &, const jsi::Value &name) override; + + void setPrototypeOf(const jsi::Object &object, const jsi::Value &prototype) + override; + jsi::Value getPrototypeOf(const jsi::Object &object) override; jsi::Array getPropertyNames(const jsi::Object &o) override; @@ -99,6 +142,22 @@ class TracingRuntime : public jsi::RuntimeDecorator { jsi::ArrayBuffer createArrayBuffer( std::shared_ptr buffer) override; + jsi::Uint8Array createUint8Array(size_t length) override; + jsi::Uint8Array createUint8Array( + const jsi::ArrayBuffer &buffer, + size_t offset, + size_t length) override; + + jsi::ArrayBuffer buffer(const jsi::TypedArray &typedArray) override; + + jsi::Value createError(const jsi::String &msg) override; + jsi::Value createEvalError(const jsi::String &msg) override; + jsi::Value createRangeError(const jsi::String &msg) override; + jsi::Value createReferenceError(const jsi::String &msg) override; + jsi::Value createSyntaxError(const jsi::String &msg) override; + jsi::Value createTypeError(const jsi::String &msg) override; + jsi::Value createURIError(const jsi::String &msg) override; + size_t size(const jsi::Array &arr) override; size_t size(const jsi::ArrayBuffer &buf) override; @@ -111,6 +170,9 @@ class TracingRuntime : public jsi::RuntimeDecorator { size_t i, const jsi::Value &value) override; + size_t push(const jsi::Array &arr, const jsi::Value *elements, size_t count) + override; + jsi::Function createFunctionFromHostFunction( const jsi::PropNameID &name, unsigned int paramCount, @@ -130,8 +192,21 @@ class TracingRuntime : public jsi::RuntimeDecorator { void setExternalMemoryPressure(const jsi::Object &obj, size_t amount) override; + std::shared_ptr tryGetMutableBuffer( + const jsi::ArrayBuffer &buffer) override; /// @} +#ifdef JSI_UNSTABLE + std::shared_ptr serialize(const jsi::Value &value) override; + jsi::Value deserialize( + const std::shared_ptr &serialized) override; + std::unique_ptr serializeWithTransfer( + const jsi::Value &value, + const jsi::Array &transferList) override; + jsi::Array deserializeWithTransfer( + std::unique_ptr &serialized) override; +#endif + void addMarker(const std::string &marker); SynthTrace &trace() { @@ -172,7 +247,7 @@ class TracingRuntime : public jsi::RuntimeDecorator { SynthTrace::TimeSinceStart getTimeSinceStart() const; - std::unique_ptr runtime_; + std::shared_ptr runtime_; SynthTrace trace_; std::deque savedFunctions; const SynthTrace::TimePoint startTime_{std::chrono::steady_clock::now()}; @@ -209,7 +284,7 @@ class TracingHermesRuntime final : public TracingRuntime { /// \p rollbackAction is invoked if the runtime is destructed prior to /// completion of tracing. It may or may not invoked if completion failed. TracingHermesRuntime( - std::unique_ptr runtime, + std::shared_ptr runtime, const ::hermes::vm::RuntimeConfig &runtimeConfig, std::unique_ptr traceStream, std::function commitAction, @@ -257,7 +332,7 @@ class TracingHermesRuntime final : public TracingRuntime { /// The return value of \p traceCompletionCallback indicates whether the /// invocation completed successfully. std::unique_ptr makeTracingHermesRuntime( - std::unique_ptr hermesRuntime, + std::shared_ptr hermesRuntime, const ::hermes::vm::RuntimeConfig &runtimeConfig, const std::string &traceScratchPath, const std::string &traceResultPath, @@ -268,7 +343,7 @@ std::unique_ptr makeTracingHermesRuntime( /// The \p forReplay parameter indicates whether the runtime is being used /// in trace replay. (Its behavior can differ slightly in that case.) std::unique_ptr makeTracingHermesRuntime( - std::unique_ptr hermesRuntime, + std::shared_ptr hermesRuntime, const ::hermes::vm::RuntimeConfig &runtimeConfig, std::unique_ptr traceStream, bool forReplay = false); @@ -276,5 +351,3 @@ std::unique_ptr makeTracingHermesRuntime( } // namespace tracing } // namespace hermes } // namespace facebook - -#endif // HERMES_TRACINGRUNTIME_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/CDPAgent.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/CDPAgent.h index e2243259..8169f152 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/CDPAgent.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/CDPAgent.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_CDPAGENT_H -#define HERMES_CDP_CDPAGENT_H +#pragma once #include #include @@ -29,7 +28,8 @@ class CDPDebugAPI; /// Public-facing wrapper for internal CDP state that can be preserved across /// reloads. -struct HERMES_EXPORT State { +class HERMES_EXPORT State { + public: /// Incomplete type that stores the actual state. struct Private; @@ -103,8 +103,9 @@ class HERMES_EXPORT CDPAgent { /// tasks enqueued during destruction. ~CDPAgent(); - /// Process a CDP command encoded in \p json. This can be called from - /// arbitrary threads. + /// This function can be called from arbitrary threads. It processes a CDP + /// command encoded in \p json as UTF-8 in accordance with RFC-8259. See: + // https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/public/devtools_protocol/#wire-format_strings-and-binary-values void handleCommand(std::string json); /// Enable the Runtime domain without processing a CDP command or sending a @@ -128,5 +129,3 @@ class HERMES_EXPORT CDPAgent { } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_CDPAGENT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/CDPDebugAPI.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/CDPDebugAPI.h index 9809ec9a..9c8b256b 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/CDPDebugAPI.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/CDPDebugAPI.h @@ -5,12 +5,11 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_CDPDEBUGAPI_H -#define HERMES_CDP_CDPDEBUGAPI_H +#pragma once #include - -#include "ConsoleMessage.h" +#include +#include namespace facebook { namespace hermes { @@ -37,7 +36,12 @@ class HERMES_EXPORT CDPDebugAPI { /// Gets the AsyncDebuggerAPI associated with this instance. debugger::AsyncDebuggerAPI &asyncDebuggerAPI() { - return *asyncDebuggerAPI_; + return asyncDebuggerAPI_; + } + + /// Gets the DebuggerDomainCoordinator associated with this instance. + DebuggerDomainCoordinator &debuggerDomainCoordinator() { + return debuggerDomainCoordinator_; } /// Adds a console message to the current CDPDebugAPI instance, @@ -53,14 +57,17 @@ class HERMES_EXPORT CDPDebugAPI { CDPDebugAPI(HermesRuntime &runtime, size_t maxCachedMessages); - HermesRuntime &runtime_; - std::unique_ptr asyncDebuggerAPI_; + /// Member order matters for destruction: asyncDebuggerAPI_ must be destroyed + /// first, as its destructor flushes the queue of pending tasks, which may + /// reference other objects (like consoleMessageDispatcher_ and + /// debuggerDomainCoordinator_). ConsoleMessageStorage consoleMessageStorage_; ConsoleMessageDispatcher consoleMessageDispatcher_; + HermesRuntime &runtime_; + DebuggerDomainCoordinator debuggerDomainCoordinator_; + debugger::AsyncDebuggerAPI asyncDebuggerAPI_; }; } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_CDPDEBUGAPI_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/CallbackOStream.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/CallbackOStream.h index b8a4eb3b..bdf7914f 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/CallbackOStream.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/CallbackOStream.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_CALLBACKOSTREAM_H -#define HERMES_CDP_CALLBACKOSTREAM_H +#pragma once #include #include @@ -21,7 +20,8 @@ namespace cdp { /// Subclass of \c std::ostream where flushing is implemented through a /// callback. Writes are collected in a buffer. When filled, the buffer's /// contents are emptied out and sent to a callback. -struct CallbackOStream : public std::ostream { +class CallbackOStream : public std::ostream { + public: /// Signature of callback called to flush buffer contents. Accepts the buffer /// as a string. Returns a boolean indicating whether flushing succeeded. /// Callback failure will be translated to stream failure. If the callback @@ -45,7 +45,8 @@ struct CallbackOStream : public std::ostream { private: /// \c std::streambuf sub-class backed by a std::string buffer and /// implementing overflow by calling a callback. - struct StreamBuf : public std::streambuf { + class StreamBuf : public std::streambuf { + public: /// Construct a new streambuf. Parameters are the same as those of /// \c CallbackOStream . StreamBuf(size_t sz, Fn cb); @@ -86,5 +87,3 @@ struct CallbackOStream : public std::ostream { } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_CALLBACKOSTREAM_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/ConsoleMessage.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/ConsoleMessage.h index 906dbb9a..88577592 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/ConsoleMessage.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/ConsoleMessage.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_CDPCONSOLEMESSAGESTORAGE_H -#define HERMES_CDP_CDPCONSOLEMESSAGESTORAGE_H +#pragma once #include #include @@ -134,5 +133,3 @@ class ConsoleMessageDispatcher { } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_CDPCONSOLEMESSAGESTORAGE_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DebuggerDomainAgent.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DebuggerDomainAgent.h index b1336e6b..5e83856d 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DebuggerDomainAgent.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DebuggerDomainAgent.h @@ -5,25 +5,21 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_DEBUGGERDOMAINAGENT_H -#define HERMES_CDP_DEBUGGERDOMAINAGENT_H +#pragma once -#include #include #include +#include +#include +#include #include #include -#include "DomainAgent.h" -#include "DomainState.h" - namespace facebook { namespace hermes { namespace cdp { -enum class PausedNotificationReason; - namespace m = ::facebook::hermes::cdp::message; /// Details about a single Hermes breakpoint, implied by a CDP breakpoint. @@ -89,12 +85,15 @@ class DebuggerDomainAgent : public DomainAgent { DebuggerDomainAgent( int32_t executionContextID, HermesRuntime &runtime, - debugger::AsyncDebuggerAPI &asyncDebugger, + debugger::AsyncDebuggerAPI &asyncDebuggerAPI, + DebuggerDomainCoordinator &debuggerDomainAPI, SynchronizedOutboundCallback messageCallback, std::shared_ptr objTable_, DomainState &state); ~DebuggerDomainAgent(); + // ------ CDP API (used by CDPAgent) ------ + /// Enables the Debugger domain without processing CDP message or sending a /// CDP response. It will still send CDP notifications if needed. void enable(); @@ -119,7 +118,8 @@ class DebuggerDomainAgent : public DomainAgent { /// Handles Debugger.setBlackboxedRanges request void setBlackboxedRanges(const m::debugger::SetBlackboxedRangesRequest &req); - + /// Handles Debugger.setBlackboxPatterns request + void setBlackboxPatterns(const m::debugger::SetBlackboxPatternsRequest &req); /// Handles Debugger.setPauseOnExceptions void setPauseOnExceptions( const m::debugger::SetPauseOnExceptionsRequest &req); @@ -127,12 +127,28 @@ class DebuggerDomainAgent : public DomainAgent { /// Handles Debugger.evaluateOnCallFrame void evaluateOnCallFrame(const m::debugger::EvaluateOnCallFrameRequest &req); - /// Debugger.setBreakpoint creates a CDP breakpoint that applies to exactly - /// one script (identified by script ID) that does not survive reloads. + /// @cdp Debugger.setBreakpoint creates a CDP breakpoint that applies to + /// exactly one script (identified by script ID) that does not survive + /// reloads. A `condition` equal to an empty string is treated the same as an + /// omitted condition (= unconditional breakpoint). + /// Hermes allows multiple breakpoints to be set at the same location, + /// even in the same CDP session. For comparison, V8 allows it from different + /// sessions but disallows it within a single session. void setBreakpoint(const m::debugger::SetBreakpointRequest &req); - // Debugger.setBreakpointByUrl creates a CDP breakpoint that may apply to - // multiple scripts (identified by URL), and survives reloads. + /// @cdp Debugger.setBreakpointByUrl creates a CDP breakpoint that may apply + /// to multiple scripts (identified by URL), and survives reloads. A + /// `condition` equal to an empty string is treated the same as an omitted + /// condition (= unconditional breakpoint). + /// Hermes allows multiple breakpoints to be set at the same location, + /// even in the same CDP session. For comparison, V8 allows it from different + /// sessions but disallows it within a single session. void setBreakpointByUrl(const m::debugger::SetBreakpointByUrlRequest &req); + /// @cdp Debugger.getPossibleBreakpoints returns the valid breakpoint + /// locations within a source range. The `start` and (if provided) `end` + /// locations must refer to the same script. `restrictToFunction` is not yet + /// supported and is ignored. + void getPossibleBreakpoints( + const m::debugger::GetPossibleBreakpointsRequest &req); /// Handles Debugger.removeBreakpoint void removeBreakpoint(const m::debugger::RemoveBreakpointRequest &req); /// Handles Debugger.setBreakpointsActive @@ -140,75 +156,131 @@ class DebuggerDomainAgent : public DomainAgent { void setBreakpointsActive( const m::debugger::SetBreakpointsActiveRequest &req); - private: - /// Handle an event originating from the runtime. - void handleDebuggerEvent( - HermesRuntime &runtime, - debugger::AsyncDebuggerAPI &asyncDebugger, - debugger::DebuggerEventType event); + // ------ Coordinator API (used by DebuggerDomainCoordinator) ------ + + void processScript(const debugger::SourceLocation &srcLoc); + bool locationHasManualBreakpoint( + const debugger::SourceLocation &srcLoc) const; + + /// Checks whether the passed location falls within a blackboxed range + /// in blackboxedRanges_. + /// Chrome looks at full functions ("frames") to determine this. See: + /// https://source.chromium.org/chromium/chromium/src/+/318e9cfd9fbbbc70906f6a78d017a2708248dc6d:v8/src/inspector/v8-debugger-agent-impl.cc;l=984-1026 + /// We, on the other hand, look at individual lines since there's no + /// difference in practise because the current way functions are blackboxed is + /// by using ignoreList in source maps, which blackboxes full files, which + /// means also it blackboxes full functions, so there's no difference between + /// checking if a line in a function is blackboxed or if the whole function is + /// blackboxed. + /// This means that we receive one "Debugger.setBlackboxedRanges" per bundle + /// file comprised of source js files. + /// For each file appearing in the "ignoreList" in source maps, we receive the + /// start positions and end positions of the file inside the bundle file: + /// [ file 1 start position, + /// file 1 end position, + /// file 2 start position, + /// file 2 end position, + /// ... ] + bool isLocationBlackboxed(const debugger::SourceLocation &loc) const; + + void notifyPaused(PausedNotificationReason reason); + void notifyUnpaused(); + private: /// Send a Debugger.paused notification to the debug client void sendPausedNotificationToClient(PausedNotificationReason reason); /// Send a Debugger.scriptParsed notification to the debug client void sendScriptParsedNotificationToClient( const debugger::SourceLocation srcLoc); - /// Obtain the newly loaded script and send a ScriptParsed notification to the - /// debug client - void processNewLoadedScript(); - std::pair createCDPBreakpoint( CDPBreakpointDescription &&description, std::optional hermesBreakpoint = std::nullopt); - std::optional createHermesBreakpont( + std::optional createHermesBreakpoint( debugger::ScriptID scriptID, const CDPBreakpointDescription &description); + void applyBreakpointAndSendNotification( + CDPBreakpointID cdpBreakpointID, + CDPBreakpoint &cdpBreakpoint, + const debugger::SourceLocation &srcLoc); + std::optional applyBreakpoint( - CDPBreakpoint &breakpoint, + CDPBreakpoint &cdpBreakpoint, debugger::ScriptID scriptID); + /// Holds a boolean that determines if scripts without a script url + /// (e.g. anonymous scripts) should be blackboxed. + /// Same as V8: + /// https://source.chromium.org/chromium/chromium/src/+/fef5d519bab86dbd712d76bfca5be90a6e03459c:v8/src/inspector/v8-debugger-agent-impl.cc;l=997-999 + bool blackboxAnonymousScripts_ = false; + /// Optionally, holds a compiled regex pattern that is used to test if + /// script urls should be blackboxed. + /// See isLocationBlackboxed below for more details. Same as V8: + /// https://source.chromium.org/chromium/chromium/src/+/fef5d519bab86dbd712d76bfca5be90a6e03459c:v8/src/inspector/v8-debugger-agent-impl.cc;l=993-996 + /// Matching using the compiled regex should be done with + /// ::hermes::regex::searchWithBytecode. + std::optional> compiledBlackboxPatternRegex_; + + /// A vector of 1-based positions per script id indicating where blackbox + /// state changes using [from inclusive, to exclusive) pairs. + /// [ (start) ... position[0]) range is not blackboxed + /// [position[0] ... position[1]) range is blackboxed + /// [position[1] ... position[2]) range is not blackboxed ... ... + /// [position[n] ... (end) ) range is blackboxed if n is even, not + /// blackboxed if odd. + /// This is used to determine if the debugger is paused on one of these + /// blackboxed ranges, to prevent the user from stopping there in the + /// following scenarios: + /// 1. Step out- repeats stepping out until reaches a non-blackboxed range. + /// 2. Step over- stepping over to a blackboxed range meaning that + /// the next un-blackboxed range would be after all the stepping in the + /// function are done (because blackboxing is per file, meaning per function + /// as well) so we can execute step out as well in this case until we + /// step out of blackboxed ranges. + /// Comparing with v8, we don’t check if the user comes from a blackboxed + /// range, but only if a stepover got you to a blackboxed range. However + /// both results in the same thing which is stepping out until reaching a + /// non-blackboxed range. + /// 3. Step into- execute another step into. + /// Repeat this step until outside of a blackboxed range. + /// 4. Exceptions triggering the debugger pause- + /// (uncaught or if the user chooses to stop on all exceptions)- + /// ignore and continue execution + /// 5. Debugger statements- ignore and continue execution + /// 6. Explicit pause- keep stepping in until reaching a non-blackboxed range + /// 7. Manual breakpoints- allow stopping in blackboxed ranges + std::unordered_map>> + blackboxedRanges_; + bool checkDebuggerEnabled(const m::Request &req); bool checkDebuggerPaused(const m::Request &req); /// Removes any modifications this agent made to Hermes in order to enable /// debugging - void cleanUp(); + void disable(); HermesRuntime &runtime_; debugger::AsyncDebuggerAPI &asyncDebugger_; - - /// ID for the registered DebuggerEventCallback - debugger::DebuggerEventCallbackID debuggerEventCallbackId_; + DebuggerDomainCoordinator &debuggerDomainCoordinator_; /// Details of each CDP breakpoint that has been created, and not /// yet destroyed. std::unordered_map cdpBreakpoints_{}; /// CDP breakpoint IDs are assigned by the DebuggerDomainAgent. Keep track of - /// the next available ID. - CDPBreakpointID nextBreakpointID_ = 1; + /// the next available ID. Starts with 100 to avoid confusion with Hermes + /// breakpoints IDs that start with 1. + CDPBreakpointID nextBreakpointID_ = 100; DomainState &state_; - /// Whether the currently installed breakpoints actually take effect. If - /// they're supposed to be inactive, then debugger agent will automatically - /// resume execution when breakpoints are hit. - bool breakpointsActive_ = true; - /// Whether Debugger.enable was received and wasn't disabled by receiving /// Debugger.disable bool enabled_; - - /// Whether to consider the debugger as currently paused. There are some - /// debugger events such as ScriptLoaded where we don't consider the debugger - /// to be paused. - bool paused_; }; } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_DEBUGGERDOMAINAGENT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DebuggerDomainCoordinator.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DebuggerDomainCoordinator.h new file mode 100644 index 00000000..6e73b1f6 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DebuggerDomainCoordinator.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#include +#include + +namespace facebook { +namespace hermes { +namespace cdp { + +enum class PausedNotificationReason { kException, kOther, kStep }; + +/// Last explicit debugger step command issued by the user. +enum class UserStepRequest { + StepInto, + StepOver, + StepOut, +}; + +class DebuggerDomainAgent; + +/// Coordinates multiple DebuggerDomainAgent instances connecting to the same +/// Hermes Runtime. This class manages shared state, ensures cooperative access, +/// and eliminates race conditions when multiple agents connect concurrently. +/// +/// All methods must be called on the runtime thread unless otherwise noted. +class DebuggerDomainCoordinator { + public: + /// Constructs a DebuggerDomainCoordinator for use with the provided + /// HermesRuntime. + explicit DebuggerDomainCoordinator(HermesRuntime &runtime); + ~DebuggerDomainCoordinator(); + + // Rule of Five: Non-copyable, non-movable (stable references required) + DebuggerDomainCoordinator(const DebuggerDomainCoordinator &) = delete; + DebuggerDomainCoordinator &operator=(const DebuggerDomainCoordinator &) = + delete; + DebuggerDomainCoordinator(DebuggerDomainCoordinator &&) = delete; + DebuggerDomainCoordinator &operator=(DebuggerDomainCoordinator &&) = delete; + + //===--------------------------------------------------------------------===// + // Agent management + //===--------------------------------------------------------------------===// + + /// Registers a new agent with the coordinator. We will call the agent's + /// methods to notify it of debugger events and query state set by the + /// debugging client (like blackboxed ranges). The agent MUST call + /// disableAgent() before being destroyed. + void enableAgent( + debugger::AsyncDebuggerAPI &asyncDebugger, + DebuggerDomainAgent &agent); + /// Unregisters an agent from the coordinator. + void disableAgent( + debugger::AsyncDebuggerAPI &asyncDebugger, + DebuggerDomainAgent &agent); + + //===--------------------------------------------------------------------===// + // Debugger control + //===--------------------------------------------------------------------===// + + /// Used to handle Debugger.pause requests + void pause(); + /// Used to handle Debugger.stepInto, Debugger.stepOver, + /// and debugger.stepOut requests + void stepFromPaused( + debugger::AsyncDebuggerAPI &asyncDebugger, + UserStepRequest stepRequest); + /// Globally enables or disables pausing at breakpoints. + void setBreakpointsActive(bool active); + /// Returns whether the debugger is currently paused. + bool isPaused(debugger::AsyncDebuggerAPI &asyncDebugger) const; + /// Used to handle Debugger.resume requests + void resume(debugger::AsyncDebuggerAPI &asyncDebugger); + + private: + /// Handle an event originating from the runtime. + void handleDebuggerEvent( + HermesRuntime &runtime, + debugger::AsyncDebuggerAPI &asyncDebugger, + debugger::DebuggerEventType event); + + /// Called when the runtime is paused. + void setPaused(PausedNotificationReason pausedNotificationReason); + + /// Called when the runtime is resumed. + void setUnpaused(); + + /// Obtain the newly loaded script and send a ScriptParsed notification to the + /// enabled agents + void processNewLoadedScript(); + + /// Checks whether the location of the top frame of the call stack is + /// blackboxed in ALL of the enabled agents (and has no manual breakpoints). + bool isTopFrameLocationBlackboxed(); + + HermesRuntime &runtime_; + + /// The set of agents that are currently enabled. + std::vector enabledAgents_; + + /// Whether the currently installed breakpoints actually take effect. If + /// they're supposed to be inactive, then we will automatically + /// resume execution when breakpoints are hit. + bool breakpointsActive_; + + /// Whether to consider the debugger as currently paused. There are some + /// debugger events such as ScriptLoaded where we don't consider the debugger + /// to be paused. + bool paused_; + + /// Set to true when the user selects to explicitly pause execution. + /// This is set back to false when the execution is paused. + bool explicitPausePending_ = false; + + /// Last explicit step type issued by the user. + /// * This is "sticky" - we can't tell if a step command was + /// completed since a step command that does not result in further operations + /// resolves to a "resume" without "stepFinished" or debugger pause. + /// That means that this member should only be used in situations where we are + /// sure that a step command was issued in the given scenario, i.e. a + /// StepFinish event. For example, a step into command followed by a resume + /// would leave this member holding an "StepInto" even when minutes later the + /// execution stops on a breakpoint. + std::optional lastUserStepRequest_ = std::nullopt; +}; + +} // namespace cdp +} // namespace hermes +} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DomainAgent.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DomainAgent.h index 6770e829..ae74e5ee 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DomainAgent.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DomainAgent.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_DOMAINAGENT_H -#define HERMES_CDP_DOMAINAGENT_H +#pragma once #include #include @@ -106,5 +105,3 @@ class DomainAgent { } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_DOMAINAGENT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DomainState.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DomainState.h index 4c21603c..6c169084 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DomainState.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/DomainState.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_DOMAINSTATE_H -#define HERMES_CDP_DOMAINSTATE_H +#pragma once #include #include @@ -32,11 +31,18 @@ namespace cdp { /// Base class for data to be stored in DomainState. struct StateValue { - public: virtual ~StateValue() = default; virtual std::unique_ptr copy() const = 0; }; +/// StateValue that can be used as a boolean flag. +struct BooleanStateValue : public StateValue { + ~BooleanStateValue() override = default; + std::unique_ptr copy() const override; + + bool value{false}; +}; + /// StateValue that can be used as a dictionary. Used as the main storage value /// of DomainState so that modifications can be based on keys of the dictionary /// hierarchy. @@ -132,5 +138,3 @@ class DomainState { } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_DOMAINSTATE_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/HeapProfilerDomainAgent.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/HeapProfilerDomainAgent.h index 227214bc..6fdb22d8 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/HeapProfilerDomainAgent.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/HeapProfilerDomainAgent.h @@ -5,13 +5,11 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_HEAPPROFILERDOMAINAGENT_H -#define HERMES_CDP_HEAPPROFILERDOMAINAGENT_H +#pragma once +#include #include -#include "DomainAgent.h" - namespace facebook { namespace hermes { namespace cdp { @@ -71,5 +69,3 @@ class HeapProfilerDomainAgent : public DomainAgent { } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_HEAPPROFILERDOMAINAGENT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/JSONValueInterfaces.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/JSONValueInterfaces.h index 23a12ba8..9faf2d79 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/JSONValueInterfaces.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/JSONValueInterfaces.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_JSONVALUEINTERFACES_H -#define HERMES_CDP_JSONVALUEINTERFACES_H +#pragma once #include #include @@ -39,5 +38,3 @@ bool jsonValsEQ(const JSONValue *A, const JSONValue *B); } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_JSONVALUEINTERFACES_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageConverters.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageConverters.h index 7397bd1d..3489b0a9 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageConverters.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageConverters.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_MESSAGECONVERTERS_H -#define HERMES_CDP_MESSAGECONVERTERS_H +#pragma once #include #include @@ -81,5 +80,3 @@ std::unique_ptr makeProfile(const std::string &value); } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_MESSAGECONVERTERS_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageInterfaces.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageInterfaces.h index f19418f5..7dd1c5cb 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageInterfaces.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageInterfaces.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_MESSAGEINTERFACES_H -#define HERMES_CDP_MESSAGEINTERFACES_H +#pragma once #include #include @@ -71,5 +70,3 @@ struct Notification : public Serializable { } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_MESSAGEINTERFACES_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageTypes.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageTypes.h index fcc86c32..682d94cb 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageTypes.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageTypes.h @@ -1,5 +1,5 @@ // Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved. -// @generated SignedSource<> +// @generated SignedSource<<727dcfe67419625e56b2acb525424108>> #pragma once @@ -20,6 +20,7 @@ using JSONBlob = std::string; struct UnknownRequest; namespace debugger { +struct BreakLocation; using BreakpointId = std::string; struct BreakpointResolvedNotification; struct CallFrame; @@ -28,6 +29,8 @@ struct DisableRequest; struct EnableRequest; struct EvaluateOnCallFrameRequest; struct EvaluateOnCallFrameResponse; +struct GetPossibleBreakpointsRequest; +struct GetPossibleBreakpointsResponse; struct Location; struct PauseRequest; struct PausedNotification; @@ -35,8 +38,10 @@ struct RemoveBreakpointRequest; struct ResumeRequest; struct ResumedNotification; struct Scope; +using ScriptLanguage = std::string; struct ScriptParsedNotification; struct ScriptPosition; +struct SetBlackboxPatternsRequest; struct SetBlackboxedRangesRequest; struct SetBreakpointByUrlRequest; struct SetBreakpointByUrlResponse; @@ -131,9 +136,11 @@ struct RequestHandler { virtual void handle(const debugger::DisableRequest &req) = 0; virtual void handle(const debugger::EnableRequest &req) = 0; virtual void handle(const debugger::EvaluateOnCallFrameRequest &req) = 0; + virtual void handle(const debugger::GetPossibleBreakpointsRequest &req) = 0; virtual void handle(const debugger::PauseRequest &req) = 0; virtual void handle(const debugger::RemoveBreakpointRequest &req) = 0; virtual void handle(const debugger::ResumeRequest &req) = 0; + virtual void handle(const debugger::SetBlackboxPatternsRequest &req) = 0; virtual void handle(const debugger::SetBlackboxedRangesRequest &req) = 0; virtual void handle(const debugger::SetBreakpointRequest &req) = 0; virtual void handle(const debugger::SetBreakpointByUrlRequest &req) = 0; @@ -177,9 +184,11 @@ struct NoopRequestHandler : public RequestHandler { void handle(const debugger::DisableRequest &req) override {} void handle(const debugger::EnableRequest &req) override {} void handle(const debugger::EvaluateOnCallFrameRequest &req) override {} + void handle(const debugger::GetPossibleBreakpointsRequest &req) override {} void handle(const debugger::PauseRequest &req) override {} void handle(const debugger::RemoveBreakpointRequest &req) override {} void handle(const debugger::ResumeRequest &req) override {} + void handle(const debugger::SetBlackboxPatternsRequest &req) override {} void handle(const debugger::SetBlackboxedRangesRequest &req) override {} void handle(const debugger::SetBreakpointRequest &req) override {} void handle(const debugger::SetBreakpointByUrlRequest &req) override {} @@ -370,6 +379,21 @@ struct runtime::ExceptionDetails : public Serializable { std::optional executionContextId; }; +struct debugger::BreakLocation : public Serializable { + BreakLocation() = default; + BreakLocation(BreakLocation &&) = default; + BreakLocation(const BreakLocation &) = delete; + static std::unique_ptr tryMake(const JSONObject *obj); + JSONValue *toJsonVal(JSONFactory &factory) const override; + BreakLocation &operator=(const BreakLocation &) = delete; + BreakLocation &operator=(BreakLocation &&) = default; + + runtime::ScriptId scriptId{}; + long long lineNumber{}; + std::optional columnNumber; + std::optional type; +}; + struct debugger::Scope : public Serializable { Scope() = default; Scope(Scope &&) = default; @@ -623,6 +647,19 @@ struct debugger::EvaluateOnCallFrameRequest : public Request { std::optional throwOnSideEffect; }; +struct debugger::GetPossibleBreakpointsRequest : public Request { + GetPossibleBreakpointsRequest(); + static std::unique_ptr tryMake( + const JSONObject *obj); + + JSONValue *toJsonVal(JSONFactory &factory) const override; + void accept(RequestHandler &handler) const override; + + debugger::Location start{}; + std::optional end; + std::optional restrictToFunction; +}; + struct debugger::PauseRequest : public Request { PauseRequest(); static std::unique_ptr tryMake(const JSONObject *obj); @@ -652,6 +689,18 @@ struct debugger::ResumeRequest : public Request { std::optional terminateOnResume; }; +struct debugger::SetBlackboxPatternsRequest : public Request { + SetBlackboxPatternsRequest(); + static std::unique_ptr tryMake( + const JSONObject *obj); + + JSONValue *toJsonVal(JSONFactory &factory) const override; + void accept(RequestHandler &handler) const override; + + std::vector patterns; + std::optional skipAnonymous; +}; + struct debugger::SetBlackboxedRangesRequest : public Request { SetBlackboxedRangesRequest(); static std::unique_ptr tryMake( @@ -1015,6 +1064,15 @@ struct debugger::EvaluateOnCallFrameResponse : public Response { std::optional exceptionDetails; }; +struct debugger::GetPossibleBreakpointsResponse : public Response { + GetPossibleBreakpointsResponse() = default; + static std::unique_ptr tryMake( + const JSONObject *obj); + JSONValue *toJsonVal(JSONFactory &factory) const override; + + std::vector locations; +}; + struct debugger::SetBreakpointResponse : public Response { SetBreakpointResponse() = default; static std::unique_ptr tryMake(const JSONObject *obj); @@ -1181,6 +1239,7 @@ struct debugger::ScriptParsedNotification : public Notification { std::optional hasSourceURL; std::optional isModule; std::optional length; + std::optional scriptLanguage; }; struct heapProfiler::AddHeapSnapshotChunkNotification : public Notification { diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageTypesInlines.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageTypesInlines.h index fe765f93..027c9e1d 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageTypesInlines.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/MessageTypesInlines.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_MESSAGETYPESINLINES_H -#define HERMES_CDP_MESSAGETYPESINLINES_H +#pragma once #include #include @@ -312,5 +311,3 @@ void deleter(T *p) { } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_MESSAGETYPESINLINES_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/ProfilerDomainAgent.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/ProfilerDomainAgent.h index 6c62b9c8..b074111f 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/ProfilerDomainAgent.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/ProfilerDomainAgent.h @@ -5,14 +5,12 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_PROFILERDOMAINAGENT_H -#define HERMES_CDP_PROFILERDOMAINAGENT_H +#pragma once +#include #include #include -#include "DomainAgent.h" - namespace facebook { namespace hermes { namespace cdp { @@ -38,5 +36,3 @@ class ProfilerDomainAgent : public DomainAgent { } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_PROFILERDOMAINAGENT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/RemoteObjectConverters.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/RemoteObjectConverters.h index ae688884..93dfbedf 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/RemoteObjectConverters.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/RemoteObjectConverters.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_REMOTEOBJECTCONVERTERS_H -#define HERMES_CDP_REMOTEOBJECTCONVERTERS_H +#pragma once #include #include @@ -76,5 +75,3 @@ ExceptionDetails makeExceptionDetails( } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_REMOTEOBJECTCONVERTERS_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/RemoteObjectsTable.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/RemoteObjectsTable.h index 1b8fff5a..66e72164 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/RemoteObjectsTable.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/RemoteObjectsTable.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_REMOTEOBJECTSTABLE_H -#define HERMES_CDP_REMOTEOBJECTSTABLE_H +#pragma once #include #include @@ -126,5 +125,3 @@ class RemoteObjectsTable { } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_REMOTEOBJECTSTABLE_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/RuntimeDomainAgent.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/RuntimeDomainAgent.h index 9c8142aa..72cca3ee 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/RuntimeDomainAgent.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/cdp/RuntimeDomainAgent.h @@ -5,14 +5,13 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_CDP_RUNTIMEDOMAINAGENT_H -#define HERMES_CDP_RUNTIMEDOMAINAGENT_H +#pragma once #include -#include "CDPDebugAPI.h" -#include "DomainAgent.h" -#include "RemoteObjectConverters.h" +#include +#include +#include namespace facebook { namespace hermes { @@ -29,7 +28,7 @@ class RuntimeDomainAgent : public DomainAgent { RuntimeDomainAgent( int32_t executionContextID, HermesRuntime &runtime, - debugger::AsyncDebuggerAPI &asyncDebuggerAPI, + const debugger::AsyncDebuggerAPI &asyncDebuggerAPI, SynchronizedOutboundCallback messageCallback, std::shared_ptr objTable, ConsoleMessageStorage &consoleMessageStorage, @@ -115,7 +114,7 @@ class RuntimeDomainAgent : public DomainAgent { const ObjectSerializationOptions &serializationOptions); HermesRuntime &runtime_; - debugger::AsyncDebuggerAPI &asyncDebuggerAPI_; + const debugger::AsyncDebuggerAPI &asyncDebuggerAPI_; ConsoleMessageStorage &consoleMessageStorage_; ConsoleMessageDispatcher &consoleMessageDispatcher_; @@ -137,5 +136,3 @@ class RuntimeDomainAgent : public DomainAgent { } // namespace cdp } // namespace hermes } // namespace facebook - -#endif // HERMES_CDP_RUNTIMEDOMAINAGENT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/Dummy.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/Dummy.h new file mode 100644 index 00000000..af9cf2e7 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/Dummy.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook { +namespace hermes { + +/// Dummy extension for testing precompiled extension system. +/// Does nothing - just validates the multi-extension architecture. +/// +/// \param runtime The JSI runtime to install into. +/// \param extensions The precompiled extensions object containing setup +/// functions. +void installDummy(jsi::Runtime &runtime, jsi::Object &extensions); + +} // namespace hermes +} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/TimerStats.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/Extensions.h similarity index 59% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/TimerStats.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/Extensions.h index 6b3e84ec..de18a16b 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/TimerStats.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/Extensions.h @@ -9,15 +9,12 @@ #include -#include - namespace facebook { namespace hermes { -/// Creates and returns a Runtime that computes the time spent in invocations to -/// the Hermes VM. -std::unique_ptr makeTimedRuntime( - std::unique_ptr hermesRuntime); +/// Install all JSI extensions (TextEncoder, etc.) into the runtime. +/// The extensions object is passed in from the caller who loaded the bytecode. +void installExtensions(jsi::Runtime &rt, jsi::Object extensions); } // namespace hermes } // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/ExtensionsBytecode.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/ExtensionsBytecode.h new file mode 100644 index 00000000..fcb74829 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/ExtensionsBytecode.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include "llvh/ADT/ArrayRef.h" + +#include + +namespace facebook { +namespace hermes { + +/// Returns the precompiled bytecode for JSI extensions. +/// This bytecode, when executed, returns an object with setup functions +/// keyed by extension name. +llvh::ArrayRef getExtensionsBytecode(); + +} // namespace hermes +} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/Intrinsics.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/Intrinsics.h new file mode 100644 index 00000000..e65bc7a8 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/Intrinsics.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include "jsi/jsi.h" + +namespace facebook { +namespace hermes { + +/// Holds references to built-in JavaScript constructors captured at extension +/// initialization time. This ensures extensions use the original intrinsics +/// even if user code replaces the global properties. +struct ExtensionIntrinsics { + jsi::Function typeError; + jsi::Function rangeError; + jsi::Function uint8Array; + + /// Capture intrinsics from the runtime. Must be called before any user code + /// executes. + explicit ExtensionIntrinsics(jsi::Runtime &rt); +}; + +/// Capture and store intrinsics from the runtime. Must be called before any +/// user code executes. +void captureIntrinsics(jsi::Runtime &rt); + +/// Retrieve the stored intrinsics. Throws if captureIntrinsics was not called. +const ExtensionIntrinsics &getIntrinsics(jsi::Runtime &rt); + +/// Throw a TypeError with the given message. Uses the intrinsic TypeError +/// constructor captured at initialization time. +[[noreturn]] void throwTypeError(jsi::Runtime &rt, const char *message); + +/// Throw a RangeError with the given message. Uses the intrinsic RangeError +/// constructor captured at initialization time. +[[noreturn]] void throwRangeError(jsi::Runtime &rt, const char *message); + +} // namespace hermes +} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/JSIUtils.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/JSIUtils.h new file mode 100644 index 00000000..5412b50f --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/JSIUtils.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include "Intrinsics.h" + +#include "jsi/jsi.h" +#include "llvh/ADT/Optional.h" + +#include +#include +#include +#include + +namespace facebook { +namespace hermes { + +/// Result of getTypedArrayBuffer - the destination buffer info. +struct TypedArrayBufferInfo { + uint8_t *data; + size_t byteLength; +}; + +/// MutableBuffer implementation that owns a std::string of UTF-8 data. +class UTF8Buffer : public jsi::MutableBuffer { + public: + explicit UTF8Buffer(std::string &&data) : data_(std::move(data)) {} + + size_t size() const override { + return data_.size(); + } + + uint8_t *data() override { + return reinterpret_cast(data_.data()); + } + + private: + std::string data_; +}; + +/// Try to convert a jsi::Value to a valid unsigned integer of type T. +/// Returns llvh::None if the value is not a number, is NaN, negative, +/// not an integer, exceeds MAX_SAFE_INTEGER, or exceeds the range of T. +template +inline llvh::Optional valueToUnsigned(const jsi::Value &val) { + static_assert(std::is_unsigned::value, "T must be an unsigned type"); + if (!val.isNumber()) { + return llvh::None; + } + double d = val.asNumber(); + // Check non-negative and within MAX_SAFE_INTEGER (2^53 - 1), which is exactly + // representable as a double. This ensures d could be an exact integer. + constexpr double maxSafeInteger = 9007199254740991.0; // 2^53 - 1 + if (!(d >= 0 && d <= maxSafeInteger)) { + return llvh::None; + } + // Cast to uint64_t and verify no fractional part was lost. + auto u = static_cast(d); + if (static_cast(u) != d) { + return llvh::None; + } + if (u > std::numeric_limits::max()) { + return llvh::None; + } + return static_cast(u); +} + +/// Extract buffer info from a TypedArray-like object. +/// We use duck-typing (checking for buffer/byteOffset/byteLength) rather than +/// instanceof Uint8Array. This is more permissive than the spec requires, but +/// handles cross-realm Uint8Arrays and is consistent with JSI's portable +/// design. The original VM implementation used internal type checks. +/// Throws JSError if the object is not a valid TypedArray or is detached. +/// \param errorMessage The error message to use if the object is invalid. +/// \param detachedErrorMessage The error message to use if the buffer is +/// detached. +TypedArrayBufferInfo getTypedArrayBuffer( + jsi::Runtime &rt, + const jsi::Value &val, + const char *errorMessage, + const char *detachedErrorMessage); + +} // namespace hermes +} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/TextEncoder.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/TextEncoder.h new file mode 100644 index 00000000..465ebda6 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/TextEncoder.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook { +namespace hermes { + +/// Install the TextEncoder constructor on the global object. +/// This creates a proper TextEncoder class conforming to the WHATWG Encoding +/// Standard with: +/// - constructor (callable with 'new TextEncoder()') +/// - encoding getter (always returns "utf-8") +/// - encode(string) method returning Uint8Array +/// - encodeInto(string, Uint8Array) method returning {read, written} +/// +/// \param runtime The JSI runtime to install into. +/// \param extensions The precompiled extensions object containing setup +/// functions. +void installTextEncoder(jsi::Runtime &runtime, jsi::Object &extensions); + +} // namespace hermes +} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/Worker.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/Worker.h new file mode 100644 index 00000000..691723e0 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/Worker.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once +#ifdef JSI_UNSTABLE +#ifndef HERMES_EXTENSIONS_WORKER_H +#define HERMES_EXTENSIONS_WORKER_H + +#include + +namespace facebook { +namespace hermes { + +/// Install the Worker constructor on the global object. +/// \param runtime The JSI runtime to install into. +/// \param extensions The precompiled extensions object containing setup +/// functions. +void installWorker(jsi::Runtime &rt, jsi::Object &extensions); + +} // namespace hermes +} // namespace facebook + +#endif // HERMES_EXTENSIONS_WORKER_H +#endif // JSI_UNSTABLE diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/contrib/ContribDummy.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/contrib/ContribDummy.h new file mode 100644 index 00000000..d6c115ec --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/contrib/ContribDummy.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook { +namespace hermes { + +/// ContribDummy extension - example community contribution. +/// Does nothing - serves as a template for contrib extensions. +/// +/// \param runtime The JSI runtime to install into. +/// \param extensions The precompiled extensions object containing setup +/// functions. +void installContribDummy(jsi::Runtime &runtime, jsi::Object &extensions); + +} // namespace hermes +} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/contrib/ContribExtensions.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/contrib/ContribExtensions.h new file mode 100644 index 00000000..37638601 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/contrib/ContribExtensions.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook { +namespace hermes { + +/// Install all contrib (community-contributed) extensions into the runtime. +/// +/// \param runtime The JSI runtime to install into. +/// \param extensions The precompiled extensions object containing setup +/// functions. +void installContribExtensions(jsi::Runtime &runtime, jsi::Object &extensions); + +} // namespace hermes +} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/contrib/TextDecoder.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/contrib/TextDecoder.h new file mode 100644 index 00000000..63f0ad07 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/contrib/TextDecoder.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook { +namespace hermes { + +/// Install the TextDecoder constructor on the global object. +/// This creates a proper TextDecoder class conforming to the WHATWG Encoding +/// Standard with: +/// - constructor (callable with 'new TextDecoder(label, options)') +/// - encoding getter (returns the encoding name) +/// - fatal getter (returns the fatal flag) +/// - ignoreBOM getter (returns the ignoreBOM flag) +/// - decode(input, options) method returning a string +/// +/// \param runtime The JSI runtime to install into. +/// \param extensions The precompiled extensions object containing setup +/// functions. +void installTextDecoder(jsi::Runtime &runtime, jsi::Object &extensions); + +} // namespace hermes +} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/contrib/TextDecoderUtils.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/contrib/TextDecoderUtils.h new file mode 100644 index 00000000..4dd5e87b --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/extensions/contrib/TextDecoderUtils.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include "llvh/ADT/Optional.h" +#include "llvh/ADT/StringRef.h" + +#include +#include + +namespace facebook { +namespace hermes { + +// Encoding types supported by TextDecoder. isSingleByteEncoding and +// kSingleByteEncodings depend on the default enum values. +enum class TextDecoderEncoding : uint8_t { + UTF8, + UTF16LE, + UTF16BE, + IBM866, + ISO_8859_2, + ISO_8859_3, + ISO_8859_4, + ISO_8859_5, + ISO_8859_6, + ISO_8859_7, + ISO_8859_8, + ISO_8859_8_I, + ISO_8859_10, + ISO_8859_13, + ISO_8859_14, + ISO_8859_15, + ISO_8859_16, + KOI8_R, + KOI8_U, + Macintosh, + Windows874, + Windows1250, + Windows1251, + Windows1252, + Windows1253, + Windows1254, + Windows1255, + Windows1256, + Windows1257, + Windows1258, + XMacCyrillic, + _count, +}; + +enum class DecodeError { + None = 0, + InvalidSequence, // Invalid byte sequence (fatal mode) + InvalidSurrogate, // Invalid surrogate (fatal mode) + OddByteCount, // Odd byte count in UTF-16 (fatal mode) +}; + +// First single-byte encoding value. +static constexpr uint8_t kFirstSingleByteEncoding = + static_cast(TextDecoderEncoding::IBM866); + +// Number of single-byte encoding values +static constexpr uint8_t kNumSingleByteEncodings = + (uint8_t)TextDecoderEncoding::_count - kFirstSingleByteEncoding; + +inline bool isSingleByteEncoding(TextDecoderEncoding enc) { + return static_cast(enc) >= kFirstSingleByteEncoding; +} + +// Array of pointers to single-byte encoding tables, indexed by +// (TextDecoderEncoding - kFirstSingleByteEncoding). +extern const std::array + kSingleByteEncodings; + +// Parse the encoding label and return the corresponding encoding type. +// Returns llvh::None if the encoding is not supported. +llvh::Optional parseEncodingLabel(llvh::StringRef label); + +// Get the canonical encoding name for the given encoding type. +const char *getEncodingName(TextDecoderEncoding encoding); + +DecodeError decodeUTF8( + const uint8_t *bytes, + size_t length, + bool fatal, + bool ignoreBOM, + bool stream, + bool bomSeen, + std::u16string *decoded, + uint8_t outPendingBytes[4], + size_t *outPendingCount, + bool *outBOMSeen); + +DecodeError decodeUTF16( + const uint8_t *bytes, + size_t length, + bool fatal, + bool ignoreBOM, + bool bigEndian, + bool stream, + bool bomSeen, + std::u16string *decoded, + uint8_t outPendingBytes[4], + size_t *outPendingCount, + bool *outBOMSeen); + +} // namespace hermes +} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/hermes.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/hermes.h index 0d6d70fc..1a66be93 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/hermes.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/hermes.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_HERMES_H -#define HERMES_HERMES_H +#pragma once #include #include @@ -17,227 +16,201 @@ #include #include +#include +#include #include #include -#include "js_native_api.h" - struct HermesTestHelper; +struct SHUnit; +struct SHRuntime; namespace hermes { - namespace vm { - class GCExecTrace; - class Runtime; - } // namespace vm +namespace vm { +class GCExecTrace; +class Runtime; +class SerializedValue; +} // namespace vm } // namespace hermes namespace facebook { - namespace jsi { - - class ThreadSafeRuntime; - - } - - namespace hermes { - - namespace debugger { - class Debugger; - } - - class HermesRuntimeImpl; - -/// Represents a Hermes JS runtime. - class HERMES_EXPORT HermesRuntime : public jsi::Runtime { - public: - - napi_status createNapiEnv(napi_env *env); - - static bool isHermesBytecode(const uint8_t *data, size_t len); - // Returns the supported bytecode version. - static uint32_t getBytecodeVersion(); - // (EXPERIMENTAL) Issues madvise calls for portions of the given - // bytecode file that will likely be used when loading the bytecode - // file and running its global function. - static void prefetchHermesBytecode(const uint8_t *data, size_t len); - // Returns whether the data is valid HBC with more extensive checks than - // isHermesBytecode and returns why it isn't in errorMessage (if nonnull) - // if not. - static bool hermesBytecodeSanityCheck( - const uint8_t *data, - size_t len, - std::string *errorMessage = nullptr); - static void setFatalHandler(void (*handler)(const std::string &)); - - // Assuming that \p data is valid HBC bytecode data, returns a pointer to the - // first element of the epilogue, data append to the end of the bytecode - // stream. Return pair contain ptr to data and header. - static std::pair getBytecodeEpilogue( - const uint8_t *data, - size_t len); - - /// Enable sampling profiler. - /// Starts a separate thread that polls VM state with \p meanHzFreq frequency. - /// Any subsequent call to \c enableSamplingProfiler() is ignored until - /// next call to \c disableSamplingProfiler() - static void enableSamplingProfiler(double meanHzFreq = 100); - - /// Disable the sampling profiler - static void disableSamplingProfiler(); - - /// Dump sampled stack trace to the given file name. - static void dumpSampledTraceToFile(const std::string &fileName); - - /// Dump sampled stack trace to the given stream. - static void dumpSampledTraceToStream(std::ostream &stream); - - /// Serialize the sampled stack to the format expected by DevTools' - /// Profiler.stop return type. - void sampledTraceToStreamInDevToolsFormat(std::ostream &stream); - - /// Return the executed JavaScript function info. - /// This information holds the segmentID, Virtualoffset and sourceURL. - /// This information is needed specifically to be able to symbolicate non-CJS - /// bundles correctly. This API will be simplified later to simply return a - /// segmentID and virtualOffset, when we are able to only support CJS bundles. - static std::unordered_map> - getExecutedFunctions(); - - /// \return whether code coverage profiler is enabled or not. - static bool isCodeCoverageProfilerEnabled(); - - /// Enable code coverage profiler. - static void enableCodeCoverageProfiler(); - - /// Disable code coverage profiler. - static void disableCodeCoverageProfiler(); - - // The base class declares most of the interesting methods. This - // just declares new methods which are specific to HermesRuntime. - // The actual implementations of the pure virtual methods are - // provided by a class internal to the .cpp file, which is created - // by the factory. - - /// Load a new segment into the Runtime. - /// The \param context must be a valid RequireContext retrieved from JS - /// using `require.context`. - void loadSegment( - std::unique_ptr buffer, - const jsi::Value &context); - - /// Gets a guaranteed unique id for an Object (or, respectively, String - /// or PropNameId), which is assigned at allocation time and is - /// static throughout that object's (or string's, or PropNameID's) - /// lifetime. - uint64_t getUniqueID(const jsi::Object &o) const; - uint64_t getUniqueID(const jsi::BigInt &s) const; - uint64_t getUniqueID(const jsi::String &s) const; - uint64_t getUniqueID(const jsi::PropNameID &pni) const; - uint64_t getUniqueID(const jsi::Symbol &sym) const; - - /// Same as the other \c getUniqueID, except it can return 0 for some values. - /// 0 means there is no ID associated with the value. - uint64_t getUniqueID(const jsi::Value &val) const; - - /// From an ID retrieved from \p getUniqueID, go back to the object. - /// NOTE: This is much slower in general than the reverse operation, and takes - /// up more memory. Don't use this unless it's absolutely necessary. - /// \return a jsi::Object if a matching object is found, else returns null. - jsi::Value getObjectForID(uint64_t id); - - /// Get a structure representing the execution history (currently just of - /// GC, but will be generalized as necessary), to aid in debugging - /// non-deterministic execution. - const ::hermes::vm::GCExecTrace &getGCExecTrace() const; - - /// Get IO tracking (aka HBC page access) info as a JSON string. - /// See hermes::vm::Runtime::getIOTrackingInfoJSON() for conditions - /// needed for there to be useful output. - std::string getIOTrackingInfoJSON(); - -#ifdef HERMESVM_PROFILER_BB - /// Write the trace to the given stream. - void dumpBasicBlockProfileTrace(std::ostream &os) const; -#endif +namespace jsi { -#ifdef HERMESVM_PROFILER_OPCODE - /// Write the opcode stats to the given stream. - void dumpOpcodeStats(std::ostream &os) const; -#endif +class ThreadSafeRuntime; - /// \return a reference to the Debugger for this Runtime. - debugger::Debugger &getDebugger(); +} -#ifdef HERMES_ENABLE_DEBUGGER - - struct DebugFlags { - // Looking for the .lazy flag? It's no longer necessary. - // Source is evaluated lazily by default. See - // RuntimeConfig::CompilationMode. - }; +namespace hermes { - /// Evaluate the given code in an unoptimized form, - /// used for debugging. - void debugJavaScript( - const std::string &src, - const std::string &sourceURL, - const DebugFlags &debugFlags); +namespace debugger { +class Debugger; +} + +class HermesRuntime; +/// The Hermes Root API interface. This is the entry point to create the Hermes +/// runtime and to access Hermes-specific methods that do not rely on a runtime +/// instance. +class HERMES_EXPORT IHermesRootAPI : public jsi::ICast { + public: + static constexpr jsi::UUID uuid{ + 0xb654d898, + 0xdfad, + 0x11ef, + 0x859a, + 0x325096b39f47}; + + // Returns an instance of Hermes Runtime. + virtual std::unique_ptr makeHermesRuntime( + const ::hermes::vm::RuntimeConfig &runtimeConfig) = 0; + + virtual bool isHermesBytecode(const uint8_t *data, size_t len) = 0; + + // Returns the supported bytecode version. + virtual uint32_t getBytecodeVersion() = 0; + + // (EXPERIMENTAL) Issues madvise calls for portions of the given + // bytecode file that will likely be used when loading the bytecode + // file and running its global function. + virtual void prefetchHermesBytecode(const uint8_t *data, size_t len) = 0; + + // Returns whether the data is valid HBC with more extensive checks than + // isHermesBytecode and returns why it isn't in errorMessage (if nonnull) + // if not. + virtual bool hermesBytecodeSanityCheck( + const uint8_t *data, + size_t len, + std::string *errorMessage = nullptr) = 0; + + /// Sets a global fatal handler that is shared across all active Hermes + /// runtimes. Setting fatal handler in multiple places will override the + /// previous fatal handler set by this functionality. + /// The fatal handler must not throw exceptions, as Hermes is compiled without + /// exceptions. + virtual void setFatalHandler(void (*handler)(const std::string &)) = 0; + + // Assuming that \p data is valid HBC bytecode data, returns a pointer to the + // first element of the epilogue, data append to the end of the bytecode + // stream. Return pair contain ptr to data and header. + virtual std::pair getBytecodeEpilogue( + const uint8_t *data, + size_t len) = 0; + + /// Enable sampling profiler. + /// Starts a separate thread that polls VM state with \p meanHzFreq frequency. + /// Any subsequent call to \c enableSamplingProfiler() is ignored until + /// next call to \c disableSamplingProfiler() + virtual void enableSamplingProfiler(double meanHzFreq = 100) = 0; + + /// Disable the sampling profiler + virtual void disableSamplingProfiler() = 0; + + /// Dump sampled stack trace to the given file name. + virtual void dumpSampledTraceToFile(const std::string &fileName) = 0; + + /// Dump sampled stack trace to the given stream. + virtual void dumpSampledTraceToStream(std::ostream &stream) = 0; + + /// Return the executed JavaScript function info. + /// This information holds the segmentID, Virtualoffset and sourceURL. + /// This information is needed specifically to be able to symbolicate non-CJS + /// bundles correctly. This API will be simplified later to simply return a + /// segmentID and virtualOffset, when we are able to only support CJS bundles. + virtual std::unordered_map> + getExecutedFunctions() = 0; + + /// \return whether code coverage profiler is enabled or not. + virtual bool isCodeCoverageProfilerEnabled() = 0; + + /// Enable code coverage profiler. + virtual void enableCodeCoverageProfiler() = 0; + + /// Disable code coverage profiler. + virtual void disableCodeCoverageProfiler() = 0; + + protected: + /// The destructor is protected as delete calls on interfaces must not occur. + /// It is also non-virtual to simplify the v-table. + ~IHermesRootAPI() {} +}; + +/// The setFatalHandler functionality has global effects, which may cause +/// unintended or surprising behavior for users of this API. For this reason, it +/// is not recommended and the functionality is provided by the optional +/// interface ISetFatalHandler. +class HERMES_EXPORT ISetFatalHandler : public jsi::ICast { + public: + static constexpr jsi::UUID uuid{ + 0xda98a610, + 0x09cb, + 0x11f0, + 0x87bf, + 0x325096b39f47}; + /// Sets a global fatal handler that is shared across all active Hermes + /// runtimes. Setting fatal handler in multiple places will override the + /// previous fatal handler set by this functionality. + /// The fatal handler must not throw exceptions, as Hermes is compiled without + /// exceptions. + virtual void setFatalHandler(void (*handler)(const std::string &)) = 0; + + protected: + ~ISetFatalHandler() = default; +}; + +/// Interface for methods that are exposed for test purposes. +class HERMES_EXPORT IHermesTestHelpers : public jsi::ICast { + public: + static constexpr jsi::UUID uuid{ + 0x664e489a, + 0xf941, + 0x11ef, + 0xa44c, + 0x325096b39f47}; + + virtual size_t rootsListLengthForTests() const = 0; + + protected: + ~IHermesTestHelpers() = default; +}; + +#ifdef JSI_UNSTABLE +// Interface for methods that are exposed for tracing purposes. +class IHermesTracingHelpers : public jsi::ICast { + public: + static constexpr jsi::UUID uuid{ + 0x74ac2c4e, + 0xc660, + 0x11f0, + 0x8de9, + 0x0242ac120002}; + + // Returns the secret for obtaining the underlying SerializedValue object + virtual const ::hermes::vm::SerializedValue *getHermesSerializedValue( + const jsi::Serialized &serialized) const = 0; + virtual const std::shared_ptr makeSerialized( + ::hermes::vm::SerializedValue &value) const = 0; + + protected: + ~IHermesTracingHelpers() = default; +}; #endif - /// Register this runtime and thread for sampling profiler. Before using the - /// runtime on another thread, invoke this function again from the new thread - /// to make the sampling profiler target the new thread (and forget the old - /// thread). - void registerForProfiling(); - /// Unregister this runtime for sampling profiler. - void unregisterForProfiling(); - - /// Define methods to interrupt JS execution and set time limits. - /// All JS compiled to bytecode via prepareJS, or evaluateJS, will support - /// interruption and time limit monitoring if the runtime is configured with - /// AsyncBreakCheckInEval. If JS prepared in other ways is executed, care must - /// be taken to ensure that it is compiled in a mode that supports it (i.e., - /// the emitted code contains async break checks). - - /// Asynchronously terminates the current execution. This can be called on - /// any thread. - void asyncTriggerTimeout(); - - /// Register this runtime for execution time limit monitoring, with a time - /// limit of \p timeoutInMs milliseconds. - /// See compilation notes above. - void watchTimeLimit(uint32_t timeoutInMs); - /// Unregister this runtime for execution time limit monitoring. - void unwatchTimeLimit(); - - /// Same as \c evaluate JavaScript but with a source map, which will be - /// applied to exception traces and debug information. - /// - /// This is an experimental Hermes-specific API. In the future it may be - /// renamed, moved or combined with another API, but the provided - /// functionality will continue to be available in some form. - jsi::Value evaluateJavaScriptWithSourceMap( - const std::shared_ptr &buffer, - const std::shared_ptr &sourceMapBuf, - const std::string &sourceURL); - - /// Returns the underlying low level Hermes VM runtime instance. - /// This function is considered unsafe and unstable. - /// Direct use of a vm::Runtime should be avoided as the lower level APIs are - /// unsafe and they can change without notice. - ::hermes::vm::Runtime *getVMRuntimeUnsafe() const; - - private: - // Only HermesRuntimeImpl can subclass this. - HermesRuntime() = default; - friend class HermesRuntimeImpl; - - friend struct ::HermesTestHelper; - size_t rootsListLengthForTests() const; - - // Do not add any members here. This ensures that there are no - // object size inconsistencies. All data should be in the impl - // class in the .cpp file. - }; +class HermesRuntime : public jsi::Runtime, + public IHermes, + public IHermesSHUnit { + public: + /// Similar to jsi::Runtime, HermesRuntime is treated as an object, rather + /// than a pure interface. This is to prevent breaking usages of + /// HermesRuntime prior to the introduction of jsi::IRuntime, IHermes, and + /// other interfaces. + ~HermesRuntime() override = default; + + using jsi::Runtime::castInterface; +}; + +/// Returns a pointer to an object that can be cast into IHermesRootAPI, which +/// can be used to create a Hermes runtime and to access global Hermes-specific +/// methods. This object has static lifetime. +HERMES_EXPORT jsi::ICast *makeHermesRootAPI(); /// Return a RuntimeConfig that is more suited for running untrusted JS than /// the default config. Disables some language features and may trade off some @@ -248,16 +221,22 @@ namespace facebook { /// conf.withArrayBuffer(true); /// ... /// auto runtime = makeHermesRuntime(conf.build()); - HERMES_EXPORT ::hermes::vm::RuntimeConfig hardenedHermesRuntimeConfig(); - - HERMES_EXPORT std::unique_ptr makeHermesRuntime( - const ::hermes::vm::RuntimeConfig &runtimeConfig = - ::hermes::vm::RuntimeConfig()); - HERMES_EXPORT std::unique_ptr - makeThreadSafeHermesRuntime( - const ::hermes::vm::RuntimeConfig &runtimeConfig = - ::hermes::vm::RuntimeConfig()); - } // namespace hermes +HERMES_EXPORT ::hermes::vm::RuntimeConfig hardenedHermesRuntimeConfig(); + +HERMES_EXPORT std::unique_ptr makeHermesRuntime( + const ::hermes::vm::RuntimeConfig &runtimeConfig = + ::hermes::vm::RuntimeConfig()); + +/// Create a HermesRuntime for the given config without throwing any exceptions. +/// This is safe to be called from code that is compiled without exceptions. +/// Returns nullptr on failure. +HERMES_EXPORT std::unique_ptr makeHermesRuntimeNoThrow( + const ::hermes::vm::RuntimeConfig &runtimeConfig = + ::hermes::vm::RuntimeConfig()) noexcept; + +HERMES_EXPORT std::unique_ptr +makeThreadSafeHermesRuntime( + const ::hermes::vm::RuntimeConfig &runtimeConfig = + ::hermes::vm::RuntimeConfig()); +} // namespace hermes } // namespace facebook - -#endif \ No newline at end of file diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/hermes_api.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/hermes_api.h deleted file mode 100644 index f0e616f8..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/hermes_api.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_HERMES_API_H -#define HERMES_HERMES_API_H - -#include "js_runtime.h" - -EXTERN_C_START - -typedef struct hermes_local_connection_s *hermes_local_connection; -typedef struct hermes_remote_connection_s *hermes_remote_connection; - -//============================================================================= -// jsr_runtime -//============================================================================= - -JSR_API hermes_dump_crash_data(jsr_runtime runtime, int32_t fd); -JSR_API hermes_sampling_profiler_enable(); -JSR_API hermes_sampling_profiler_disable(); -JSR_API hermes_sampling_profiler_add(jsr_runtime runtime); -JSR_API hermes_sampling_profiler_remove(jsr_runtime runtime); -JSR_API hermes_sampling_profiler_dump_to_file(const char *filename); - -//============================================================================= -// jsr_config -//============================================================================= - -JSR_API hermes_config_enable_default_crash_handler( - jsr_config config, - bool value); - -//============================================================================= -// Setting inspector singleton -//============================================================================= - -typedef int32_t(NAPI_CDECL *hermes_inspector_add_page_cb)( - const char *title, - const char *vm, - void *connectFunc); - -typedef void(NAPI_CDECL *hermes_inspector_remove_page_cb)(int32_t page_id); - -JSR_API hermes_set_inspector( - hermes_inspector_add_page_cb add_page_cb, - hermes_inspector_remove_page_cb remove_page_cb); - -//============================================================================= -// Local and remote inspector connections. -// Local is defined in Hermes VM, Remote is defined by inspector outside of VM. -//============================================================================= - -typedef void(NAPI_CDECL *hermes_remote_connection_send_message_cb)( - hermes_remote_connection remote_connection, - const char *message); - -typedef void(NAPI_CDECL *hermes_remote_connection_disconnect_cb)( - hermes_remote_connection remote_connection); - -JSR_API hermes_create_local_connection( - void *connect_func, - hermes_remote_connection remote_connection, - hermes_remote_connection_send_message_cb on_send_message_cb, - hermes_remote_connection_disconnect_cb on_disconnect_cb, - jsr_data_delete_cb on_delete_cb, - void *deleter_data, - hermes_local_connection *local_connection); - -JSR_API hermes_delete_local_connection( - hermes_local_connection local_connection); - -JSR_API hermes_local_connection_send_message( - hermes_local_connection local_connection, - const char *message); - -JSR_API hermes_local_connection_disconnect( - hermes_local_connection local_connection); - -EXTERN_C_END - -#endif // !HERMES_HERMES_API_H \ No newline at end of file diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/hermes_tracing.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/hermes_tracing.h index 470e82d9..6e30607a 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/hermes_tracing.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/hermes_tracing.h @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#ifndef HERMES_HERMES_TRACING_H -#define HERMES_HERMES_TRACING_H +#pragma once #include @@ -30,8 +29,8 @@ namespace hermes { /// The return value of \p traceCompletionCallback indicates whether the /// invocation completed successfully. If \p traceCompletionCallback is null, it /// also assumes as if the callback is successful. -std::unique_ptr makeTracingHermesRuntime( - std::unique_ptr hermesRuntime, +std::shared_ptr makeTracingHermesRuntime( + std::shared_ptr hermesRuntime, const ::hermes::vm::RuntimeConfig &runtimeConfig, const std::string &traceScratchPath, const std::string &traceResultPath, @@ -43,13 +42,11 @@ std::unique_ptr makeTracingHermesRuntime( /// \p traceStream the stream to write trace to. /// \p forReplay indicates whether the runtime is being used in trace replay and /// tracing. -std::unique_ptr makeTracingHermesRuntime( - std::unique_ptr hermesRuntime, +std::shared_ptr makeTracingHermesRuntime( + std::shared_ptr hermesRuntime, const ::hermes::vm::RuntimeConfig &runtimeConfig, std::unique_ptr traceStream, bool forReplay = false); } // namespace hermes } // namespace facebook - -#endif diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/RuntimeAdapter.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/RuntimeAdapter.h deleted file mode 100644 index 64396f2c..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/RuntimeAdapter.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -#include - -#ifndef INSPECTOR_EXPORT -#ifdef _MSC_VER -#ifdef CREATE_SHARED_LIBRARY -#define INSPECTOR_EXPORT __declspec(dllexport) -#else -#define INSPECTOR_EXPORT -#endif // CREATE_SHARED_LIBRARY -#else // _MSC_VER -#define INSPECTOR_EXPORT __attribute__((visibility("default"))) -#endif // _MSC_VER -#endif // !defined(INSPECTOR_EXPORT) - -namespace facebook { -namespace hermes { -namespace inspector_modern { - -/** - * RuntimeAdapter encapsulates a HermesRuntime object. The underlying Hermes - * runtime object should stay alive for at least as long as the RuntimeAdapter - * is alive. - */ -class INSPECTOR_EXPORT RuntimeAdapter { - public: - virtual ~RuntimeAdapter() = 0; - - /// getRuntime should return the runtime encapsulated by this adapter. The - /// CDP Handler will only invoke this function from the runtime thread. - virtual HermesRuntime &getRuntime() = 0; - - /// \p tickleJs is a method that subclasses can choose to override to make - /// the inspector more responsive. If overridden, it should call the - /// \p __tickleJs JavaScript function. Calling JavaScript functions must be - /// done on the runtime thread, and \p tickleJs() may be invoked from an - /// arbitrary thread. Thus, the call to \p __tickleJs should occur with - /// appropriate locking (e.g. via a thread-safe runtime instance, or by - /// enqueuing the call on to a dedicated JS thread). - /// - /// This makes the inspector more responsive because it gives the inspector - /// the ability to force the process to enter the Hermes interpreter loop - /// soon. This is important because the inspector can only do a number of - /// important operations (like manipulating breakpoints) within the context of - /// a Hermes interperter loop. - /// - /// The default implementation does nothing. - virtual void tickleJs(); -}; - -/** - * SharedRuntimeAdapter is a simple implementation of RuntimeAdapter that - * uses shared_ptr to hold on to the runtime. It's generally only used in tests, - * since it does not implement tickleJs. - */ -class INSPECTOR_EXPORT SharedRuntimeAdapter : public RuntimeAdapter { - public: - SharedRuntimeAdapter(std::shared_ptr runtime); - ~SharedRuntimeAdapter() override; - - HermesRuntime &getRuntime() override; - - private: - std::shared_ptr runtime_; -}; - -} // namespace inspector_modern -} // namespace hermes -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/CDPHandler.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/CDPHandler.h deleted file mode 100644 index 01fe26eb..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/CDPHandler.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -// using include guards instead of #pragma once due to compile issues -// with MSVC and BUCK -#ifndef HERMES_INSPECTOR_CDPHANDLER_H -#define HERMES_INSPECTOR_CDPHANDLER_H - -#include -#include -#include -#include - -#include -#include - -namespace facebook { -namespace hermes { -namespace inspector_modern { -namespace chrome { - -using CDPMessageCallbackFunction = std::function; -using OnUnregisterFunction = std::function; - -class CDPHandlerImpl; - -struct State; - -/// Utility struct to configure the initial state of the CDP session. -struct INSPECTOR_EXPORT CDPHandlerSessionConfig { - bool isRuntimeDomainEnabled{false}; -}; - -/// Configuration for the execution context managed by the CDPHandler. -struct INSPECTOR_EXPORT CDPHandlerExecutionContextDescription { - int32_t id{}; - std::string origin; - std::string name; - std::optional auxData; - bool shouldSendNotifications{}; -}; - -/// CDPHandler processes CDP messages between the client and the debugger. -/// It performs no networking or connection logic itself. -/// The CDP Handler is invoked from multiple threads. The locking strategy is -/// to acquire the lock at each entry point into the class, and hold it until -/// the entry function has returned. In practice, these functions fall into 2 -/// categories: public functions invoked by the creator of this instance, and -/// callbacks invoked by the runtime to report events. -/// Once the lock is held, most members are safe to use from any thread, with -/// the notable exception of the runtime (and debugger retrieved from the -/// runtime). Most runtime methods must only be invoked when running on the -/// runtime thread, which occurs in the CDP Handler constructor/destructor, and -/// callbacks from the runtime thread (e.g. host functions, instrumentation -/// callbacks, and pause callback). -class INSPECTOR_EXPORT CDPHandler { - /// Hide the constructor so users can only construct via static create - /// methods. - CDPHandler( - std::unique_ptr adapter, - const std::string &title, - bool waitForDebugger, - bool processConsoleAPI, - std::shared_ptr state, - const CDPHandlerSessionConfig &sessionConfig, - std::optional - executionContextDescription); - - public: - /// Creating a CDPHandler enables the debugger on the provided runtime. This - /// should generally called before you start running any JS in the runtime. - /// This should also be called on the runtime thread, as methods are invoked - /// on the given \p adapter. - static std::shared_ptr create( - std::unique_ptr adapter, - bool waitForDebugger = false, - bool processConsoleAPI = true, - std::shared_ptr state = nullptr, - const CDPHandlerSessionConfig &sessionConfig = {}, - std::optional - executionContextDescription = std::nullopt); - /// Temporarily kept to allow React Native build to still work - static std::shared_ptr create( - std::unique_ptr adapter, - const std::string &title, - bool waitForDebugger = false, - bool processConsoleAPI = true, - std::shared_ptr state = nullptr, - const CDPHandlerSessionConfig &sessionConfig = {}, - std::optional - executionContextDescription = std::nullopt); - ~CDPHandler(); - - /// getTitle returns the name of the friendly name of the runtime that's shown - /// to users in the CDP frontend (e.g. Chrome DevTools). - std::string getTitle() const; - - /// Provide a callback to receive replies and notifications from the debugger, - /// and optionally provide a function to be called during - /// unregisterCallbacks(). - /// \param msgCallback Function to receive replies and notifications from the - /// debugger - /// \param onDisconnect Function that will be invoked upon calling - /// unregisterCallbacks - /// \return true if there wasn't a previously registered callback - bool registerCallbacks( - CDPMessageCallbackFunction msgCallback, - OnUnregisterFunction onUnregister); - - /// Unregister any previously registered callbacks. - /// \return true if there were previously registered callbacks - bool unregisterCallbacks(); - - /// Process a JSON-encoded Chrome DevTools Protocol request. - void handle(std::string str); - - /// Extract state to be persisted across reloads. - std::unique_ptr getState(); - - private: - std::shared_ptr impl_; - const std::string title_; -}; - -/// Public-facing wrapper for internal CDP state that can be preserved across -/// reloads. -struct INSPECTOR_EXPORT State { - /// Incomplete type that stores the actual state. - struct Private; - - /// Create a new wrapper with the provided \p privateState. - explicit State(std::unique_ptr privateState); - ~State(); - - /// Get the wrapped state. - Private &get() { - return *privateState_.get(); - } - - private: - /// Pointer to the actual stored state, hidden from users of this wrapper. - std::unique_ptr privateState_; -}; - -} // namespace chrome -} // namespace inspector_modern -} // namespace hermes -} // namespace facebook - -#endif // HERMES_INSPECTOR_CDPHandler_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/CallbackOStream.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/CallbackOStream.h deleted file mode 100644 index a9831555..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/CallbackOStream.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include -#include - -namespace facebook { -namespace hermes { -namespace inspector_modern { -namespace chrome { - -/// Subclass of \c std::ostream where flushing is implemented through a -/// callback. Writes are collected in a buffer. When filled, the buffer's -/// contents are emptied out and sent to a callback. -struct CallbackOStream : public std::ostream { - /// Signature of callback called to flush buffer contents. Accepts the buffer - /// as a string. Returns a boolean indicating whether flushing succeeded. - /// Callback failure will be translated to stream failure. If the callback - /// throws an exception it will be swallowed and translated into stream - /// failure. - using Fn = std::function; - - /// Construct a new stream. - /// - /// \p sz The size of the buffer -- how large it can get before it must be - /// flushed. Must be non-zero. - /// \p cb The callback function. - CallbackOStream(size_t sz, Fn cb); - - /// This class is neither movable nor copyable. - CallbackOStream(CallbackOStream &&that) = delete; - CallbackOStream &operator=(CallbackOStream &&that) = delete; - CallbackOStream(const CallbackOStream &that) = delete; - CallbackOStream &operator=(const CallbackOStream &that) = delete; - - private: - /// \c std::streambuf sub-class backed by a std::string buffer and - /// implementing overflow by calling a callback. - struct StreamBuf : public std::streambuf { - /// Construct a new streambuf. Parameters are the same as those of - /// \c CallbackOStream . - StreamBuf(size_t sz, Fn cb); - - /// Destruction will flush any remaining buffer contents. - ~StreamBuf() override; - - /// StreamBufs are not copyable, to avoid the flush callback receiving - /// the contents of multiple streams. - StreamBuf(const StreamBuf &) = delete; - StreamBuf &operator=(const StreamBuf &) = delete; - - protected: - /// std::streambuf overrides - int_type overflow(int_type ch) override; - int sync() override; - - private: - /// The size of the backing buffer. Fixed for an instance of the streambuf. - size_t sz_; - - /// The backing buffer that writes will go to until full. - std::unique_ptr buf_; - - /// The function called when buf_ has been filled. - Fn cb_; - - /// Clears the backing buffer. - void reset(); - - /// Clears the backing buffer and returns it contents in a string. - std::string take(); - }; - - StreamBuf sbuf_; -}; - -} // namespace chrome -} // namespace inspector_modern -} // namespace hermes -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/JSONValueInterfaces.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/JSONValueInterfaces.h deleted file mode 100644 index 26331381..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/JSONValueInterfaces.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include - -#include - -namespace facebook { -namespace hermes { -namespace inspector_modern { -namespace chrome { -using namespace ::hermes::parser; - -/// Convert a string to a JSONValue. Will return nullopt if parsing is not -/// successful. -std::optional parseStr( - const std::string &str, - JSONFactory &factory); - -/// Convert a string to a JSON object. Will return nullopt if parsing is not -/// successful, or the resulting JSON value is not an object. -std::optional parseStrAsJsonObj( - const std::string &str, - JSONFactory &factory); - -/// Convert a JSONValue to a string. -std::string jsonValToStr(const JSONValue *v); - -/// Check if two JSONValues are equal. -bool jsonValsEQ(const JSONValue *A, const JSONValue *B); - -}; // namespace chrome -}; // namespace inspector_modern -}; // namespace hermes -}; // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/MessageConverters.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/MessageConverters.h deleted file mode 100644 index fd26c9ed..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/MessageConverters.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include - -#include -#include -#include - -namespace facebook { -namespace hermes { -namespace inspector_modern { -namespace chrome { -namespace message { - -template -void setChromeLocation( - T &chromeLoc, - const facebook::hermes::debugger::SourceLocation &hermesLoc) { - if (hermesLoc.line != facebook::hermes::debugger::kInvalidLocation) { - chromeLoc.lineNumber = hermesLoc.line - 1; - } - - if (hermesLoc.column != facebook::hermes::debugger::kInvalidLocation) { - chromeLoc.columnNumber = hermesLoc.column - 1; - } -} - -/// ErrorCode magic numbers match JSC's (see InspectorBackendDispatcher.cpp) -enum class ErrorCode { - ParseError = -32700, - InvalidRequest = -32600, - MethodNotFound = -32601, - InvalidParams = -32602, - InternalError = -32603, - ServerError = -32000 -}; - -ErrorResponse -makeErrorResponse(int id, ErrorCode code, const std::string &message); - -OkResponse makeOkResponse(int id); - -namespace debugger { - -Location makeLocation(const facebook::hermes::debugger::SourceLocation &loc); - -} // namespace debugger - -namespace runtime { - -CallFrame makeCallFrame(const facebook::hermes::debugger::CallFrameInfo &info); - -std::vector makeCallFrames( - const facebook::hermes::debugger::StackTrace &stackTrace); - -ExceptionDetails makeExceptionDetails( - const facebook::hermes::debugger::ExceptionDetails &details); - -} // namespace runtime - -namespace heapProfiler { - -std::unique_ptr makeSamplingHeapProfile( - const std::string &value); - -} // namespace heapProfiler - -namespace profiler { - -std::unique_ptr makeProfile(const std::string &value); - -} // namespace profiler - -} // namespace message -} // namespace chrome -} // namespace inspector_modern -} // namespace hermes -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/MessageInterfaces.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/MessageInterfaces.h deleted file mode 100644 index 01e369e2..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/MessageInterfaces.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include - -#include -#include - -namespace facebook { -namespace hermes { -namespace inspector_modern { -namespace chrome { -namespace message { -using namespace ::hermes::parser; - -struct RequestHandler; - -/// Serializable is an interface for objects that can be serialized to and from -/// JSON. -struct Serializable { - virtual ~Serializable() = default; - virtual JSONValue *toJsonVal(JSONFactory &factory) const = 0; - - std::string toJsonStr() const; -}; - -/// Requests are sent from the debugger to the target. -struct Request : public Serializable { - using ParseResult = std::variant, std::string>; - static std::unique_ptr fromJson(const std::string &str); - - Request() = default; - explicit Request(std::string method) : method(method) {} - - // accept dispatches to the appropriate handler method in RequestHandler based - // on the type of the request. - virtual void accept(RequestHandler &handler) const = 0; - - long long id = 0; - std::string method; -}; - -/// Responses are sent from the target to the debugger in response to a Request. -struct Response : public Serializable { - Response() = default; - - long long id = 0; -}; - -/// Notifications are sent from the target to the debugger. This is used to -/// notify the debugger about events that occur in the target, e.g. stopping -/// at a breakpoint. -struct Notification : public Serializable { - Notification() = default; - explicit Notification(std::string method) : method(method) {} - - std::string method; -}; - -} // namespace message -} // namespace chrome -} // namespace inspector_modern -} // namespace hermes -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/MessageTypes.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/MessageTypes.h deleted file mode 100644 index e039758f..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/MessageTypes.h +++ /dev/null @@ -1,1183 +0,0 @@ -// Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved. -// @generated SignedSource<<3ebea508f76e06269045891097f89eb5>> - -#pragma once - -#include -#include - -#include -#include - -namespace facebook { -namespace hermes { -namespace inspector_modern { -namespace chrome { -namespace message { - -template -void deleter(T *p); -using JSONBlob = std::string; -struct UnknownRequest; - -namespace debugger { -using BreakpointId = std::string; -struct BreakpointResolvedNotification; -struct CallFrame; -using CallFrameId = std::string; -struct DisableRequest; -struct EnableRequest; -struct EvaluateOnCallFrameRequest; -struct EvaluateOnCallFrameResponse; -struct Location; -struct PauseRequest; -struct PausedNotification; -struct RemoveBreakpointRequest; -struct ResumeRequest; -struct ResumedNotification; -struct Scope; -struct ScriptParsedNotification; -struct SetBreakpointByUrlRequest; -struct SetBreakpointByUrlResponse; -struct SetBreakpointRequest; -struct SetBreakpointResponse; -struct SetBreakpointsActiveRequest; -struct SetInstrumentationBreakpointRequest; -struct SetInstrumentationBreakpointResponse; -struct SetPauseOnExceptionsRequest; -struct StepIntoRequest; -struct StepOutRequest; -struct StepOverRequest; -} // namespace debugger - -namespace runtime { -struct CallArgument; -struct CallFrame; -struct CallFunctionOnRequest; -struct CallFunctionOnResponse; -struct CompileScriptRequest; -struct CompileScriptResponse; -struct ConsoleAPICalledNotification; -struct CustomPreview; -struct DisableRequest; -struct EnableRequest; -struct EntryPreview; -struct EvaluateRequest; -struct EvaluateResponse; -struct ExceptionDetails; -struct ExecutionContextCreatedNotification; -struct ExecutionContextDescription; -using ExecutionContextId = long long; -struct GetHeapUsageRequest; -struct GetHeapUsageResponse; -struct GetPropertiesRequest; -struct GetPropertiesResponse; -struct GlobalLexicalScopeNamesRequest; -struct GlobalLexicalScopeNamesResponse; -struct InternalPropertyDescriptor; -struct ObjectPreview; -struct PropertyDescriptor; -struct PropertyPreview; -struct RemoteObject; -using RemoteObjectId = std::string; -struct RunIfWaitingForDebuggerRequest; -using ScriptId = std::string; -struct StackTrace; -using Timestamp = double; -using UnserializableValue = std::string; -} // namespace runtime - -namespace heapProfiler { -struct AddHeapSnapshotChunkNotification; -struct CollectGarbageRequest; -struct GetHeapObjectIdRequest; -struct GetHeapObjectIdResponse; -struct GetObjectByHeapObjectIdRequest; -struct GetObjectByHeapObjectIdResponse; -using HeapSnapshotObjectId = std::string; -struct HeapStatsUpdateNotification; -struct LastSeenObjectIdNotification; -struct ReportHeapSnapshotProgressNotification; -struct SamplingHeapProfile; -struct SamplingHeapProfileNode; -struct SamplingHeapProfileSample; -struct StartSamplingRequest; -struct StartTrackingHeapObjectsRequest; -struct StopSamplingRequest; -struct StopSamplingResponse; -struct StopTrackingHeapObjectsRequest; -struct TakeHeapSnapshotRequest; -} // namespace heapProfiler - -namespace profiler { -struct PositionTickInfo; -struct Profile; -struct ProfileNode; -struct StartRequest; -struct StopRequest; -struct StopResponse; -} // namespace profiler - -/// RequestHandler handles requests via the visitor pattern. -struct RequestHandler { - virtual ~RequestHandler() = default; - - virtual void handle(const UnknownRequest &req) = 0; - virtual void handle(const debugger::DisableRequest &req) = 0; - virtual void handle(const debugger::EnableRequest &req) = 0; - virtual void handle(const debugger::EvaluateOnCallFrameRequest &req) = 0; - virtual void handle(const debugger::PauseRequest &req) = 0; - virtual void handle(const debugger::RemoveBreakpointRequest &req) = 0; - virtual void handle(const debugger::ResumeRequest &req) = 0; - virtual void handle(const debugger::SetBreakpointRequest &req) = 0; - virtual void handle(const debugger::SetBreakpointByUrlRequest &req) = 0; - virtual void handle(const debugger::SetBreakpointsActiveRequest &req) = 0; - virtual void handle( - const debugger::SetInstrumentationBreakpointRequest &req) = 0; - virtual void handle(const debugger::SetPauseOnExceptionsRequest &req) = 0; - virtual void handle(const debugger::StepIntoRequest &req) = 0; - virtual void handle(const debugger::StepOutRequest &req) = 0; - virtual void handle(const debugger::StepOverRequest &req) = 0; - virtual void handle(const heapProfiler::CollectGarbageRequest &req) = 0; - virtual void handle(const heapProfiler::GetHeapObjectIdRequest &req) = 0; - virtual void handle( - const heapProfiler::GetObjectByHeapObjectIdRequest &req) = 0; - virtual void handle(const heapProfiler::StartSamplingRequest &req) = 0; - virtual void handle( - const heapProfiler::StartTrackingHeapObjectsRequest &req) = 0; - virtual void handle(const heapProfiler::StopSamplingRequest &req) = 0; - virtual void handle( - const heapProfiler::StopTrackingHeapObjectsRequest &req) = 0; - virtual void handle(const heapProfiler::TakeHeapSnapshotRequest &req) = 0; - virtual void handle(const profiler::StartRequest &req) = 0; - virtual void handle(const profiler::StopRequest &req) = 0; - virtual void handle(const runtime::CallFunctionOnRequest &req) = 0; - virtual void handle(const runtime::CompileScriptRequest &req) = 0; - virtual void handle(const runtime::DisableRequest &req) = 0; - virtual void handle(const runtime::EnableRequest &req) = 0; - virtual void handle(const runtime::EvaluateRequest &req) = 0; - virtual void handle(const runtime::GetHeapUsageRequest &req) = 0; - virtual void handle(const runtime::GetPropertiesRequest &req) = 0; - virtual void handle(const runtime::GlobalLexicalScopeNamesRequest &req) = 0; - virtual void handle(const runtime::RunIfWaitingForDebuggerRequest &req) = 0; -}; - -/// NoopRequestHandler can be subclassed to only handle some requests. -struct NoopRequestHandler : public RequestHandler { - void handle(const UnknownRequest &req) override {} - void handle(const debugger::DisableRequest &req) override {} - void handle(const debugger::EnableRequest &req) override {} - void handle(const debugger::EvaluateOnCallFrameRequest &req) override {} - void handle(const debugger::PauseRequest &req) override {} - void handle(const debugger::RemoveBreakpointRequest &req) override {} - void handle(const debugger::ResumeRequest &req) override {} - void handle(const debugger::SetBreakpointRequest &req) override {} - void handle(const debugger::SetBreakpointByUrlRequest &req) override {} - void handle(const debugger::SetBreakpointsActiveRequest &req) override {} - void handle( - const debugger::SetInstrumentationBreakpointRequest &req) override {} - void handle(const debugger::SetPauseOnExceptionsRequest &req) override {} - void handle(const debugger::StepIntoRequest &req) override {} - void handle(const debugger::StepOutRequest &req) override {} - void handle(const debugger::StepOverRequest &req) override {} - void handle(const heapProfiler::CollectGarbageRequest &req) override {} - void handle(const heapProfiler::GetHeapObjectIdRequest &req) override {} - void handle( - const heapProfiler::GetObjectByHeapObjectIdRequest &req) override {} - void handle(const heapProfiler::StartSamplingRequest &req) override {} - void handle( - const heapProfiler::StartTrackingHeapObjectsRequest &req) override {} - void handle(const heapProfiler::StopSamplingRequest &req) override {} - void handle( - const heapProfiler::StopTrackingHeapObjectsRequest &req) override {} - void handle(const heapProfiler::TakeHeapSnapshotRequest &req) override {} - void handle(const profiler::StartRequest &req) override {} - void handle(const profiler::StopRequest &req) override {} - void handle(const runtime::CallFunctionOnRequest &req) override {} - void handle(const runtime::CompileScriptRequest &req) override {} - void handle(const runtime::DisableRequest &req) override {} - void handle(const runtime::EnableRequest &req) override {} - void handle(const runtime::EvaluateRequest &req) override {} - void handle(const runtime::GetHeapUsageRequest &req) override {} - void handle(const runtime::GetPropertiesRequest &req) override {} - void handle(const runtime::GlobalLexicalScopeNamesRequest &req) override {} - void handle(const runtime::RunIfWaitingForDebuggerRequest &req) override {} -}; - -/// Types -struct debugger::Location : public Serializable { - Location() = default; - Location(Location &&) = default; - Location(const Location &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - Location &operator=(const Location &) = delete; - Location &operator=(Location &&) = default; - - runtime::ScriptId scriptId{}; - long long lineNumber{}; - std::optional columnNumber; -}; - -struct runtime::PropertyPreview : public Serializable { - PropertyPreview() = default; - PropertyPreview(PropertyPreview &&) = default; - PropertyPreview(const PropertyPreview &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - PropertyPreview &operator=(const PropertyPreview &) = delete; - PropertyPreview &operator=(PropertyPreview &&) = default; - - std::string name; - std::string type; - std::optional value; - std::unique_ptr< - runtime::ObjectPreview, - std::function> - valuePreview{nullptr, deleter}; - std::optional subtype; -}; - -struct runtime::EntryPreview : public Serializable { - EntryPreview() = default; - EntryPreview(EntryPreview &&) = default; - EntryPreview(const EntryPreview &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - EntryPreview &operator=(const EntryPreview &) = delete; - EntryPreview &operator=(EntryPreview &&) = default; - - std::unique_ptr< - runtime::ObjectPreview, - std::function> - key{nullptr, deleter}; - std::unique_ptr< - runtime::ObjectPreview, - std::function> - value{nullptr, deleter}; -}; - -struct runtime::ObjectPreview : public Serializable { - ObjectPreview() = default; - ObjectPreview(ObjectPreview &&) = default; - ObjectPreview(const ObjectPreview &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - ObjectPreview &operator=(const ObjectPreview &) = delete; - ObjectPreview &operator=(ObjectPreview &&) = default; - - std::string type; - std::optional subtype; - std::optional description; - bool overflow{}; - std::vector properties; - std::optional> entries; -}; - -struct runtime::CustomPreview : public Serializable { - CustomPreview() = default; - CustomPreview(CustomPreview &&) = default; - CustomPreview(const CustomPreview &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - CustomPreview &operator=(const CustomPreview &) = delete; - CustomPreview &operator=(CustomPreview &&) = default; - - std::string header; - std::optional bodyGetterId; -}; - -struct runtime::RemoteObject : public Serializable { - RemoteObject() = default; - RemoteObject(RemoteObject &&) = default; - RemoteObject(const RemoteObject &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - RemoteObject &operator=(const RemoteObject &) = delete; - RemoteObject &operator=(RemoteObject &&) = default; - - std::string type; - std::optional subtype; - std::optional className; - std::optional value; - std::optional unserializableValue; - std::optional description; - std::optional objectId; - std::optional preview; - std::optional customPreview; -}; - -struct runtime::CallFrame : public Serializable { - CallFrame() = default; - CallFrame(CallFrame &&) = default; - CallFrame(const CallFrame &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - CallFrame &operator=(const CallFrame &) = delete; - CallFrame &operator=(CallFrame &&) = default; - - std::string functionName; - runtime::ScriptId scriptId{}; - std::string url; - long long lineNumber{}; - long long columnNumber{}; -}; - -struct runtime::StackTrace : public Serializable { - StackTrace() = default; - StackTrace(StackTrace &&) = default; - StackTrace(const StackTrace &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - StackTrace &operator=(const StackTrace &) = delete; - StackTrace &operator=(StackTrace &&) = default; - - std::optional description; - std::vector callFrames; - std::unique_ptr parent; -}; - -struct runtime::ExceptionDetails : public Serializable { - ExceptionDetails() = default; - ExceptionDetails(ExceptionDetails &&) = default; - ExceptionDetails(const ExceptionDetails &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - ExceptionDetails &operator=(const ExceptionDetails &) = delete; - ExceptionDetails &operator=(ExceptionDetails &&) = default; - - long long exceptionId{}; - std::string text; - long long lineNumber{}; - long long columnNumber{}; - std::optional scriptId; - std::optional url; - std::optional stackTrace; - std::optional exception; - std::optional executionContextId; -}; - -struct debugger::Scope : public Serializable { - Scope() = default; - Scope(Scope &&) = default; - Scope(const Scope &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - Scope &operator=(const Scope &) = delete; - Scope &operator=(Scope &&) = default; - - std::string type; - runtime::RemoteObject object{}; - std::optional name; - std::optional startLocation; - std::optional endLocation; -}; - -struct debugger::CallFrame : public Serializable { - CallFrame() = default; - CallFrame(CallFrame &&) = default; - CallFrame(const CallFrame &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - CallFrame &operator=(const CallFrame &) = delete; - CallFrame &operator=(CallFrame &&) = default; - - debugger::CallFrameId callFrameId{}; - std::string functionName; - std::optional functionLocation; - debugger::Location location{}; - std::string url; - std::vector scopeChain; - runtime::RemoteObject thisObj{}; - std::optional returnValue; -}; - -struct heapProfiler::SamplingHeapProfileNode : public Serializable { - SamplingHeapProfileNode() = default; - SamplingHeapProfileNode(SamplingHeapProfileNode &&) = default; - SamplingHeapProfileNode(const SamplingHeapProfileNode &) = delete; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - SamplingHeapProfileNode &operator=(const SamplingHeapProfileNode &) = delete; - SamplingHeapProfileNode &operator=(SamplingHeapProfileNode &&) = default; - - runtime::CallFrame callFrame{}; - double selfSize{}; - long long id{}; - std::vector children; -}; - -struct heapProfiler::SamplingHeapProfileSample : public Serializable { - SamplingHeapProfileSample() = default; - SamplingHeapProfileSample(SamplingHeapProfileSample &&) = default; - SamplingHeapProfileSample(const SamplingHeapProfileSample &) = delete; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - SamplingHeapProfileSample &operator=(const SamplingHeapProfileSample &) = - delete; - SamplingHeapProfileSample &operator=(SamplingHeapProfileSample &&) = default; - - double size{}; - long long nodeId{}; - double ordinal{}; -}; - -struct heapProfiler::SamplingHeapProfile : public Serializable { - SamplingHeapProfile() = default; - SamplingHeapProfile(SamplingHeapProfile &&) = default; - SamplingHeapProfile(const SamplingHeapProfile &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - SamplingHeapProfile &operator=(const SamplingHeapProfile &) = delete; - SamplingHeapProfile &operator=(SamplingHeapProfile &&) = default; - - heapProfiler::SamplingHeapProfileNode head{}; - std::vector samples; -}; - -struct profiler::PositionTickInfo : public Serializable { - PositionTickInfo() = default; - PositionTickInfo(PositionTickInfo &&) = default; - PositionTickInfo(const PositionTickInfo &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - PositionTickInfo &operator=(const PositionTickInfo &) = delete; - PositionTickInfo &operator=(PositionTickInfo &&) = default; - - long long line{}; - long long ticks{}; -}; - -struct profiler::ProfileNode : public Serializable { - ProfileNode() = default; - ProfileNode(ProfileNode &&) = default; - ProfileNode(const ProfileNode &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - ProfileNode &operator=(const ProfileNode &) = delete; - ProfileNode &operator=(ProfileNode &&) = default; - - long long id{}; - runtime::CallFrame callFrame{}; - std::optional hitCount; - std::optional> children; - std::optional deoptReason; - std::optional> positionTicks; -}; - -struct profiler::Profile : public Serializable { - Profile() = default; - Profile(Profile &&) = default; - Profile(const Profile &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - Profile &operator=(const Profile &) = delete; - Profile &operator=(Profile &&) = default; - - std::vector nodes; - double startTime{}; - double endTime{}; - std::optional> samples; - std::optional> timeDeltas; -}; - -struct runtime::CallArgument : public Serializable { - CallArgument() = default; - CallArgument(CallArgument &&) = default; - CallArgument(const CallArgument &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - CallArgument &operator=(const CallArgument &) = delete; - CallArgument &operator=(CallArgument &&) = default; - - std::optional value; - std::optional unserializableValue; - std::optional objectId; -}; - -struct runtime::ExecutionContextDescription : public Serializable { - ExecutionContextDescription() = default; - ExecutionContextDescription(ExecutionContextDescription &&) = default; - ExecutionContextDescription(const ExecutionContextDescription &) = delete; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - ExecutionContextDescription &operator=(const ExecutionContextDescription &) = - delete; - ExecutionContextDescription &operator=(ExecutionContextDescription &&) = - default; - - runtime::ExecutionContextId id{}; - std::string origin; - std::string name; - std::optional auxData; -}; - -struct runtime::PropertyDescriptor : public Serializable { - PropertyDescriptor() = default; - PropertyDescriptor(PropertyDescriptor &&) = default; - PropertyDescriptor(const PropertyDescriptor &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - PropertyDescriptor &operator=(const PropertyDescriptor &) = delete; - PropertyDescriptor &operator=(PropertyDescriptor &&) = default; - - std::string name; - std::optional value; - std::optional writable; - std::optional get; - std::optional set; - bool configurable{}; - bool enumerable{}; - std::optional wasThrown; - std::optional isOwn; - std::optional symbol; -}; - -struct runtime::InternalPropertyDescriptor : public Serializable { - InternalPropertyDescriptor() = default; - InternalPropertyDescriptor(InternalPropertyDescriptor &&) = default; - InternalPropertyDescriptor(const InternalPropertyDescriptor &) = delete; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - InternalPropertyDescriptor &operator=(const InternalPropertyDescriptor &) = - delete; - InternalPropertyDescriptor &operator=(InternalPropertyDescriptor &&) = - default; - - std::string name; - std::optional value; -}; - -/// Requests -struct UnknownRequest : public Request { - UnknownRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional params; -}; - -struct debugger::DisableRequest : public Request { - DisableRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct debugger::EnableRequest : public Request { - EnableRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct debugger::EvaluateOnCallFrameRequest : public Request { - EvaluateOnCallFrameRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - debugger::CallFrameId callFrameId{}; - std::string expression; - std::optional objectGroup; - std::optional includeCommandLineAPI; - std::optional silent; - std::optional returnByValue; - std::optional generatePreview; - std::optional throwOnSideEffect; -}; - -struct debugger::PauseRequest : public Request { - PauseRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct debugger::RemoveBreakpointRequest : public Request { - RemoveBreakpointRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - debugger::BreakpointId breakpointId{}; -}; - -struct debugger::ResumeRequest : public Request { - ResumeRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional terminateOnResume; -}; - -struct debugger::SetBreakpointRequest : public Request { - SetBreakpointRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - debugger::Location location{}; - std::optional condition; -}; - -struct debugger::SetBreakpointByUrlRequest : public Request { - SetBreakpointByUrlRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - long long lineNumber{}; - std::optional url; - std::optional urlRegex; - std::optional scriptHash; - std::optional columnNumber; - std::optional condition; -}; - -struct debugger::SetBreakpointsActiveRequest : public Request { - SetBreakpointsActiveRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - bool active{}; -}; - -struct debugger::SetInstrumentationBreakpointRequest : public Request { - SetInstrumentationBreakpointRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::string instrumentation; -}; - -struct debugger::SetPauseOnExceptionsRequest : public Request { - SetPauseOnExceptionsRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::string state; -}; - -struct debugger::StepIntoRequest : public Request { - StepIntoRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct debugger::StepOutRequest : public Request { - StepOutRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct debugger::StepOverRequest : public Request { - StepOverRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct heapProfiler::CollectGarbageRequest : public Request { - CollectGarbageRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct heapProfiler::GetHeapObjectIdRequest : public Request { - GetHeapObjectIdRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - runtime::RemoteObjectId objectId{}; -}; - -struct heapProfiler::GetObjectByHeapObjectIdRequest : public Request { - GetObjectByHeapObjectIdRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - heapProfiler::HeapSnapshotObjectId objectId{}; - std::optional objectGroup; -}; - -struct heapProfiler::StartSamplingRequest : public Request { - StartSamplingRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional samplingInterval; - std::optional includeObjectsCollectedByMajorGC; - std::optional includeObjectsCollectedByMinorGC; -}; - -struct heapProfiler::StartTrackingHeapObjectsRequest : public Request { - StartTrackingHeapObjectsRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional trackAllocations; -}; - -struct heapProfiler::StopSamplingRequest : public Request { - StopSamplingRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct heapProfiler::StopTrackingHeapObjectsRequest : public Request { - StopTrackingHeapObjectsRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional reportProgress; - std::optional treatGlobalObjectsAsRoots; - std::optional captureNumericValue; -}; - -struct heapProfiler::TakeHeapSnapshotRequest : public Request { - TakeHeapSnapshotRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional reportProgress; - std::optional treatGlobalObjectsAsRoots; - std::optional captureNumericValue; -}; - -struct profiler::StartRequest : public Request { - StartRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct profiler::StopRequest : public Request { - StopRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct runtime::CallFunctionOnRequest : public Request { - CallFunctionOnRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::string functionDeclaration; - std::optional objectId; - std::optional> arguments; - std::optional silent; - std::optional returnByValue; - std::optional generatePreview; - std::optional userGesture; - std::optional awaitPromise; - std::optional executionContextId; - std::optional objectGroup; -}; - -struct runtime::CompileScriptRequest : public Request { - CompileScriptRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::string expression; - std::string sourceURL; - bool persistScript{}; - std::optional executionContextId; -}; - -struct runtime::DisableRequest : public Request { - DisableRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct runtime::EnableRequest : public Request { - EnableRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct runtime::EvaluateRequest : public Request { - EvaluateRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::string expression; - std::optional objectGroup; - std::optional includeCommandLineAPI; - std::optional silent; - std::optional contextId; - std::optional returnByValue; - std::optional generatePreview; - std::optional userGesture; - std::optional awaitPromise; -}; - -struct runtime::GetHeapUsageRequest : public Request { - GetHeapUsageRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct runtime::GetPropertiesRequest : public Request { - GetPropertiesRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - runtime::RemoteObjectId objectId{}; - std::optional ownProperties; - std::optional generatePreview; -}; - -struct runtime::GlobalLexicalScopeNamesRequest : public Request { - GlobalLexicalScopeNamesRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional executionContextId; -}; - -struct runtime::RunIfWaitingForDebuggerRequest : public Request { - RunIfWaitingForDebuggerRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -/// Responses -struct ErrorResponse : public Response { - ErrorResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - long long code; - std::string message; - std::optional data; -}; - -struct OkResponse : public Response { - OkResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; -}; - -struct debugger::EvaluateOnCallFrameResponse : public Response { - EvaluateOnCallFrameResponse() = default; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - runtime::RemoteObject result{}; - std::optional exceptionDetails; -}; - -struct debugger::SetBreakpointResponse : public Response { - SetBreakpointResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - debugger::BreakpointId breakpointId{}; - debugger::Location actualLocation{}; -}; - -struct debugger::SetBreakpointByUrlResponse : public Response { - SetBreakpointByUrlResponse() = default; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - debugger::BreakpointId breakpointId{}; - std::vector locations; -}; - -struct debugger::SetInstrumentationBreakpointResponse : public Response { - SetInstrumentationBreakpointResponse() = default; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - debugger::BreakpointId breakpointId{}; -}; - -struct heapProfiler::GetHeapObjectIdResponse : public Response { - GetHeapObjectIdResponse() = default; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - heapProfiler::HeapSnapshotObjectId heapSnapshotObjectId{}; -}; - -struct heapProfiler::GetObjectByHeapObjectIdResponse : public Response { - GetObjectByHeapObjectIdResponse() = default; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - runtime::RemoteObject result{}; -}; - -struct heapProfiler::StopSamplingResponse : public Response { - StopSamplingResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - heapProfiler::SamplingHeapProfile profile{}; -}; - -struct profiler::StopResponse : public Response { - StopResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - profiler::Profile profile{}; -}; - -struct runtime::CallFunctionOnResponse : public Response { - CallFunctionOnResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - runtime::RemoteObject result{}; - std::optional exceptionDetails; -}; - -struct runtime::CompileScriptResponse : public Response { - CompileScriptResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::optional scriptId; - std::optional exceptionDetails; -}; - -struct runtime::EvaluateResponse : public Response { - EvaluateResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - runtime::RemoteObject result{}; - std::optional exceptionDetails; -}; - -struct runtime::GetHeapUsageResponse : public Response { - GetHeapUsageResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - double usedSize{}; - double totalSize{}; -}; - -struct runtime::GetPropertiesResponse : public Response { - GetPropertiesResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::vector result; - std::optional> - internalProperties; - std::optional exceptionDetails; -}; - -struct runtime::GlobalLexicalScopeNamesResponse : public Response { - GlobalLexicalScopeNamesResponse() = default; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::vector names; -}; - -/// Notifications -struct debugger::BreakpointResolvedNotification : public Notification { - BreakpointResolvedNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - debugger::BreakpointId breakpointId{}; - debugger::Location location{}; -}; - -struct debugger::PausedNotification : public Notification { - PausedNotification(); - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::vector callFrames; - std::string reason; - std::optional data; - std::optional> hitBreakpoints; - std::optional asyncStackTrace; -}; - -struct debugger::ResumedNotification : public Notification { - ResumedNotification(); - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; -}; - -struct debugger::ScriptParsedNotification : public Notification { - ScriptParsedNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - runtime::ScriptId scriptId{}; - std::string url; - long long startLine{}; - long long startColumn{}; - long long endLine{}; - long long endColumn{}; - runtime::ExecutionContextId executionContextId{}; - std::string hash; - std::optional executionContextAuxData; - std::optional sourceMapURL; - std::optional hasSourceURL; - std::optional isModule; - std::optional length; -}; - -struct heapProfiler::AddHeapSnapshotChunkNotification : public Notification { - AddHeapSnapshotChunkNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::string chunk; -}; - -struct heapProfiler::HeapStatsUpdateNotification : public Notification { - HeapStatsUpdateNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::vector statsUpdate; -}; - -struct heapProfiler::LastSeenObjectIdNotification : public Notification { - LastSeenObjectIdNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - long long lastSeenObjectId{}; - double timestamp{}; -}; - -struct heapProfiler::ReportHeapSnapshotProgressNotification - : public Notification { - ReportHeapSnapshotProgressNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - long long done{}; - long long total{}; - std::optional finished; -}; - -struct runtime::ConsoleAPICalledNotification : public Notification { - ConsoleAPICalledNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::string type; - std::vector args; - runtime::ExecutionContextId executionContextId{}; - runtime::Timestamp timestamp{}; - std::optional stackTrace; -}; - -struct runtime::ExecutionContextCreatedNotification : public Notification { - ExecutionContextCreatedNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - runtime::ExecutionContextDescription context{}; -}; - -} // namespace message -} // namespace chrome -} // namespace inspector_modern -} // namespace hermes -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/MessageTypesInlines.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/MessageTypesInlines.h deleted file mode 100644 index 49a4995d..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/MessageTypesInlines.h +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include - -#include -#include -#include - -namespace facebook { -namespace hermes { -namespace inspector_modern { -namespace chrome { -namespace message { - -template -using optional = std::optional; - -template -struct is_vector : std::false_type {}; - -template -struct is_vector> : std::true_type {}; - -/// valueFromJson - -/// Convert JSONValue to a Serializable type. -template -typename std:: - enable_if::value, std::unique_ptr>::type - valueFromJson(const JSONValue *v) { - auto res = llvh::dyn_cast_or_null(v); - if (!res) { - return nullptr; - } - return T::tryMake(res); -} - -/// Convert JSONValue to a bool. -template -typename std::enable_if::value, std::unique_ptr>::type -valueFromJson(const JSONValue *v) { - auto res = llvh::dyn_cast_or_null(v); - if (!res) { - return nullptr; - } - return std::make_unique(res->getValue()); -} - -/// Convert JSONValue to a long long. -template -typename std::enable_if::value, std::unique_ptr>:: - type - valueFromJson(const JSONValue *v) { - auto res = llvh::dyn_cast_or_null(v); - if (!res) { - return nullptr; - } - return std::make_unique(res->getValue()); -} - -/// Convert JSONValue to a double. -template -typename std::enable_if::value, std::unique_ptr>:: - type - valueFromJson(const JSONValue *v) { - auto res = llvh::dyn_cast_or_null(v); - if (!res) { - return nullptr; - } - return std::make_unique(res->getValue()); -} - -/// Convert JSONValue to a string. -template -typename std:: - enable_if::value, std::unique_ptr>::type - valueFromJson(const JSONValue *v) { - auto res = llvh::dyn_cast_or_null(v); - if (!res) { - return nullptr; - } - return std::make_unique(res->c_str()); -} - -/// Convert JSONValue to a vector. -template -typename std::enable_if::value, std::unique_ptr>::type -valueFromJson(const JSONValue *items) { - auto *arr = llvh::dyn_cast(items); - std::unique_ptr result = std::make_unique(); - result->reserve(arr->size()); - for (const auto &item : *arr) { - auto itemResult = valueFromJson(item); - if (!itemResult) { - return nullptr; - } - result->push_back(std::move(*itemResult)); - } - return result; -} - -/// Convert JSONValue to a JSONObject. -template -typename std:: - enable_if::value, std::unique_ptr>::type - valueFromJson(JSONValue *v) { - auto *res = llvh::dyn_cast_or_null(v); - if (!res) { - return nullptr; - } - return std::make_unique(res); -} - -/// Pass through JSONValues. -template -typename std:: - enable_if::value, std::unique_ptr>::type - valueFromJson(JSONValue *v) { - return std::make_unique(v); -} - -/// assign(lhs, obj, key) is a wrapper for: -/// -/// lhs = obj[key] -/// -/// It mainly exists so that we can choose the right version of valueFromJson -/// based on the type of lhs. - -template -bool assign(T &lhs, const JSONObject *obj, const U &key) { - JSONValue *v = obj->get(key); - if (v == nullptr) { - return false; - } - auto convertResult = valueFromJson(v); - if (convertResult) { - lhs = std::move(*convertResult); - return true; - } - return false; -} - -template -bool assign(optional &lhs, const JSONObject *obj, const U &key) { - JSONValue *v = obj->get(key); - if (v != nullptr) { - auto convertResult = valueFromJson(v); - if (convertResult) { - lhs = std::move(*convertResult); - return true; - } - return false; - } else { - lhs.reset(); - return true; - } -} - -template -bool assign(std::unique_ptr &lhs, const JSONObject *obj, const U &key) { - JSONValue *v = obj->get(key); - if (v != nullptr) { - auto convertResult = valueFromJson(v); - if (convertResult) { - lhs = std::move(convertResult); - return true; - } - return false; - } else { - lhs.reset(); - return true; - } -} - -template -bool assign( - std::unique_ptr> &lhs, - const JSONObject *obj, - const U &key) { - JSONValue *v = obj->get(key); - if (v != nullptr) { - auto convertResult = valueFromJson(v); - if (convertResult) { - lhs = std::move(convertResult); - return true; - } - return false; - } else { - lhs.reset(); - return true; - } -} - -/// valueToJson - -inline JSONValue *valueToJson(const Serializable &value, JSONFactory &factory) { - return value.toJsonVal(factory); -} - -// Convert a bool to JSONValue. -inline JSONValue *valueToJson(bool b, JSONFactory &factory) { - return factory.getBoolean(b); -} - -// Convert a long long to JSONValue. -inline JSONValue *valueToJson(long long num, JSONFactory &factory) { - return factory.getNumber(num); -} - -// Convert a double to JSONValue. -inline JSONValue *valueToJson(double num, JSONFactory &factory) { - return factory.getNumber(num); -} - -// Convert a string to JSONValue. -inline JSONValue *valueToJson(const std::string &str, JSONFactory &factory) { - return factory.getString(str); -} - -// Convert a vector to JSONValue. -template -JSONValue *valueToJson(const std::vector &items, JSONFactory &factory) { - llvh::SmallVector storage; - for (const auto &item : items) { - storage.push_back(valueToJson(item, factory)); - } - return factory.newArray(storage.size(), storage.begin(), storage.end()); -} - -// Cast a JSONObject to JSONValue. -inline JSONValue *valueToJson(JSONObject *obj, JSONFactory &factory) { - return llvh::cast(obj); -} - -// Pass through JSONValues. -inline JSONValue *valueToJson(JSONValue *v, JSONFactory &factory) { - return v; -} - -/// put(obj, key, value) is meant to be a wrapper for: -/// obj[key] = valueToJson(value); -/// However, JSONObjects are immutable, so we represent a 'put' operation as -/// pushing a new element onto a vector of JSONFactory::Props. - -using Properties = llvh::SmallVectorImpl; - -template -void put( - Properties &props, - const std::string &key, - const V &value, - JSONFactory &factory) { - JSONString *jsStr = factory.getString(key); - JSONValue *jsVal = valueToJson(value, factory); - props.push_back({jsStr, jsVal}); -} - -template -void put( - Properties &props, - const std::string &key, - const optional &optValue, - JSONFactory &factory) { - if (optValue.has_value()) { - JSONString *jsStr = factory.getString(key); - JSONValue *jsVal = valueToJson(optValue.value(), factory); - props.push_back({jsStr, jsVal}); - } -} - -template -void put( - Properties &props, - const std::string &key, - const std::unique_ptr &ptr, - JSONFactory &factory) { - if (ptr.get()) { - JSONString *jsStr = factory.getString(key); - JSONValue *jsVal = valueToJson(*ptr, factory); - props.push_back({jsStr, jsVal}); - } -} - -template -void put( - Properties &props, - const std::string &key, - const std::unique_ptr> &ptr, - JSONFactory &factory) { - if (ptr.get()) { - JSONString *jsStr = factory.getString(key); - JSONValue *jsVal = valueToJson(*ptr, factory); - props.push_back({jsStr, jsVal}); - } -} - -template -void deleter(T *p) { - delete p; -} - -} // namespace message -} // namespace chrome -} // namespace inspector_modern -} // namespace hermes -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/RemoteObjectConverters.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/RemoteObjectConverters.h deleted file mode 100644 index 89355dc3..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/RemoteObjectConverters.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include - -namespace facebook { -namespace hermes { -namespace inspector_modern { -namespace chrome { -namespace message { - -namespace debugger { - -CallFrame makeCallFrame( - uint32_t callFrameIndex, - const facebook::hermes::debugger::CallFrameInfo &callFrameInfo, - const facebook::hermes::debugger::LexicalInfo &lexicalInfo, - facebook::hermes::inspector_modern::chrome::RemoteObjectsTable &objTable, - jsi::Runtime &runtime, - const facebook::hermes::debugger::ProgramState &state); - -std::vector makeCallFrames( - const facebook::hermes::debugger::ProgramState &state, - facebook::hermes::inspector_modern::chrome::RemoteObjectsTable &objTable, - jsi::Runtime &runtime); - -} // namespace debugger - -namespace runtime { - -RemoteObject makeRemoteObject( - facebook::jsi::Runtime &runtime, - const facebook::jsi::Value &value, - facebook::hermes::inspector_modern::chrome::RemoteObjectsTable &objTable, - const std::string &objectGroup, - bool byValue = false, - bool generatePreview = false); - -} // namespace runtime - -} // namespace message -} // namespace chrome -} // namespace inspector_modern -} // namespace hermes -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/RemoteObjectsTable.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/RemoteObjectsTable.h deleted file mode 100644 index d7a3370f..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/RemoteObjectsTable.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include - -#include - -namespace facebook { -namespace hermes { -namespace inspector_modern { -namespace chrome { - -/// Well-known object group names - -/** - * Objects created as a result of the Debugger.paused notification (e.g. scope - * objects) are placed in the "backtrace" object group. This object group is - * cleared when the VM resumes. - */ -extern const char *BacktraceObjectGroup; - -/** - * Objects that are created as a result of a console evaluation are placed in - * the "console" object group. This object group is cleared when the client - * clears the console. - */ -extern const char *ConsoleObjectGroup; - -/** - * RemoteObjectsTable manages the mapping of string object ids to scope metadata - * or actual JSI objects. The debugger vends these ids to the client so that the - * client can perform operations on the ids (e.g. enumerate properties on the - * object backed by the id). See Runtime.RemoteObjectId in the CDT docs for - * more details. - * - * Note that object handles are not ref-counted. Suppose an object foo is mapped - * to object id "objId" and is also in object group "objGroup". Then *either* of - * `releaseObject("objId")` or `releaseObjectGroup("objGroup")` will remove foo - * from the table. This matches the behavior of object groups in CDT. - */ -class RemoteObjectsTable { - public: - RemoteObjectsTable(); - ~RemoteObjectsTable(); - - RemoteObjectsTable(const RemoteObjectsTable &) = delete; - RemoteObjectsTable &operator=(const RemoteObjectsTable &) = delete; - - /** - * addScope adds the provided (frameIndex, scopeIndex) mapping to the table. - * If objectGroup is non-empty, then the scope object is also added to that - * object group for releasing via releaseObjectGroup. Returns an object id. - */ - std::string addScope( - std::pair frameAndScopeIndex, - const std::string &objectGroup); - - /** - * addValue adds the JSI value to the table. If objectGroup is non-empty, then - * the scope object is also added to that object group for releasing via - * releaseObjectGroup. Returns an object id. - */ - std::string addValue( - ::facebook::jsi::Value value, - const std::string &objectGroup); - - /** - * Retrieves the (frameIndex, scopeIndex) associated with this object id, or - * nullptr if no mapping exists. The pointer stays valid as long as you only - * call const methods on this class. - */ - const std::pair *getScope(const std::string &objId) const; - - /** - * Retrieves the JSI value associated with this object id, or nullptr if no - * mapping exists. The pointer stays valid as long as you only call const - * methods on this class. - */ - const ::facebook::jsi::Value *getValue(const std::string &objId) const; - - /** - * Retrieves the object group that this object id is in, or empty string if it - * isn't in an object group. The returned pointer is only guaranteed to be - * valid until the next call to this class. - */ - std::string getObjectGroup(const std::string &objId) const; - - /** - * Removes the scope or JSI value backed by the provided object ID from the - * table. - */ - void releaseObject(const std::string &objId); - - /** - * Removes all objects that are part of the provided object group from the - * table. - */ - void releaseObjectGroup(const std::string &objectGroup); - - private: - void releaseObject(int64_t id); - - int64_t scopeId_ = -1; - int64_t valueId_ = 1; - - std::unordered_map> scopes_; - std::unordered_map values_; - std::unordered_map idToGroup_; - std::unordered_map> groupToIds_; -}; - -} // namespace chrome -} // namespace inspector_modern -} // namespace hermes -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/tests/AsyncHermesRuntime.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/tests/AsyncHermesRuntime.h deleted file mode 100644 index aaaf9cd0..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/tests/AsyncHermesRuntime.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include - -namespace facebook { -namespace hermes { -namespace inspector_modern { -namespace chrome { - -/// URL assigned to scripts being executed in the absense of a caller-specified -/// URL. -constexpr auto kDefaultUrl = "url"; - -/** - * AsyncHermesRuntime is a helper class that runs JS scripts in a Hermes VM on - * a separate thread. This is useful for tests that want to test running JS - * in a multithreaded environment. - */ -class AsyncHermesRuntime { - public: - // Create a runtime. If veryLazy, configure the runtime to use completely - // lazy compilation. - AsyncHermesRuntime(bool veryLazy = false); - ~AsyncHermesRuntime(); - - std::shared_ptr runtime() { - return runtime_; - } - - /** - * stop sets the stop flag on this instance. JS scripts can get the current - * value of the stop flag by calling the global shouldStop() function. - */ - void stop(); - - /** - * start unsets the stop flag on this instance. JS scripts can get the current - * value of the stop flag by calling the global shouldStop() function. - */ - void start(); - - /** - * hasStoredValue returns whether or not a value has been stored yet - */ - bool hasStoredValue(); - - /** - * awaitStoredValue is a helper for getStoredValue that returns the value - * synchronously rather than in a future. - */ - jsi::Value awaitStoredValue( - std::chrono::milliseconds timeout = std::chrono::milliseconds(2500)); - - /** - * tickleJsAsync evaluates '__tickleJs()' in the underlying Hermes runtime on - * a separate thread. - */ - void tickleJsAsync(); - - /** - * executeScriptAsync evaluates JS in the underlying Hermes runtime on a - * separate thread. - * - * This method should be called at most once during the lifetime of an - * AsyncHermesRuntime instance. - */ - void executeScriptAsync( - const std::string &str, - const std::string &url = kDefaultUrl, - facebook::hermes::HermesRuntime::DebugFlags flags = - facebook::hermes::HermesRuntime::DebugFlags{}); - - /** - * executeScriptSync evaluates JS in the underlying Hermes runtime on a - * separate thread. It will block the caller until execution completes. If - * this takes longer than \p timeout, an exception will be thrown. - */ - void executeScriptSync( - const std::string &script, - const std::string &url = kDefaultUrl, - facebook::hermes::HermesRuntime::DebugFlags flags = - facebook::hermes::HermesRuntime::DebugFlags{}, - std::chrono::milliseconds timeout = std::chrono::milliseconds(2500)); - - /// Evaluates the given bytecode in the underlying Hermes runtime on a - /// separate thread. - /// \param bytecode Bytecode compiled with compileJS() API - /// \param url Corresponding source URL - void evaluateBytecodeAsync( - const std::string &bytecode, - const std::string &url = "url"); - - /** - * wait blocks until all previous executeScriptAsync calls finish. - */ - void wait( - std::chrono::milliseconds timeout = std::chrono::milliseconds(2500)); - - /** - * returns the number of thrown exceptions. - */ - size_t getNumberOfExceptions(); - - /** - * returns the message of the last thrown exception. - */ - std::string getLastThrownExceptionMessage(); - - /** - * registers the runtime for profiling in the executor thread. - */ - void registerForProfilingInExecutor(); - - /** - * unregisters the runtime for profiling in the executor thread. - */ - void unregisterForProfilingInExecutor(); - - private: - jsi::Value shouldStop( - jsi::Runtime &runtime, - const jsi::Value &thisVal, - const jsi::Value *args, - size_t count); - - jsi::Value storeValue( - jsi::Runtime &runtime, - const jsi::Value &thisVal, - const jsi::Value *args, - size_t count); - - std::shared_ptr runtime_; - std::unique_ptr<::hermes::SerialExecutor> executor_; - std::atomic stopFlag_{}; - std::promise storedValue_; - bool hasStoredValue_{false}; - std::vector thrownExceptions_; -}; - -/// RAII-style class dealing with sampling profiler registration in tests. This -/// is especially important in tests -- if any test failure is caused by an -/// uncaught exception, stack unwinding will destroy a VM registered for -/// profiling in a thread that's not the one where registration happened, which -/// will lead to a hermes fatal error. Using this RAII class ensure that the -/// proper test failure cause is reported. -struct SamplingProfilerRAII { - explicit SamplingProfilerRAII(AsyncHermesRuntime &rt) : runtime_(rt) { - runtime_.registerForProfilingInExecutor(); - } - - ~SamplingProfilerRAII() { - runtime_.unregisterForProfilingInExecutor(); - } - - AsyncHermesRuntime &runtime_; -}; -} // namespace chrome -} // namespace inspector_modern -} // namespace hermes -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/tests/SyncConnection.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/tests/SyncConnection.h deleted file mode 100644 index d9ecc509..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/tests/SyncConnection.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include -#include - -#include -#include - -#include "AsyncHermesRuntime.h" - -namespace facebook { -namespace hermes { -namespace inspector_modern { -namespace chrome { - -class ExecutorRuntimeAdapter - : public facebook::hermes::inspector_modern::RuntimeAdapter { - public: - explicit ExecutorRuntimeAdapter(AsyncHermesRuntime &runtime) - : runtime_(runtime) {} - - virtual ~ExecutorRuntimeAdapter() override = default; - - HermesRuntime &getRuntime() override { - return *runtime_.runtime(); - } - - void tickleJs() override; - - private: - AsyncHermesRuntime &runtime_; -}; - -/** - * SyncConnection provides a synchronous interface over Connection that is - * useful in tests. - */ -class SyncConnection { - public: - explicit SyncConnection( - AsyncHermesRuntime &runtime, - bool waitForDebugger = false); - ~SyncConnection(); - - /// sends a message to the debugger - void send(const std::string &str); - - /// waits for the next message of either kind (response or notification) - /// from the debugger. returns the message. throws on timeout. - std::string waitForMessage( - std::chrono::milliseconds timeout = std::chrono::milliseconds(2500)); - - bool registerCallbacks(); - bool unregisterCallbacks(); - - /// \return True if onUnregister was called in a previous unregisterCallbacks - /// call. A registerCallbacks call will reset the status. - bool onUnregisterWasCalled(); - - private: - /// This function is given to the CDPHandler to receive replies in the form of - /// CDP messages - void onReply(const std::string &message); - - /// This function is given to the CDPHandler to be invoked upon - /// unregisterCallbacks call - void onUnregister(); - - std::shared_ptr cdpHandler_; - - bool onUnregisterCalled_ = false; - - std::mutex mutex_; - std::condition_variable hasMessage_; - std::queue messages_; -}; - -} // namespace chrome -} // namespace inspector_modern -} // namespace hermes -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/tests/TestHelpers.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/tests/TestHelpers.h deleted file mode 100644 index 2f0e0399..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/inspector/chrome/tests/TestHelpers.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -#include -#include -#include -#include - -namespace facebook { -namespace hermes { -namespace inspector_modern { -namespace chrome { - -using namespace ::hermes::parser; - -inline JSONValue *mustParseStr(const std::string &str, JSONFactory &factory) { - std::optional v = parseStr(str, factory); - EXPECT_TRUE(v.has_value()); - return v.value(); -} - -inline JSONObject *mustParseStrAsJsonObj( - const std::string &str, - JSONFactory &factory) { - std::optional obj = parseStrAsJsonObj(str, factory); - EXPECT_TRUE(obj.has_value()); - return obj.value(); -} - -template -T mustMake(const JSONObject *obj) { - std::unique_ptr instance = T::tryMake(obj); - EXPECT_TRUE(instance != nullptr); - return std::move(*instance); -} - -namespace message { - -inline std::unique_ptr mustGetRequestFromJson(const std::string &str) { - std::unique_ptr req = Request::fromJson(str); - EXPECT_TRUE(req != nullptr); - return req; -} - -} // namespace message - -} // namespace chrome -} // namespace inspector_modern -} // namespace hermes -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/napi/node_api.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/napi/node_api.h new file mode 100644 index 00000000..46dbb02b --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/napi/node_api.h @@ -0,0 +1,265 @@ +#ifndef SRC_NODE_API_H_ +#define SRC_NODE_API_H_ + +#if defined(BUILDING_NODE_EXTENSION) && !defined(NAPI_EXTERN) +#ifdef _WIN32 +// Building native addon against node +#define NAPI_EXTERN __declspec(dllimport) +#elif defined(__wasm__) +#define NAPI_EXTERN __attribute__((__import_module__("napi"))) +#endif +#endif +#include "js_native_api.h" +#include "node_api_types.h" + +struct uv_loop_s; // Forward declaration. + +#ifdef _WIN32 +#define NAPI_MODULE_EXPORT __declspec(dllexport) +#else +#ifdef __EMSCRIPTEN__ +#define NAPI_MODULE_EXPORT \ + __attribute__((visibility("default"))) __attribute__((used)) +#else +#define NAPI_MODULE_EXPORT __attribute__((visibility("default"))) +#endif +#endif + +#if defined(__GNUC__) +#define NAPI_NO_RETURN __attribute__((noreturn)) +#elif defined(_WIN32) +#define NAPI_NO_RETURN __declspec(noreturn) +#else +#define NAPI_NO_RETURN +#endif + +// Used by deprecated registration method napi_module_register. +typedef struct napi_module { + int nm_version; + unsigned int nm_flags; + const char* nm_filename; + napi_addon_register_func nm_register_func; + const char* nm_modname; + void* nm_priv; + void* reserved[4]; +} napi_module; + +#define NAPI_MODULE_VERSION 1 + +#define NAPI_MODULE_INITIALIZER_X(base, version) \ + NAPI_MODULE_INITIALIZER_X_HELPER(base, version) +#define NAPI_MODULE_INITIALIZER_X_HELPER(base, version) base##version + +#ifdef __wasm__ +#define NAPI_MODULE_INITIALIZER_BASE napi_register_wasm_v +#else +#define NAPI_MODULE_INITIALIZER_BASE napi_register_module_v +#endif + +#define NODE_API_MODULE_GET_API_VERSION_BASE node_api_module_get_api_version_v + +#define NAPI_MODULE_INITIALIZER \ + NAPI_MODULE_INITIALIZER_X(NAPI_MODULE_INITIALIZER_BASE, NAPI_MODULE_VERSION) + +#define NODE_API_MODULE_GET_API_VERSION \ + NAPI_MODULE_INITIALIZER_X(NODE_API_MODULE_GET_API_VERSION_BASE, \ + NAPI_MODULE_VERSION) + +#define NAPI_MODULE_INIT() \ + EXTERN_C_START \ + NAPI_MODULE_EXPORT int32_t NODE_API_MODULE_GET_API_VERSION(void) { \ + return NAPI_VERSION; \ + } \ + NAPI_MODULE_EXPORT napi_value NAPI_MODULE_INITIALIZER(napi_env env, \ + napi_value exports); \ + EXTERN_C_END \ + napi_value NAPI_MODULE_INITIALIZER(napi_env env, napi_value exports) + +#define NAPI_MODULE(modname, regfunc) \ + NAPI_MODULE_INIT() { return regfunc(env, exports); } + +// Deprecated. Use NAPI_MODULE. +#define NAPI_MODULE_X(modname, regfunc, priv, flags) \ + NAPI_MODULE(modname, regfunc) + +EXTERN_C_START + +// Deprecated. Replaced by symbol-based registration defined by NAPI_MODULE +// and NAPI_MODULE_INIT macros. +NAPI_EXTERN void NAPI_CDECL +napi_module_register(napi_module* mod); + +NAPI_EXTERN NAPI_NO_RETURN void NAPI_CDECL +napi_fatal_error(const char* location, + size_t location_len, + const char* message, + size_t message_len); + +// Methods for custom handling of async operations +NAPI_EXTERN napi_status NAPI_CDECL +napi_async_init(napi_env env, + napi_value async_resource, + napi_value async_resource_name, + napi_async_context* result); + +NAPI_EXTERN napi_status NAPI_CDECL +napi_async_destroy(napi_env env, napi_async_context async_context); + +NAPI_EXTERN napi_status NAPI_CDECL +napi_make_callback(napi_env env, + napi_async_context async_context, + napi_value recv, + napi_value func, + size_t argc, + const napi_value* argv, + napi_value* result); + +// Methods to provide node::Buffer functionality with napi types +NAPI_EXTERN napi_status NAPI_CDECL napi_create_buffer(napi_env env, + size_t length, + void** data, + napi_value* result); +#ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED +NAPI_EXTERN napi_status NAPI_CDECL +napi_create_external_buffer(napi_env env, + size_t length, + void* data, + node_api_basic_finalize finalize_cb, + void* finalize_hint, + napi_value* result); +#endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED + +#if NAPI_VERSION >= 10 + +NAPI_EXTERN napi_status NAPI_CDECL +node_api_create_buffer_from_arraybuffer(napi_env env, + napi_value arraybuffer, + size_t byte_offset, + size_t byte_length, + napi_value* result); +#endif // NAPI_VERSION >= 10 + +NAPI_EXTERN napi_status NAPI_CDECL napi_create_buffer_copy(napi_env env, + size_t length, + const void* data, + void** result_data, + napi_value* result); +NAPI_EXTERN napi_status NAPI_CDECL napi_is_buffer(napi_env env, + napi_value value, + bool* result); +NAPI_EXTERN napi_status NAPI_CDECL napi_get_buffer_info(napi_env env, + napi_value value, + void** data, + size_t* length); + +// Methods to manage simple async operations +NAPI_EXTERN napi_status NAPI_CDECL +napi_create_async_work(napi_env env, + napi_value async_resource, + napi_value async_resource_name, + napi_async_execute_callback execute, + napi_async_complete_callback complete, + void* data, + napi_async_work* result); +NAPI_EXTERN napi_status NAPI_CDECL napi_delete_async_work(napi_env env, + napi_async_work work); +NAPI_EXTERN napi_status NAPI_CDECL napi_queue_async_work(node_api_basic_env env, + napi_async_work work); +NAPI_EXTERN napi_status NAPI_CDECL +napi_cancel_async_work(node_api_basic_env env, napi_async_work work); + +// version management +NAPI_EXTERN napi_status NAPI_CDECL napi_get_node_version( + node_api_basic_env env, const napi_node_version** version); + +#if NAPI_VERSION >= 2 + +// Return the current libuv event loop for a given environment +NAPI_EXTERN napi_status NAPI_CDECL +napi_get_uv_event_loop(node_api_basic_env env, struct uv_loop_s** loop); + +#endif // NAPI_VERSION >= 2 + +#if NAPI_VERSION >= 3 + +NAPI_EXTERN napi_status NAPI_CDECL napi_fatal_exception(napi_env env, + napi_value err); + +NAPI_EXTERN napi_status NAPI_CDECL napi_add_env_cleanup_hook( + node_api_basic_env env, napi_cleanup_hook fun, void* arg); + +NAPI_EXTERN napi_status NAPI_CDECL napi_remove_env_cleanup_hook( + node_api_basic_env env, napi_cleanup_hook fun, void* arg); + +NAPI_EXTERN napi_status NAPI_CDECL +napi_open_callback_scope(napi_env env, + napi_value resource_object, + napi_async_context context, + napi_callback_scope* result); + +NAPI_EXTERN napi_status NAPI_CDECL +napi_close_callback_scope(napi_env env, napi_callback_scope scope); + +#endif // NAPI_VERSION >= 3 + +#if NAPI_VERSION >= 4 + +// Calling into JS from other threads +NAPI_EXTERN napi_status NAPI_CDECL +napi_create_threadsafe_function(napi_env env, + napi_value func, + napi_value async_resource, + napi_value async_resource_name, + size_t max_queue_size, + size_t initial_thread_count, + void* thread_finalize_data, + napi_finalize thread_finalize_cb, + void* context, + napi_threadsafe_function_call_js call_js_cb, + napi_threadsafe_function* result); + +NAPI_EXTERN napi_status NAPI_CDECL napi_get_threadsafe_function_context( + napi_threadsafe_function func, void** result); + +NAPI_EXTERN napi_status NAPI_CDECL +napi_call_threadsafe_function(napi_threadsafe_function func, + void* data, + napi_threadsafe_function_call_mode is_blocking); + +NAPI_EXTERN napi_status NAPI_CDECL +napi_acquire_threadsafe_function(napi_threadsafe_function func); + +NAPI_EXTERN napi_status NAPI_CDECL napi_release_threadsafe_function( + napi_threadsafe_function func, napi_threadsafe_function_release_mode mode); + +NAPI_EXTERN napi_status NAPI_CDECL napi_unref_threadsafe_function( + node_api_basic_env env, napi_threadsafe_function func); + +NAPI_EXTERN napi_status NAPI_CDECL napi_ref_threadsafe_function( + node_api_basic_env env, napi_threadsafe_function func); + +#endif // NAPI_VERSION >= 4 + +#if NAPI_VERSION >= 8 + +NAPI_EXTERN napi_status NAPI_CDECL +napi_add_async_cleanup_hook(node_api_basic_env env, + napi_async_cleanup_hook hook, + void* arg, + napi_async_cleanup_hook_handle* remove_handle); + +NAPI_EXTERN napi_status NAPI_CDECL +napi_remove_async_cleanup_hook(napi_async_cleanup_hook_handle remove_handle); + +#endif // NAPI_VERSION >= 8 + +#if NAPI_VERSION >= 9 + +NAPI_EXTERN napi_status NAPI_CDECL +node_api_get_module_file_name(node_api_basic_env env, const char** result); + +#endif // NAPI_VERSION >= 9 + +EXTERN_C_END + +#endif // SRC_NODE_API_H_ diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/napi/node_api_types.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/napi/node_api_types.h new file mode 100644 index 00000000..2580f15c --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/napi/node_api_types.h @@ -0,0 +1,56 @@ +#ifndef SRC_NODE_API_TYPES_H_ +#define SRC_NODE_API_TYPES_H_ + +#include "js_native_api_types.h" + +typedef napi_value(NAPI_CDECL* napi_addon_register_func)(napi_env env, + napi_value exports); +typedef int32_t(NAPI_CDECL* node_api_addon_get_api_version_func)(void); + +typedef struct napi_callback_scope__* napi_callback_scope; +typedef struct napi_async_context__* napi_async_context; +typedef struct napi_async_work__* napi_async_work; + +#if NAPI_VERSION >= 3 +typedef void(NAPI_CDECL* napi_cleanup_hook)(void* arg); +#endif // NAPI_VERSION >= 3 + +#if NAPI_VERSION >= 4 +typedef struct napi_threadsafe_function__* napi_threadsafe_function; +#endif // NAPI_VERSION >= 4 + +#if NAPI_VERSION >= 4 +typedef enum { + napi_tsfn_release, + napi_tsfn_abort +} napi_threadsafe_function_release_mode; + +typedef enum { + napi_tsfn_nonblocking, + napi_tsfn_blocking +} napi_threadsafe_function_call_mode; +#endif // NAPI_VERSION >= 4 + +typedef void(NAPI_CDECL* napi_async_execute_callback)(napi_env env, void* data); +typedef void(NAPI_CDECL* napi_async_complete_callback)(napi_env env, + napi_status status, + void* data); +#if NAPI_VERSION >= 4 +typedef void(NAPI_CDECL* napi_threadsafe_function_call_js)( + napi_env env, napi_value js_callback, void* context, void* data); +#endif // NAPI_VERSION >= 4 + +typedef struct { + uint32_t major; + uint32_t minor; + uint32_t patch; + const char* release; +} napi_node_version; + +#if NAPI_VERSION >= 8 +typedef struct napi_async_cleanup_hook_handle__* napi_async_cleanup_hook_handle; +typedef void(NAPI_CDECL* napi_async_cleanup_hook)( + napi_async_cleanup_hook_handle handle, void* data); +#endif // NAPI_VERSION >= 8 + +#endif // SRC_NODE_API_TYPES_H_ diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/synthtest/tests/TestFunctions.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/synthtest/tests/TestFunctions.h deleted file mode 100644 index 48099473..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/hermes/synthtest/tests/TestFunctions.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_API_SYNTHTEST_TESTS_TESTFUNCTIONS -#define HERMES_API_SYNTHTEST_TESTS_TESTFUNCTIONS - -#define FOREACH_TEST(F) \ - F(callbacksCallJSFunction) \ - F(globalReturnObject) \ - F(getPropertyNames) \ - F(hostCallsJS) \ - F(hostCallsJSCallsHost) \ - F(hostCallsJSWithThis) \ - F(hostFunctionCachesObject) \ - F(hostFunctionCreatesObjects) \ - F(hostFunctionMutatesGlobalObject) \ - F(hostFunctionMutatesObject) \ - F(hostFunctionNameAndParams) \ - F(hostFunctionReturn) \ - F(hostFunctionReturnArgument) \ - F(hostFunctionReturnThis) \ - F(hostGlobalObject) \ - F(nativePropertyNames) \ - F(nativeSetsConstant) \ - F(parseGCConfig) \ - F(partialTraceHostFunction) \ - F(partialTraceHostObjectGet) \ - F(partialTraceHostObjectSet) \ - F(surrogatePairString) - -#define TEST_FUNC_FORWARD_DECL(name) \ - const char *name##Trace(); \ - const char *name##Source(); - -namespace facebook { -namespace hermes { -namespace synthtest { - -// Forward decls for all of the functions used. -FOREACH_TEST(TEST_FUNC_FORWARD_DECL) - -} // namespace synthtest -} // namespace hermes -} // namespace facebook - -#endif diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_abi/HermesABIHelpers.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_abi/HermesABIHelpers.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_abi/HermesABIHelpers.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes_abi/HermesABIHelpers.h diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_abi/HermesABIRuntimeWrapper.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_abi/HermesABIRuntimeWrapper.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_abi/HermesABIRuntimeWrapper.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes_abi/HermesABIRuntimeWrapper.h diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_abi/hermes_abi.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_abi/hermes_abi.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_abi/hermes_abi.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes_abi/hermes_abi.h diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_abi/hermes_vtable.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_abi/hermes_vtable.h similarity index 90% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_abi/hermes_vtable.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes_abi/hermes_vtable.h index 5adeeb36..5b2645d5 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_abi/hermes_vtable.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_abi/hermes_vtable.h @@ -20,8 +20,7 @@ __declspec(dllexport) #else // _MSC_VER __attribute__((visibility("default"))) #endif // _MSC_VER -const struct HermesABIVTable * -get_hermes_abi_vtable(); +const struct HermesABIVTable *get_hermes_abi_vtable(); #ifdef __cplusplus } diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/HermesSandboxRuntime.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/HermesSandboxRuntime.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/HermesSandboxRuntime.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/HermesSandboxRuntime.h diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/hermes_sandbox_impl_compiled.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/hermes_sandbox_impl_compiled.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/hermes_sandbox_impl_compiled.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/hermes_sandbox_impl_compiled.h diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/hermes_sandbox_impl_dbg_compiled-impl.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/hermes_sandbox_impl_dbg_compiled-impl.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/hermes_sandbox_impl_dbg_compiled-impl.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/hermes_sandbox_impl_dbg_compiled-impl.h diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/hermes_sandbox_impl_dbg_compiled.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/hermes_sandbox_impl_dbg_compiled.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/hermes_sandbox_impl_dbg_compiled.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/hermes_sandbox_impl_dbg_compiled.h diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/hermes_sandbox_impl_opt_compiled-impl.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/hermes_sandbox_impl_opt_compiled-impl.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/hermes_sandbox_impl_opt_compiled-impl.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/hermes_sandbox_impl_opt_compiled-impl.h diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/hermes_sandbox_impl_opt_compiled.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/hermes_sandbox_impl_opt_compiled.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/hermes_sandbox_impl_opt_compiled.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/hermes_sandbox_impl_opt_compiled.h diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/wasm-rt-fb.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/wasm-rt-fb.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/wasm-rt-fb.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/wasm-rt-fb.h diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/wasm-rt-impl.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/wasm-rt-impl.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/wasm-rt-impl.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/wasm-rt-impl.h diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/wasm-rt.h b/test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/wasm-rt.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes_sandbox/external/wasm-rt.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/hermes_sandbox/external/wasm-rt.h diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/JSIDynamic.h b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/JSIDynamic.h index a96cc281..d022b639 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/JSIDynamic.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/JSIDynamic.h @@ -20,7 +20,7 @@ facebook::jsi::Value valueFromDynamic( folly::dynamic dynamicFromValue( facebook::jsi::Runtime& runtime, const facebook::jsi::Value& value, - std::function filterObjectKeys = nullptr); + const std::function& filterObjectKeys = nullptr); } // namespace jsi } // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/decorator.h b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/decorator.h index c0d3cc6d..f101c183 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/decorator.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/decorator.h @@ -112,6 +112,10 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { return plain_; } + ICast* castInterface(const UUID& interfaceUUID) override { + return plain().castInterface(interfaceUUID); + } + Value evaluateJavaScript( const std::shared_ptr& buffer, const std::string& sourceURL) override { @@ -137,10 +141,10 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { } std::string description() override { return plain().description(); - }; + } bool isInspectable() override { return plain().isInspectable(); - }; + } Instrumentation& instrumentation() override { return *this; } @@ -156,41 +160,45 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { Runtime::PointerValue* cloneSymbol(const Runtime::PointerValue* pv) override { return plain_.cloneSymbol(pv); - }; + } Runtime::PointerValue* cloneBigInt(const Runtime::PointerValue* pv) override { return plain_.cloneBigInt(pv); - }; + } Runtime::PointerValue* cloneString(const Runtime::PointerValue* pv) override { return plain_.cloneString(pv); - }; + } Runtime::PointerValue* cloneObject(const Runtime::PointerValue* pv) override { return plain_.cloneObject(pv); - }; + } Runtime::PointerValue* clonePropNameID( const Runtime::PointerValue* pv) override { return plain_.clonePropNameID(pv); - }; + } PropNameID createPropNameIDFromAscii(const char* str, size_t length) override { return plain_.createPropNameIDFromAscii(str, length); - }; + } PropNameID createPropNameIDFromUtf8(const uint8_t* utf8, size_t length) override { return plain_.createPropNameIDFromUtf8(utf8, length); - }; + } PropNameID createPropNameIDFromString(const String& str) override { return plain_.createPropNameIDFromString(str); - }; + } + PropNameID createPropNameIDFromUtf16(const char16_t* utf16, size_t length) + override { + return plain_.createPropNameIDFromUtf16(utf16, length); + } PropNameID createPropNameIDFromSymbol(const Symbol& sym) override { return plain_.createPropNameIDFromSymbol(sym); - }; + } std::string utf8(const PropNameID& id) override { return plain_.utf8(id); - }; + } bool compare(const PropNameID& a, const PropNameID& b) override { return plain_.compare(a, b); - }; + } std::string symbolToString(const Symbol& sym) override { return plain_.symbolToString(sym); @@ -217,10 +225,13 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { String createStringFromAscii(const char* str, size_t length) override { return plain_.createStringFromAscii(str, length); - }; + } String createStringFromUtf8(const uint8_t* utf8, size_t length) override { return plain_.createStringFromUtf8(utf8, length); - }; + } + String createStringFromUtf16(const char16_t* utf16, size_t length) override { + return plain_.createStringFromUtf16(utf16, length); + } std::string utf8(const String& s) override { return plain_.utf8(s); } @@ -232,25 +243,44 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { return plain_.utf16(sym); } + void getStringData( + const jsi::String& str, + void* ctx, + void ( + *cb)(void* ctx, bool ascii, const void* data, size_t num)) override { + plain_.getStringData(str, ctx, cb); + } + + void getPropNameIdData( + const jsi::PropNameID& sym, + void* ctx, + void ( + *cb)(void* ctx, bool ascii, const void* data, size_t num)) override { + plain_.getPropNameIdData(sym, ctx, cb); + } + + Object createObjectWithPrototype(const Value& prototype) override { + return plain_.createObjectWithPrototype(prototype); + } + Object createObject() override { return plain_.createObject(); - }; + } Object createObject(std::shared_ptr ho) override { return plain_.createObject( std::make_shared(*this, std::move(ho))); - }; + } std::shared_ptr getHostObject(const jsi::Object& o) override { std::shared_ptr dho = plain_.getHostObject(o); return static_cast(*dho).plainHO_; - }; - -// HostFunctionType& getHostFunction(const jsi::Function& f) override { -// HostFunctionType& dhf = plain_.getHostFunction(f); -// // This will fail if a cpp file including this header is not compiled -// // with RTTI. -// return dhf.target()->plainHF_; -// }; + } + HostFunctionType& getHostFunction(const jsi::Function& f) override { + HostFunctionType& dhf = plain_.getHostFunction(f); + // This will fail if a cpp file including this header is not compiled + // with RTTI. + return dhf.target()->plainHF_; + } bool hasNativeState(const Object& o) override { return plain_.hasNativeState(o); @@ -267,78 +297,121 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { plain_.setExternalMemoryPressure(obj, amt); } + void setPrototypeOf(const Object& object, const Value& prototype) override { + plain_.setPrototypeOf(object, prototype); + } + + Value getPrototypeOf(const Object& object) override { + return plain_.getPrototypeOf(object); + } + Value getProperty(const Object& o, const PropNameID& name) override { return plain_.getProperty(o, name); - }; + } Value getProperty(const Object& o, const String& name) override { return plain_.getProperty(o, name); - }; + } + Value getProperty(const Object& o, const Value& name) override { + return plain_.getProperty(o, name); + } bool hasProperty(const Object& o, const PropNameID& name) override { return plain_.hasProperty(o, name); - }; + } bool hasProperty(const Object& o, const String& name) override { return plain_.hasProperty(o, name); - }; + } + bool hasProperty(const Object& o, const Value& name) override { + return plain_.hasProperty(o, name); + } void setPropertyValue( const Object& o, const PropNameID& name, const Value& value) override { plain_.setPropertyValue(o, name, value); - }; + } void setPropertyValue(const Object& o, const String& name, const Value& value) override { plain_.setPropertyValue(o, name, value); - }; + } + void setPropertyValue(const Object& o, const Value& name, const Value& value) + override { + plain_.setPropertyValue(o, name, value); + } + + void deleteProperty(const Object& object, const PropNameID& name) override { + plain_.deleteProperty(object, name); + } + + void deleteProperty(const Object& object, const String& name) override { + plain_.deleteProperty(object, name); + } + + void deleteProperty(const Object& object, const Value& name) override { + plain_.deleteProperty(object, name); + } bool isArray(const Object& o) const override { return plain_.isArray(o); - }; + } bool isArrayBuffer(const Object& o) const override { return plain_.isArrayBuffer(o); - }; + } + bool isTypedArray(const Object& o) const override { + return plain_.isTypedArray(o); + } + bool isUint8Array(const Object& o) const override { + return plain_.isUint8Array(o); + } bool isFunction(const Object& o) const override { return plain_.isFunction(o); - }; + } bool isHostObject(const jsi::Object& o) const override { return plain_.isHostObject(o); - }; + } bool isHostFunction(const jsi::Function& f) const override { return plain_.isHostFunction(f); - }; + } Array getPropertyNames(const Object& o) override { return plain_.getPropertyNames(o); - }; + } WeakObject createWeakObject(const Object& o) override { return plain_.createWeakObject(o); - }; + } Value lockWeakObject(const WeakObject& wo) override { return plain_.lockWeakObject(wo); - }; + } Array createArray(size_t length) override { return plain_.createArray(length); - }; + } ArrayBuffer createArrayBuffer( std::shared_ptr buffer) override { return plain_.createArrayBuffer(std::move(buffer)); - }; + } size_t size(const Array& a) override { return plain_.size(a); - }; + } size_t size(const ArrayBuffer& ab) override { return plain_.size(ab); - }; + } uint8_t* data(const ArrayBuffer& ab) override { return plain_.data(ab); - }; + } + bool detached(const ArrayBuffer& ab) override { + return plain_.detached(ab); + } Value getValueAtIndex(const Array& a, size_t i) override { return plain_.getValueAtIndex(a, i); - }; + } void setValueAtIndexImpl(const Array& a, size_t i, const Value& value) override { plain_.setValueAtIndexImpl(a, i, value); - }; + } + + size_t push(const Array& a, const Value* elements, size_t count) override { + return plain_.push(a, elements, count); + } Function createFunctionFromHostFunction( const PropNameID& name, @@ -346,18 +419,58 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { HostFunctionType func) override { return plain_.createFunctionFromHostFunction( name, paramCount, DecoratedHostFunction(*this, std::move(func))); - }; + } Value call( const Function& f, const Value& jsThis, const Value* args, size_t count) override { return plain_.call(f, jsThis, args, count); - }; + } Value callAsConstructor(const Function& f, const Value* args, size_t count) override { return plain_.callAsConstructor(f, args, count); - }; + } + + void setRuntimeDataImpl( + const UUID& uuid, + const void* data, + void (*deleter)(const void* data)) override { + return plain_.setRuntimeDataImpl(uuid, data, deleter); + } + + const void* getRuntimeDataImpl(const UUID& uuid) override { + return plain_.getRuntimeDataImpl(uuid); + } + + std::shared_ptr tryGetMutableBuffer( + const jsi::ArrayBuffer& arrayBuffer) override { + return plain_.tryGetMutableBuffer(arrayBuffer); + } + + ArrayBuffer buffer(const TypedArray& typedArray) override { + return plain_.buffer(typedArray); + } + size_t byteOffset(const TypedArray& typedArray) override { + return plain_.byteOffset(typedArray); + } + size_t byteLength(const TypedArray& typedArray) override { + return plain_.byteLength(typedArray); + } + size_t length(const TypedArray& typedArray) override { + return plain_.length(typedArray); + } + + Uint8Array createUint8Array(size_t length) override { + return plain_.createUint8Array(length); + } + + Uint8Array createUint8Array( + const ArrayBuffer& buffer, + size_t offset, + size_t length) override { + return plain_.createUint8Array(buffer, offset, length); + } // Private data for managing scopes. Runtime::ScopeState* pushScope() override { @@ -369,20 +482,20 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { bool strictEquals(const Symbol& a, const Symbol& b) const override { return plain_.strictEquals(a, b); - }; + } bool strictEquals(const BigInt& a, const BigInt& b) const override { return plain_.strictEquals(a, b); - }; + } bool strictEquals(const String& a, const String& b) const override { return plain_.strictEquals(a, b); - }; + } bool strictEquals(const Object& a, const Object& b) const override { return plain_.strictEquals(a, b); - }; + } bool instanceOf(const Object& o, const Function& f) override { return plain_.instanceOf(o, f); - }; + } // jsi::Instrumentation methods @@ -445,6 +558,10 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { .writeBasicBlockProfileTraceToFile(fileName); } + void dumpOpcodeStats(std::ostream& os) const override { + const_cast(plain()).instrumentation().dumpOpcodeStats(os); + } + /// Dump external profiler symbols to the given file name. void dumpProfilerSymbolsToFile(const std::string& fileName) const override { const_cast(plain()).instrumentation().dumpProfilerSymbolsToFile( @@ -542,6 +659,11 @@ class WithRuntimeDecorator : public RuntimeDecorator { // the derived class. WithRuntimeDecorator(Plain& plain, With& with) : RD(plain), with_(with) {} + ICast* castInterface(const UUID& interfaceUUID) override { + Around around{with_}; + return RD::castInterface(interfaceUUID); + } + Value evaluateJavaScript( const std::shared_ptr& buffer, const std::string& sourceURL) override { @@ -574,11 +696,11 @@ class WithRuntimeDecorator : public RuntimeDecorator { std::string description() override { Around around{with_}; return RD::description(); - }; + } bool isInspectable() override { Around around{with_}; return RD::isInspectable(); - }; + } // The jsi:: prefix is necessary because MSVC compiler complains C2247: // Instrumentation is not accessible because RuntimeDecorator uses private @@ -593,90 +715,99 @@ class WithRuntimeDecorator : public RuntimeDecorator { Runtime::PointerValue* cloneSymbol(const Runtime::PointerValue* pv) override { Around around{with_}; return RD::cloneSymbol(pv); - }; + } Runtime::PointerValue* cloneBigInt(const Runtime::PointerValue* pv) override { Around around{with_}; return RD::cloneBigInt(pv); - }; + } Runtime::PointerValue* cloneString(const Runtime::PointerValue* pv) override { Around around{with_}; return RD::cloneString(pv); - }; + } Runtime::PointerValue* cloneObject(const Runtime::PointerValue* pv) override { Around around{with_}; return RD::cloneObject(pv); - }; + } Runtime::PointerValue* clonePropNameID( const Runtime::PointerValue* pv) override { Around around{with_}; return RD::clonePropNameID(pv); - }; + } PropNameID createPropNameIDFromAscii(const char* str, size_t length) override { Around around{with_}; return RD::createPropNameIDFromAscii(str, length); - }; + } PropNameID createPropNameIDFromUtf8(const uint8_t* utf8, size_t length) override { Around around{with_}; return RD::createPropNameIDFromUtf8(utf8, length); - }; + } + PropNameID createPropNameIDFromUtf16(const char16_t* utf16, size_t length) + override { + Around around{with_}; + return RD::createPropNameIDFromUtf16(utf16, length); + } PropNameID createPropNameIDFromString(const String& str) override { Around around{with_}; return RD::createPropNameIDFromString(str); - }; + } PropNameID createPropNameIDFromSymbol(const Symbol& sym) override { Around around{with_}; return RD::createPropNameIDFromSymbol(sym); - }; + } std::string utf8(const PropNameID& id) override { Around around{with_}; return RD::utf8(id); - }; + } bool compare(const PropNameID& a, const PropNameID& b) override { Around around{with_}; return RD::compare(a, b); - }; + } std::string symbolToString(const Symbol& sym) override { Around around{with_}; return RD::symbolToString(sym); - }; + } BigInt createBigIntFromInt64(int64_t i) override { Around around{with_}; return RD::createBigIntFromInt64(i); - }; + } BigInt createBigIntFromUint64(uint64_t i) override { Around around{with_}; return RD::createBigIntFromUint64(i); - }; + } bool bigintIsInt64(const BigInt& bi) override { Around around{with_}; return RD::bigintIsInt64(bi); - }; + } bool bigintIsUint64(const BigInt& bi) override { Around around{with_}; return RD::bigintIsUint64(bi); - }; + } uint64_t truncate(const BigInt& bi) override { Around around{with_}; return RD::truncate(bi); - }; + } String bigintToString(const BigInt& bi, int i) override { Around around{with_}; return RD::bigintToString(bi, i); - }; + } String createStringFromAscii(const char* str, size_t length) override { Around around{with_}; return RD::createStringFromAscii(str, length); - }; + } String createStringFromUtf8(const uint8_t* utf8, size_t length) override { Around around{with_}; return RD::createStringFromUtf8(utf8, length); - }; + } + String createStringFromUtf16(const char16_t* utf16, size_t length) override { + Around around{with_}; + return RD::createStringFromUtf16(utf16, length); + } std::string utf8(const String& s) override { Around around{with_}; return RD::utf8(s); @@ -691,134 +822,211 @@ class WithRuntimeDecorator : public RuntimeDecorator { return RD::utf16(sym); } + void getStringData( + const jsi::String& str, + void* ctx, + void ( + *cb)(void* ctx, bool ascii, const void* data, size_t num)) override { + Around around{with_}; + RD::getStringData(str, ctx, cb); + } + + void getPropNameIdData( + const jsi::PropNameID& sym, + void* ctx, + void ( + *cb)(void* ctx, bool ascii, const void* data, size_t num)) override { + Around around{with_}; + RD::getPropNameIdData(sym, ctx, cb); + } + Value createValueFromJsonUtf8(const uint8_t* json, size_t length) override { Around around{with_}; return RD::createValueFromJsonUtf8(json, length); - }; + } + + Object createObjectWithPrototype(const Value& prototype) override { + Around around{with_}; + return RD::createObjectWithPrototype(prototype); + } Object createObject() override { Around around{with_}; return RD::createObject(); - }; + } Object createObject(std::shared_ptr ho) override { Around around{with_}; return RD::createObject(std::move(ho)); - }; + } std::shared_ptr getHostObject(const jsi::Object& o) override { Around around{with_}; return RD::getHostObject(o); - }; + } HostFunctionType& getHostFunction(const jsi::Function& f) override { Around around{with_}; return RD::getHostFunction(f); - }; + } bool hasNativeState(const Object& o) override { Around around{with_}; return RD::hasNativeState(o); - }; + } std::shared_ptr getNativeState(const Object& o) override { Around around{with_}; return RD::getNativeState(o); - }; + } void setNativeState(const Object& o, std::shared_ptr state) override { Around around{with_}; RD::setNativeState(o, state); - }; + } + + void setPrototypeOf(const Object& object, const Value& prototype) override { + Around around{with_}; + RD::setPrototypeOf(object, prototype); + } + + Value getPrototypeOf(const Object& object) override { + Around around{with_}; + return RD::getPrototypeOf(object); + } Value getProperty(const Object& o, const PropNameID& name) override { Around around{with_}; return RD::getProperty(o, name); - }; + } Value getProperty(const Object& o, const String& name) override { Around around{with_}; return RD::getProperty(o, name); - }; + } + Value getProperty(const Object& o, const Value& name) override { + Around around{with_}; + return RD::getProperty(o, name); + } bool hasProperty(const Object& o, const PropNameID& name) override { Around around{with_}; return RD::hasProperty(o, name); - }; + } bool hasProperty(const Object& o, const String& name) override { Around around{with_}; return RD::hasProperty(o, name); - }; + } + bool hasProperty(const Object& o, const Value& name) override { + Around around{with_}; + return RD::hasProperty(o, name); + } void setPropertyValue( const Object& o, const PropNameID& name, const Value& value) override { Around around{with_}; RD::setPropertyValue(o, name, value); - }; + } void setPropertyValue(const Object& o, const String& name, const Value& value) override { Around around{with_}; RD::setPropertyValue(o, name, value); - }; + } + void setPropertyValue(const Object& o, const Value& name, const Value& value) + override { + Around around{with_}; + RD::setPropertyValue(o, name, value); + } + + void deleteProperty(const Object& object, const PropNameID& name) override { + Around around{with_}; + RD::deleteProperty(object, name); + } + + void deleteProperty(const Object& object, const String& name) override { + Around around{with_}; + RD::deleteProperty(object, name); + } + + void deleteProperty(const Object& object, const Value& name) override { + Around around{with_}; + RD::deleteProperty(object, name); + } bool isArray(const Object& o) const override { Around around{with_}; return RD::isArray(o); - }; + } bool isArrayBuffer(const Object& o) const override { Around around{with_}; return RD::isArrayBuffer(o); - }; + } + bool isTypedArray(const Object& o) const override { + Around around{with_}; + return RD::isTypedArray(o); + } + bool isUint8Array(const Object& o) const override { + Around around{with_}; + return RD::isUint8Array(o); + } bool isFunction(const Object& o) const override { Around around{with_}; return RD::isFunction(o); - }; + } bool isHostObject(const jsi::Object& o) const override { Around around{with_}; return RD::isHostObject(o); - }; + } bool isHostFunction(const jsi::Function& f) const override { Around around{with_}; return RD::isHostFunction(f); - }; + } Array getPropertyNames(const Object& o) override { Around around{with_}; return RD::getPropertyNames(o); - }; + } WeakObject createWeakObject(const Object& o) override { Around around{with_}; return RD::createWeakObject(o); - }; + } Value lockWeakObject(const WeakObject& wo) override { Around around{with_}; return RD::lockWeakObject(wo); - }; + } Array createArray(size_t length) override { Around around{with_}; return RD::createArray(length); - }; + } ArrayBuffer createArrayBuffer( std::shared_ptr buffer) override { return RD::createArrayBuffer(std::move(buffer)); - }; + } size_t size(const Array& a) override { Around around{with_}; return RD::size(a); - }; + } size_t size(const ArrayBuffer& ab) override { Around around{with_}; return RD::size(ab); - }; + } uint8_t* data(const ArrayBuffer& ab) override { Around around{with_}; return RD::data(ab); - }; + } + bool detached(const ArrayBuffer& ab) override { + Around around{with_}; + return RD::detached(ab); + } Value getValueAtIndex(const Array& a, size_t i) override { Around around{with_}; return RD::getValueAtIndex(a, i); - }; + } void setValueAtIndexImpl(const Array& a, size_t i, const Value& value) override { Around around{with_}; RD::setValueAtIndexImpl(a, i, value); - }; + } + size_t push(const Array& a, const Value* elements, size_t count) override { + Around around{with_}; + return RD::push(a, elements, count); + } Function createFunctionFromHostFunction( const PropNameID& name, @@ -827,7 +1035,7 @@ class WithRuntimeDecorator : public RuntimeDecorator { Around around{with_}; return RD::createFunctionFromHostFunction( name, paramCount, std::move(func)); - }; + } Value call( const Function& f, const Value& jsThis, @@ -835,12 +1043,47 @@ class WithRuntimeDecorator : public RuntimeDecorator { size_t count) override { Around around{with_}; return RD::call(f, jsThis, args, count); - }; + } Value callAsConstructor(const Function& f, const Value* args, size_t count) override { Around around{with_}; return RD::callAsConstructor(f, args, count); - }; + } + + std::shared_ptr tryGetMutableBuffer( + const jsi::ArrayBuffer& arrayBuffer) override { + Around around{with_}; + return RD::tryGetMutableBuffer(arrayBuffer); + } + + ArrayBuffer buffer(const TypedArray& typedArray) override { + Around around{with_}; + return RD::buffer(typedArray); + } + size_t byteOffset(const TypedArray& typedArray) override { + Around around{with_}; + return RD::byteOffset(typedArray); + } + size_t byteLength(const TypedArray& typedArray) override { + Around around{with_}; + return RD::byteLength(typedArray); + } + size_t length(const TypedArray& typedArray) override { + Around around{with_}; + return RD::length(typedArray); + } + + Uint8Array createUint8Array(size_t length) override { + Around around{with_}; + return RD::createUint8Array(length); + } + Uint8Array createUint8Array( + const ArrayBuffer& buffer, + size_t offset, + size_t length) override { + Around around{with_}; + return RD::createUint8Array(buffer, offset, length); + } // Private data for managing scopes. Runtime::ScopeState* pushScope() override { @@ -855,31 +1098,44 @@ class WithRuntimeDecorator : public RuntimeDecorator { bool strictEquals(const Symbol& a, const Symbol& b) const override { Around around{with_}; return RD::strictEquals(a, b); - }; + } bool strictEquals(const BigInt& a, const BigInt& b) const override { Around around{with_}; return RD::strictEquals(a, b); - }; + } bool strictEquals(const String& a, const String& b) const override { Around around{with_}; return RD::strictEquals(a, b); - }; + } bool strictEquals(const Object& a, const Object& b) const override { Around around{with_}; return RD::strictEquals(a, b); - }; + } bool instanceOf(const Object& o, const Function& f) override { Around around{with_}; return RD::instanceOf(o, f); - }; + } void setExternalMemoryPressure(const jsi::Object& obj, size_t amount) override { Around around{with_}; RD::setExternalMemoryPressure(obj, amount); - }; + } + + void setRuntimeDataImpl( + const UUID& uuid, + const void* data, + void (*deleter)(const void* data)) override { + Around around{with_}; + RD::setRuntimeDataImpl(uuid, data, deleter); + } + + const void* getRuntimeDataImpl(const UUID& uuid) override { + Around around{with_}; + return RD::getRuntimeDataImpl(uuid); + } private: // Wrap an RAII type around With& to guarantee after always happens. diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/hermes.h b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/hermes-interfaces.h similarity index 74% rename from test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/hermes.h rename to test-app/runtime/src/main/cpp/napi/hermes/include/jsi/hermes-interfaces.h index 364a645a..4655aa8c 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/hermes.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/hermes-interfaces.h @@ -26,6 +26,59 @@ namespace debugger { class Debugger; } +/// IEventLoopControl is defined by the integrator to allow the Runtime to +/// schedule some task to be run when convenient, and to keep track of "Task +/// sources". After it is set to a Runtime, the integrator must ensure that the +/// `IEventLoopControl` instance outlives the Runtime. The IEventLoopControl +/// methods may be called by the Runtime from any thread, so they must be +/// thread-safe and cannot perform any VM operations. +struct IEventLoopControl { + /// `scheduleTask` is a function used by the caller (the Runtime) to schedule + /// some \p task. The scheduled task may perform VM operations. Thus, the + /// integrator must only run the tasks when it had exclusive access to the + /// Runtime. + virtual void scheduleTask(const std::function& task) = 0; + /// Used by the caller (the Runtime) to register a new source that can + /// schedule new work via `scheduleTask`. This method return an uint64 + /// identifying the source registered. As an example, a WebWorker instance may + /// schedule a message-processing task via `scheduleTask`, and thus is + /// considered as a "task queue source". The Runtime may register each Worker + /// using this method. This is useful for the integrator to keep track of + /// active "sources". + virtual uint64_t registerTaskQueueSource() = 0; + /// Used by the caller to unregister a source when it is not allowed to invoke + /// `scheduleTasks` anymore. The source is identified by \p sourceId, which is + /// provided when the source was originally register in + /// `registerTaskQueueSource`. As an example, after WebWorker instance is + /// terminated, it will not schedule more tasks. The Runtime may unregister + /// the Worker instance, and the integrator may exit the event-loop if there + /// are no more active sources. + virtual void unregisterTaskQueueSource(uint64_t sourceId) = 0; + + protected: + ~IEventLoopControl() = default; +}; + +/// Interface for setting the IEventLoopControl in the Runtime. +struct JSI_EXPORT ISetEventLoopControl : public jsi::ICast { + public: + static constexpr jsi::UUID uuid{ + 0x7b6902e6, + 0xfd38, + 0x11f0, + 0x8de9, + 0x0242ac120002}; + + /// Configures the eventloop control mechanism using \p eventLoopControl. + virtual void setEventLoopControl(IEventLoopControl* eventLoopControl) = 0; + /// Retrieves the IEventLoopControl if it was set previously. Otherwise, + /// return nullptr. + virtual IEventLoopControl* getEventLoopControl() = 0; + + protected: + ~ISetEventLoopControl() = default; +}; + /// Interface for Hermes-specific runtime methods.The actual implementations of /// the pure virtual methods are provided by Hermes API. class JSI_EXPORT IHermes : public jsi::ICast { diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/instrumentation.h b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/instrumentation.h index 726858cc..4a88951f 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/instrumentation.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/instrumentation.h @@ -121,6 +121,9 @@ class JSI_EXPORT Instrumentation { virtual void writeBasicBlockProfileTraceToFile( const std::string& fileName) const = 0; + /// Write the opcode stats to the given stream. + virtual void dumpOpcodeStats(std::ostream& os) const = 0; + /// Dump external profiler symbols to the given file name. virtual void dumpProfilerSymbolsToFile(const std::string& fileName) const = 0; }; diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/jsi-inl.h b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/jsi-inl.h index 111a4702..6a29f647 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/jsi-inl.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/jsi-inl.h @@ -11,48 +11,48 @@ namespace facebook { namespace jsi { namespace detail { -inline Value toValue(Runtime&, std::nullptr_t) { +inline Value toValue(IRuntime&, std::nullptr_t) { return Value::null(); } -inline Value toValue(Runtime&, bool b) { +inline Value toValue(IRuntime&, bool b) { return Value(b); } -inline Value toValue(Runtime&, double d) { +inline Value toValue(IRuntime&, double d) { return Value(d); } -inline Value toValue(Runtime&, float f) { +inline Value toValue(IRuntime&, float f) { return Value(static_cast(f)); } -inline Value toValue(Runtime&, int i) { +inline Value toValue(IRuntime&, int i) { return Value(i); } -inline Value toValue(Runtime& runtime, const char* str) { +inline Value toValue(IRuntime& runtime, const char* str) { return String::createFromAscii(runtime, str); } -inline Value toValue(Runtime& runtime, const std::string& str) { +inline Value toValue(IRuntime& runtime, const std::string& str) { return String::createFromUtf8(runtime, str); } template -inline Value toValue(Runtime& runtime, const T& other) { +inline Value toValue(IRuntime& runtime, const T& other) { static_assert( std::is_base_of::value, "This type cannot be converted to Value"); return Value(runtime, other); } -inline Value toValue(Runtime& runtime, const Value& value) { +inline Value toValue(IRuntime& runtime, const Value& value) { return Value(runtime, value); } -inline Value&& toValue(Runtime&, Value&& value) { +inline Value&& toValue(IRuntime&, Value&& value) { return std::move(value); } -inline PropNameID toPropNameID(Runtime& runtime, const char* name) { +inline PropNameID toPropNameID(IRuntime& runtime, const char* name) { return PropNameID::forAscii(runtime, name); } -inline PropNameID toPropNameID(Runtime& runtime, const std::string& name) { +inline PropNameID toPropNameID(IRuntime& runtime, const std::string& name) { return PropNameID::forUtf8(runtime, name); } -inline PropNameID&& toPropNameID(Runtime&, PropNameID&& name) { +inline PropNameID&& toPropNameID(IRuntime&, PropNameID&& name) { return std::move(name); } @@ -84,59 +84,110 @@ inline const Runtime::PointerValue* Runtime::getPointerValue( return value.data_.pointer.ptr_; } -inline Value Object::getProperty(Runtime& runtime, const char* name) const { +inline void Runtime::setRuntimeData( + const UUID& dataUUID, + const std::shared_ptr& data) { + auto* dataPtr = new std::shared_ptr(data); + setRuntimeDataImpl(dataUUID, dataPtr, [](const void* data) { + delete (const std::shared_ptr*)data; + }); +} + +inline std::shared_ptr Runtime::getRuntimeData(const UUID& dataUUID) { + auto* data = (const std::shared_ptr*)getRuntimeDataImpl(dataUUID); + return data ? *data : nullptr; +} + +Value Object::getPrototype(IRuntime& runtime) const { + return runtime.getPrototypeOf(*this); +} + +inline Value Object::getProperty(IRuntime& runtime, const char* name) const { return getProperty(runtime, String::createFromAscii(runtime, name)); } -inline Value Object::getProperty(Runtime& runtime, const String& name) const { +inline Value Object::getProperty(IRuntime& runtime, const String& name) const { return runtime.getProperty(*this, name); } -inline Value Object::getProperty(Runtime& runtime, const PropNameID& name) +inline Value Object::getProperty(IRuntime& runtime, const PropNameID& name) const { return runtime.getProperty(*this, name); } -inline bool Object::hasProperty(Runtime& runtime, const char* name) const { +inline Value Object::getProperty(IRuntime& runtime, const Value& name) const { + return runtime.getProperty(*this, name); +} + +inline bool Object::hasProperty(IRuntime& runtime, const char* name) const { return hasProperty(runtime, String::createFromAscii(runtime, name)); } -inline bool Object::hasProperty(Runtime& runtime, const String& name) const { +inline bool Object::hasProperty(IRuntime& runtime, const String& name) const { return runtime.hasProperty(*this, name); } -inline bool Object::hasProperty(Runtime& runtime, const PropNameID& name) +inline bool Object::hasProperty(IRuntime& runtime, const PropNameID& name) const { return runtime.hasProperty(*this, name); } +inline bool Object::hasProperty(IRuntime& runtime, const Value& name) const { + return runtime.hasProperty(*this, name); +} + template -void Object::setProperty(Runtime& runtime, const char* name, T&& value) const { +void Object::setProperty(IRuntime& runtime, const char* name, T&& value) const { setProperty( runtime, String::createFromAscii(runtime, name), std::forward(value)); } template -void Object::setProperty(Runtime& runtime, const String& name, T&& value) +void Object::setProperty(IRuntime& runtime, const String& name, T&& value) + const { + setPropertyValue( + runtime, name, detail::toValue(runtime, std::forward(value))); +} + +template +void Object::setProperty(IRuntime& runtime, const PropNameID& name, T&& value) const { setPropertyValue( runtime, name, detail::toValue(runtime, std::forward(value))); } template -void Object::setProperty(Runtime& runtime, const PropNameID& name, T&& value) +void Object::setProperty(IRuntime& runtime, const Value& name, T&& value) const { setPropertyValue( runtime, name, detail::toValue(runtime, std::forward(value))); } -inline Array Object::getArray(Runtime& runtime) const& { +inline void Object::deleteProperty(IRuntime& runtime, const char* name) const { + deleteProperty(runtime, String::createFromAscii(runtime, name)); +} + +inline void Object::deleteProperty(IRuntime& runtime, const String& name) + const { + runtime.deleteProperty(*this, name); +} + +inline void Object::deleteProperty(IRuntime& runtime, const PropNameID& name) + const { + runtime.deleteProperty(*this, name); +} + +inline void Object::deleteProperty(IRuntime& runtime, const Value& name) const { + runtime.deleteProperty(*this, name); +} + +inline Array Object::getArray(IRuntime& runtime) const& { assert(runtime.isArray(*this)); (void)runtime; // when assert is disabled we need to mark this as used return Array(runtime.cloneObject(ptr_)); } -inline Array Object::getArray(Runtime& runtime) && { +inline Array Object::getArray(IRuntime& runtime) && { assert(runtime.isArray(*this)); (void)runtime; // when assert is disabled we need to mark this as used Runtime::PointerValue* value = ptr_; @@ -144,13 +195,13 @@ inline Array Object::getArray(Runtime& runtime) && { return Array(value); } -inline ArrayBuffer Object::getArrayBuffer(Runtime& runtime) const& { +inline ArrayBuffer Object::getArrayBuffer(IRuntime& runtime) const& { assert(runtime.isArrayBuffer(*this)); (void)runtime; // when assert is disabled we need to mark this as used return ArrayBuffer(runtime.cloneObject(ptr_)); } -inline ArrayBuffer Object::getArrayBuffer(Runtime& runtime) && { +inline ArrayBuffer Object::getArrayBuffer(IRuntime& runtime) && { assert(runtime.isArrayBuffer(*this)); (void)runtime; // when assert is disabled we need to mark this as used Runtime::PointerValue* value = ptr_; @@ -158,12 +209,22 @@ inline ArrayBuffer Object::getArrayBuffer(Runtime& runtime) && { return ArrayBuffer(value); } -inline Function Object::getFunction(Runtime& runtime) const& { +inline TypedArray Object::getTypedArray(IRuntime& runtime) const& { + assert(runtime.isTypedArray(*this)); + return TypedArray(runtime.cloneObject(ptr_)); +} + +inline Uint8Array Object::getUint8Array(IRuntime& runtime) const& { + assert(runtime.isUint8Array(*this)); + return Uint8Array(runtime.cloneObject(ptr_)); +} + +inline Function Object::getFunction(IRuntime& runtime) const& { assert(runtime.isFunction(*this)); return Function(runtime.cloneObject(ptr_)); } -inline Function Object::getFunction(Runtime& runtime) && { +inline Function Object::getFunction(IRuntime& runtime) && { assert(runtime.isFunction(*this)); (void)runtime; // when assert is disabled we need to mark this as used Runtime::PointerValue* value = ptr_; @@ -172,24 +233,24 @@ inline Function Object::getFunction(Runtime& runtime) && { } template -inline bool Object::isHostObject(Runtime& runtime) const { +inline bool Object::isHostObject(IRuntime& runtime) const { return runtime.isHostObject(*this) && std::dynamic_pointer_cast(runtime.getHostObject(*this)); } template <> -inline bool Object::isHostObject(Runtime& runtime) const { +inline bool Object::isHostObject(IRuntime& runtime) const { return runtime.isHostObject(*this); } template -inline std::shared_ptr Object::getHostObject(Runtime& runtime) const { +inline std::shared_ptr Object::getHostObject(IRuntime& runtime) const { assert(isHostObject(runtime)); return std::static_pointer_cast(runtime.getHostObject(*this)); } template -inline std::shared_ptr Object::asHostObject(Runtime& runtime) const { +inline std::shared_ptr Object::asHostObject(IRuntime& runtime) const { if (!isHostObject(runtime)) { detail::throwOrDie( "Object is not a HostObject of desired type"); @@ -199,59 +260,59 @@ inline std::shared_ptr Object::asHostObject(Runtime& runtime) const { template <> inline std::shared_ptr Object::getHostObject( - Runtime& runtime) const { + IRuntime& runtime) const { assert(runtime.isHostObject(*this)); return runtime.getHostObject(*this); } template -inline bool Object::hasNativeState(Runtime& runtime) const { +inline bool Object::hasNativeState(IRuntime& runtime) const { return runtime.hasNativeState(*this) && std::dynamic_pointer_cast(runtime.getNativeState(*this)); } template <> -inline bool Object::hasNativeState(Runtime& runtime) const { +inline bool Object::hasNativeState(IRuntime& runtime) const { return runtime.hasNativeState(*this); } template -inline std::shared_ptr Object::getNativeState(Runtime& runtime) const { +inline std::shared_ptr Object::getNativeState(IRuntime& runtime) const { assert(hasNativeState(runtime)); return std::static_pointer_cast(runtime.getNativeState(*this)); } inline void Object::setNativeState( - Runtime& runtime, + IRuntime& runtime, std::shared_ptr state) const { runtime.setNativeState(*this, state); } -inline void Object::setExternalMemoryPressure(Runtime& runtime, size_t amt) +inline void Object::setExternalMemoryPressure(IRuntime& runtime, size_t amt) const { runtime.setExternalMemoryPressure(*this, amt); } -inline Array Object::getPropertyNames(Runtime& runtime) const { +inline Array Object::getPropertyNames(IRuntime& runtime) const { return runtime.getPropertyNames(*this); } -inline Value WeakObject::lock(Runtime& runtime) const { +inline Value WeakObject::lock(IRuntime& runtime) const { return runtime.lockWeakObject(*this); } template -void Array::setValueAtIndex(Runtime& runtime, size_t i, T&& value) const { +void Array::setValueAtIndex(IRuntime& runtime, size_t i, T&& value) const { setValueAtIndexImpl( runtime, i, detail::toValue(runtime, std::forward(value))); } -inline Value Array::getValueAtIndex(Runtime& runtime, size_t i) const { +inline Value Array::getValueAtIndex(IRuntime& runtime, size_t i) const { return runtime.getValueAtIndex(*this, i); } inline Function Function::createFromHostFunction( - Runtime& runtime, + IRuntime& runtime, const jsi::PropNameID& name, unsigned int paramCount, jsi::HostFunctionType func) { @@ -259,18 +320,19 @@ inline Function Function::createFromHostFunction( name, paramCount, std::move(func)); } -inline Value Function::call(Runtime& runtime, const Value* args, size_t count) +inline Value Function::call(IRuntime& runtime, const Value* args, size_t count) const { return runtime.call(*this, Value::undefined(), args, count); } -inline Value Function::call(Runtime& runtime, std::initializer_list args) - const { +inline Value Function::call( + IRuntime& runtime, + std::initializer_list args) const { return call(runtime, args.begin(), args.size()); } template -inline Value Function::call(Runtime& runtime, Args&&... args) const { +inline Value Function::call(IRuntime& runtime, Args&&... args) const { // A more awesome version of this would be able to create raw values // which can be used directly without wrapping and unwrapping, but // this will do for now. @@ -278,7 +340,7 @@ inline Value Function::call(Runtime& runtime, Args&&... args) const { } inline Value Function::callWithThis( - Runtime& runtime, + IRuntime& runtime, const Object& jsThis, const Value* args, size_t count) const { @@ -286,7 +348,7 @@ inline Value Function::callWithThis( } inline Value Function::callWithThis( - Runtime& runtime, + IRuntime& runtime, const Object& jsThis, std::initializer_list args) const { return callWithThis(runtime, jsThis, args.begin(), args.size()); @@ -294,7 +356,7 @@ inline Value Function::callWithThis( template inline Value Function::callWithThis( - Runtime& runtime, + IRuntime& runtime, const Object& jsThis, Args&&... args) const { // A more awesome version of this would be able to create raw values @@ -305,14 +367,30 @@ inline Value Function::callWithThis( } template -inline Array Array::createWithElements(Runtime& runtime, Args&&... args) { +inline Array Array::createWithElements(IRuntime& runtime, Args&&... args) { return createWithElements( runtime, {detail::toValue(runtime, std::forward(args))...}); } +template +inline size_t Array::push(IRuntime& runtime, Args&&... args) { + return push(runtime, {detail::toValue(runtime, std::forward(args))...}); +} + +inline size_t Array::push( + IRuntime& runtime, + std::initializer_list elements) { + return push(runtime, elements.begin(), elements.size()); +} + +inline size_t +Array::push(IRuntime& runtime, const Value* elements, size_t count) { + return runtime.push(*this, elements, count); +} + template inline std::vector PropNameID::names( - Runtime& runtime, + IRuntime& runtime, Args&&... args) { return names({detail::toPropNameID(runtime, std::forward(args))...}); } @@ -329,26 +407,26 @@ inline std::vector PropNameID::names( } inline Value Function::callAsConstructor( - Runtime& runtime, + IRuntime& runtime, const Value* args, size_t count) const { return runtime.callAsConstructor(*this, args, count); } inline Value Function::callAsConstructor( - Runtime& runtime, + IRuntime& runtime, std::initializer_list args) const { return callAsConstructor(runtime, args.begin(), args.size()); } template -inline Value Function::callAsConstructor(Runtime& runtime, Args&&... args) +inline Value Function::callAsConstructor(IRuntime& runtime, Args&&... args) const { return callAsConstructor( runtime, {detail::toValue(runtime, std::forward(args))...}); } -String BigInt::toString(Runtime& runtime, int radix) const { +String BigInt::toString(IRuntime& runtime, int radix) const { return runtime.bigintToString(*this, radix); } diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/jsi.h b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/jsi.h index be48bb82..bf98028f 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/jsi.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/jsi.h @@ -8,6 +8,8 @@ #pragma once #include +#include +#include #include #include #include @@ -31,6 +33,107 @@ class FBJSRuntime; namespace facebook { namespace jsi { +/// UUID version 1 implementation. This should be constructed with constant +/// arguments to identify fixed UUIDs. +class JSI_EXPORT UUID { + public: + // Construct from raw parts + constexpr UUID( + uint32_t timeLow, + uint16_t timeMid, + uint16_t timeHighAndVersion, + uint16_t variantAndClockSeq, + uint64_t node) + : high( + ((uint64_t)(timeLow) << 32) | ((uint64_t)(timeMid) << 16) | + ((uint64_t)(timeHighAndVersion))), + low(((uint64_t)(variantAndClockSeq) << 48) | node) {} + + // Default constructor (zero UUID) + constexpr UUID() : high(0), low(0) {} + + constexpr UUID(const UUID&) = default; + constexpr UUID& operator=(const UUID&) = default; + + constexpr bool operator==(const UUID& other) const { + return high == other.high && low == other.low; + } + constexpr bool operator!=(const UUID& other) const { + return !(*this == other); + } + + // Ordering (for std::map, sorting, etc.) + constexpr bool operator<(const UUID& other) const { + return (high < other.high) || (high == other.high && low < other.low); + } + + // Hash support for UUID (for unordered_map compatibility) + struct Hash { + std::size_t operator()(const UUID& uuid) const noexcept { + return std::hash{}(uuid.high) ^ + (std::hash{}(uuid.low) << 1); + } + }; + + // UUID format: 8-4-4-4-12 + std::string toString() const { + std::string buffer(36, ' '); + std::snprintf( + buffer.data(), + buffer.size() + 1, + "%08x-%04x-%04x-%04x-%012llx", + getTimeLow(), + getTimeMid(), + getTimeHighAndVersion(), + getVariantAndClockSeq(), + (unsigned long long)getNode()); + return buffer; + } + + constexpr uint32_t getTimeLow() const { + return (uint32_t)(high >> 32); + } + + constexpr uint16_t getTimeMid() const { + return (uint16_t)(high >> 16); + } + + constexpr uint16_t getTimeHighAndVersion() const { + return (uint16_t)high; + } + + constexpr uint16_t getVariantAndClockSeq() const { + return (uint16_t)(low >> 48); + } + + constexpr uint64_t getNode() const { + return low & 0xFFFFFFFFFFFF; + } + + private: + uint64_t high; + uint64_t low; +}; + +/// Base interface that all JSI interfaces inherit from. Users should not try to +/// manipulate this base type directly, and should use castInterface to get the +/// appropriate subtype. +struct JSI_EXPORT ICast { + /// If the current object can be cast into the interface specified by \p + /// interfaceUUID, return a pointer to the object. Otherwise, return a null + /// pointer. + /// The returned interface has the same lifetime as the underlying object. It + /// does not need to be released when not needed. + virtual ICast* castInterface(const UUID& interfaceUUID) = 0; + + protected: + /// Interfaces are not destructible, thus the destructor is intentionally + /// protected to prevent delete calls on the interface. + /// Additionally, the destructor is non-virtual to reduce the vtable + /// complexity from inheritance. + ~ICast() = default; +}; + /// Base class for buffers of data or bytecode that need to be passed to the /// runtime. The buffer is expected to be fully immutable, so the result of /// size(), data(), and the contents of the pointer returned by data() must not @@ -80,6 +183,7 @@ class JSI_EXPORT PreparedJavaScript { virtual ~PreparedJavaScript() = 0; }; +class IRuntime; class Runtime; class Pointer; class PropNameID; @@ -96,6 +200,8 @@ class Instrumentation; class Scope; class JSIException; class JSError; +class TypedArray; +class Uint8Array; /// A function which has this type can be registered as a function /// callable from JavaScript using Function::createFromHostFunction(). @@ -119,7 +225,7 @@ class JSI_EXPORT HostObject { // object. (This may be as late as when the Runtime is shut down.) // You have no control over which thread it is called on. This will // be called from inside the GC, so it is unsafe to do any VM - // operations which require a Runtime&. Derived classes' dtors + // operations which require a IRuntime&. Derived classes' dtors // should also avoid doing anything expensive. Calling the dtor on // a jsi object is explicitly ok. If you want to do JS operations, // or any nontrivial work, you should add it to a work queue, and @@ -151,27 +257,92 @@ class JSI_EXPORT NativeState { virtual ~NativeState(); }; -/// Represents a JS runtime. Movable, but not copyable. Note that -/// this object may not be thread-aware, but cannot be used safely from -/// multiple threads at once. The application is responsible for -/// ensuring that it is used safely. This could mean using the -/// Runtime from a single thread, using a mutex, doing all work on a -/// serial queue, etc. This restriction applies to the methods of -/// this class, and any method in the API which take a Runtime& as an -/// argument. Destructors (all but ~Scope), operators, or other methods -/// which do not take Runtime& as an argument are safe to call from any -/// thread, but it is still forbidden to make write operations on a single -/// instance of any class from more than one thread. In addition, to -/// make shutdown safe, destruction of objects associated with the Runtime -/// must be destroyed before the Runtime is destroyed, or from the -/// destructor of a managed HostObject or HostFunction. Informally, this -/// means that the main source of unsafe behavior is to hold a jsi object -/// in a non-Runtime-managed object, and not clean it up before the Runtime -/// is shut down. If your lifecycle is such that avoiding this is hard, -/// you will probably need to do use your own locks. -class JSI_EXPORT Runtime { +// JSI_UNSTABLE gates features that will be released with a Hermes version in +// the future. Until released, these features may be subject to change. After +// release, these features will be moved out of JSI_UNSTABLE and become frozen. +#ifdef JSI_UNSTABLE +/// Opaque class that is used to store serialized object from a runtime. The +/// lifetime of this object is orthogonal to the original runtime object, and +/// may outlive the original object. +class JSI_EXPORT Serialized { + public: + /// Uses \p secretAddr to validate if the Serialized data is supported. If so, + /// return the pointer to the underlying serialized data. Otherwise, return a + /// nullptr. This should be used by the runtime to deserialize the data. + virtual void* getPrivate(const void* secretAddr) = 0; + virtual ~Serialized(); +}; + +/// Provides a set of APIs that allows copying objects between different +/// runtime instances. The runtimes instances must be of the same type. As an +/// example, a serialized object from Hermes runtime may only be deserialized by +/// another Hermes runtime. +class JSI_EXPORT ISerialization : public ICast { public: - virtual ~Runtime(); + static constexpr jsi::UUID uuid{ + 0xd40fe0ec, + 0xa47c, + 0x42c9, + 0x8c09, + 0x661aeab832d8}; + + /// Serializes the given Value \p value using the structured clone algorithm. + /// It returns a shared pointer of an opaque Serialized object that can be + /// deserialized multiple times. The lifetime of the Serialized object is not + /// tied to the lifetime of the original object. + virtual std::shared_ptr serialize(const Value& value) = 0; + + /// Given a Serialized object provided by \p serialized, deserialize it using + /// the structured clone algorithm into a JS value in the current runtime. + /// Returns the deserialized JS value. + virtual Value deserialize(const std::shared_ptr& serialized) = 0; + + /// Serializes the given jsi::Value \p value using the structured clone + /// algorithm. \p transferList must be a JS Array. Given the length property + /// of \p transferList, this API will transfer everything at index [0, length + /// - 1] to the serialized object. The transferred values will no longer be + /// usable in the original runtime. It returns a unique pointer of an opaque + /// Serialized object that can be deserialized once only by + /// deserializeWithTransfer. The lifetime of the Serialized object is not tied + /// to the lifetime of the original object. + virtual std::unique_ptr serializeWithTransfer( + const Value& value, + const Array& transferList) = 0; + + /// Using the structure clone algorithm, deserialize the object provided by \p + /// serialized into a JS value in the current runtime. \p serialized must be + /// created by serializeWithTransfer. If the current runtime does not support + /// the serialization scheme in \p serialized, then this method will throw and + /// \p serialized will remain unmodified. Otherwise, this will consume the + /// serialized data entirely and make the serialized objects in the current + /// runtime. Any transferred values in the serialized object will be owned by + /// the current runtime. + /// This method returns an Array containing the deserialized values, where + /// the first element is the value passed into serializeWithTransfer, + /// followed by all transferred values. + virtual Array deserializeWithTransfer( + std::unique_ptr& serialized) = 0; + + protected: + ~ISerialization() = default; +}; + +#endif // JSI_UNSTABLE + +/// An interface that provides various functionalities of the JS runtime. +/// The APIs must not be called from multiple threads concurrently. It is the +/// user's responsibility ensure thread safety when using IRuntime. +/// Users should cast their runtime to IRuntime to access these APIs. However, +/// for backward compatibility, these APIs are also accessible via the Runtime +/// object directly. +class JSI_EXPORT IRuntime : public ICast { + public: + static constexpr jsi::UUID uuid{ + 0xc2e8e22e, + 0xd7a6, + 0x11f0, + 0x8de9, + 0x0242ac120002}; /// Evaluates the given JavaScript \c buffer. \c sourceURL is used /// to annotate the stack trace if there is an exception. The @@ -265,22 +436,31 @@ class JSI_EXPORT Runtime { /// \return an interface to extract metrics from this \c Runtime. The default /// implementation of this function returns an \c Instrumentation instance /// which returns no metrics. - virtual Instrumentation& instrumentation(); - - protected: - friend class Pointer; - friend class PropNameID; - friend class Symbol; - friend class BigInt; - friend class String; - friend class Object; - friend class WeakObject; - friend class Array; - friend class ArrayBuffer; - friend class Function; - friend class Value; - friend class Scope; - friend class JSError; + virtual Instrumentation& instrumentation() = 0; + + /// Stores the pointer \p data with the \p dataUUID in the runtime. This can + /// be used to store some custom data within the runtime. When the runtime is + /// destroyed, or if an entry at an existing key is overwritten, the runtime + /// will release its ownership of the held object. + virtual void setRuntimeData( + const UUID& dataUUID, + const std::shared_ptr& data) = 0; + /// Returns the data associated with the \p uuid in the runtime. If there's no + /// data associated with the uuid, return a null pointer. + virtual std::shared_ptr getRuntimeData(const UUID& dataUUID) = 0; + + /// Stores the pointer \p data with the \p uuid in the runtime. This can be + /// used to store some custom data within the runtime. When the runtime is + /// destroyed, or if an entry at an existing key is overwritten, the runtime + /// will release its ownership by calling \p deleter. + virtual void setRuntimeDataImpl( + const UUID& dataUUID, + const void* data, + void (*deleter)(const void* data)) = 0; + + /// Returns the data associated with the \p uuid in the runtime. If there's no + /// data associated with the uuid, return a null pointer. + virtual const void* getRuntimeDataImpl(const UUID& dataUUID) = 0; // Potential optimization: avoid the cloneFoo() virtual dispatch, // and instead just fix the number of fields, and copy them, since @@ -294,11 +474,11 @@ class JSI_EXPORT Runtime { virtual ~PointerValue() = default; }; - virtual PointerValue* cloneSymbol(const Runtime::PointerValue* pv) = 0; - virtual PointerValue* cloneBigInt(const Runtime::PointerValue* pv) = 0; - virtual PointerValue* cloneString(const Runtime::PointerValue* pv) = 0; - virtual PointerValue* cloneObject(const Runtime::PointerValue* pv) = 0; - virtual PointerValue* clonePropNameID(const Runtime::PointerValue* pv) = 0; + virtual PointerValue* cloneSymbol(const IRuntime::PointerValue* pv) = 0; + virtual PointerValue* cloneBigInt(const IRuntime::PointerValue* pv) = 0; + virtual PointerValue* cloneString(const IRuntime::PointerValue* pv) = 0; + virtual PointerValue* cloneObject(const IRuntime::PointerValue* pv) = 0; + virtual PointerValue* clonePropNameID(const IRuntime::PointerValue* pv) = 0; virtual PropNameID createPropNameIDFromAscii( const char* str, @@ -306,6 +486,9 @@ class JSI_EXPORT Runtime { virtual PropNameID createPropNameIDFromUtf8( const uint8_t* utf8, size_t length) = 0; + virtual PropNameID createPropNameIDFromUtf16( + const char16_t* utf16, + size_t length) = 0; virtual PropNameID createPropNameIDFromString(const String& str) = 0; virtual PropNameID createPropNameIDFromSymbol(const Symbol& sym) = 0; virtual std::string utf8(const PropNameID&) = 0; @@ -322,36 +505,55 @@ class JSI_EXPORT Runtime { virtual String createStringFromAscii(const char* str, size_t length) = 0; virtual String createStringFromUtf8(const uint8_t* utf8, size_t length) = 0; + virtual String createStringFromUtf16( + const char16_t* utf16, + size_t length) = 0; virtual std::string utf8(const String&) = 0; // \return a \c Value created from a utf8-encoded JSON string. The default // implementation creates a \c String and invokes JSON.parse. - virtual Value createValueFromJsonUtf8(const uint8_t* json, size_t length); + virtual Value createValueFromJsonUtf8(const uint8_t* json, size_t length) = 0; virtual Object createObject() = 0; virtual Object createObject(std::shared_ptr ho) = 0; virtual std::shared_ptr getHostObject(const jsi::Object&) = 0; virtual HostFunctionType& getHostFunction(const jsi::Function&) = 0; + // Creates a new Object with the custom prototype + virtual Object createObjectWithPrototype(const Value& prototype) = 0; + virtual bool hasNativeState(const jsi::Object&) = 0; virtual std::shared_ptr getNativeState(const jsi::Object&) = 0; virtual void setNativeState( const jsi::Object&, std::shared_ptr state) = 0; + virtual void setPrototypeOf(const Object& object, const Value& prototype) = 0; + virtual Value getPrototypeOf(const Object& object) = 0; + virtual Value getProperty(const Object&, const PropNameID& name) = 0; virtual Value getProperty(const Object&, const String& name) = 0; + virtual Value getProperty(const Object&, const Value& name) = 0; virtual bool hasProperty(const Object&, const PropNameID& name) = 0; virtual bool hasProperty(const Object&, const String& name) = 0; + virtual bool hasProperty(const Object&, const Value& name) = 0; virtual void setPropertyValue( const Object&, const PropNameID& name, const Value& value) = 0; virtual void setPropertyValue(const Object&, const String& name, const Value& value) = 0; + virtual void + setPropertyValue(const Object&, const Value& name, const Value& value) = 0; + + virtual void deleteProperty(const Object&, const PropNameID& name) = 0; + virtual void deleteProperty(const Object&, const String& name) = 0; + virtual void deleteProperty(const Object&, const Value& name) = 0; virtual bool isArray(const Object&) const = 0; virtual bool isArrayBuffer(const Object&) const = 0; + virtual bool isTypedArray(const Object&) const = 0; + virtual bool isUint8Array(const Object&) const = 0; virtual bool isFunction(const Object&) const = 0; virtual bool isHostObject(const jsi::Object&) const = 0; virtual bool isHostFunction(const jsi::Function&) const = 0; @@ -366,9 +568,11 @@ class JSI_EXPORT Runtime { virtual size_t size(const Array&) = 0; virtual size_t size(const ArrayBuffer&) = 0; virtual uint8_t* data(const ArrayBuffer&) = 0; + virtual bool detached(const ArrayBuffer&) = 0; virtual Value getValueAtIndex(const Array&, size_t i) = 0; virtual void setValueAtIndexImpl(const Array&, size_t i, const Value& value) = 0; + virtual size_t push(const Array&, const Value*, size_t) = 0; virtual Function createFunctionFromHostFunction( const PropNameID& name, @@ -384,8 +588,8 @@ class JSI_EXPORT Runtime { // Private data for managing scopes. struct ScopeState; - virtual ScopeState* pushScope(); - virtual void popScope(ScopeState*); + virtual ScopeState* pushScope() = 0; + virtual void popScope(ScopeState*) = 0; virtual bool strictEquals(const Symbol& a, const Symbol& b) const = 0; virtual bool strictEquals(const BigInt& a, const BigInt& b) const = 0; @@ -399,8 +603,210 @@ class JSI_EXPORT Runtime { const jsi::Object& obj, size_t amount) = 0; - virtual std::u16string utf16(const String& str); - virtual std::u16string utf16(const PropNameID& sym); + virtual std::u16string utf16(const String& str) = 0; + virtual std::u16string utf16(const PropNameID& sym) = 0; + + /// Invokes the provided callback \p cb with the String content in \p str. + /// The callback must take in three arguments: bool ascii, const void* data, + /// and size_t num, respectively. \p ascii indicates whether the \p data + /// passed to the callback should be interpreted as a pointer to a sequence of + /// \p num ASCII characters or UTF16 characters. Depending on the internal + /// representation of the string, the function may invoke the callback + /// multiple times, with a different format on each invocation. The callback + /// must not access runtime functionality, as any operation on the runtime may + /// invalidate the data pointers. + virtual void getStringData( + const jsi::String& str, + void* ctx, + void (*cb)(void* ctx, bool ascii, const void* data, size_t num)) = 0; + + /// Invokes the provided callback \p cb with the PropNameID content in \p sym. + /// The callback must take in three arguments: bool ascii, const void* data, + /// and size_t num, respectively. \p ascii indicates whether the \p data + /// passed to the callback should be interpreted as a pointer to a sequence of + /// \p num ASCII characters or UTF16 characters. Depending on the internal + /// representation of the string, the function may invoke the callback + /// multiple times, with a different format on each invocation. The callback + /// must not access runtime functionality, as any operation on the runtime may + /// invalidate the data pointers. + virtual void getPropNameIdData( + const jsi::PropNameID& sym, + void* ctx, + void (*cb)(void* ctx, bool ascii, const void* data, size_t num)) = 0; + + /// If possible, returns the MutableBuffer representing \p arrayBuffer's + /// underlying data, else return a nullptr. Importantly, the returned + /// MutableBuffer directly points to \p arrayBuffer's data instead of copying + /// the data over. The data's lifetime is valid for the lifetime of + /// MutableBuffer, which is orthogonal from \p arrayBuffer. + virtual std::shared_ptr tryGetMutableBuffer( + const jsi::ArrayBuffer& arrayBuffer) = 0; + + /// \return the underlying buffer of the \p typedArray. + virtual ArrayBuffer buffer(const TypedArray& typedArray) = 0; + /// \return the 'byteOffset' property of the \p typedArray. + virtual size_t byteOffset(const TypedArray& typedArray) = 0; + /// \return the 'byteLength' property of the \p typedArray. + virtual size_t byteLength(const TypedArray& typedArray) = 0; + /// \return the 'length; property of the \p typedArray. + virtual size_t length(const TypedArray& typedArray) = 0; + + /// Create a JS UInt8Array with length \p length. + virtual Uint8Array createUint8Array(size_t length) = 0; + /// Create a JS UInt8Array using the ArrayBuffer \p buffer starting at byte + /// offset \p offset and length \p length. + virtual Uint8Array + createUint8Array(const ArrayBuffer& buffer, size_t offset, size_t length) = 0; + + /// Create a new Error object with the message property set to \p message. + virtual Value createError(const String& msg) = 0; + /// Create a new EvalError object with the message property set to \p message. + virtual Value createEvalError(const String& msg) = 0; + /// Create a new RangeError object with the message property set to \p + /// message. + virtual Value createRangeError(const String& msg) = 0; + /// Create a new ReferenceError object with the message property set to \p + /// message. + virtual Value createReferenceError(const String& msg) = 0; + /// Create a new SyntaxError object with the message property set to \p + /// message. + virtual Value createSyntaxError(const String& msg) = 0; + /// Create a new TypeError object with the message property set to \p message. + virtual Value createTypeError(const String& msg) = 0; + /// Create a new URIError object with the message property set to \p message. + virtual Value createURIError(const String& msg) = 0; + + /// Returns the number of code units in the string, equivalent to 'length' + /// property of a JS string. + virtual size_t length(const String& str) = 0; + + protected: + virtual ~IRuntime() = default; +}; + +/// Represents a JS runtime. Movable, but not copyable. Note that +/// this object may not be thread-aware, but cannot be used safely from +/// multiple threads at once. The application is responsible for +/// ensuring that it is used safely. This could mean using the +/// Runtime from a single thread, using a mutex, doing all work on a +/// serial queue, etc. This restriction applies to the methods of +/// this class, and any method in the API which take a Runtime& as an +/// argument. Destructors (all but ~Scope), operators, or other methods +/// which do not take Runtime& as an argument are safe to call from any +/// thread, but it is still forbidden to make write operations on a single +/// instance of any class from more than one thread. In addition, to +/// make shutdown safe, destruction of objects associated with the Runtime +/// must be destroyed before the Runtime is destroyed, or from the +/// destructor of a managed HostObject or HostFunction. Informally, this +/// means that the main source of unsafe behavior is to hold a jsi object +/// in a non-Runtime-managed object, and not clean it up before the Runtime +/// is shut down. If your lifecycle is such that avoiding this is hard, +/// you will probably need to do use your own locks. +class JSI_EXPORT Runtime : public IRuntime { + public: + virtual ~Runtime() override; + + using IRuntime::getProperty; + using IRuntime::hasProperty; + using IRuntime::setPropertyValue; + ICast* castInterface(const UUID& uuid) override; + + Instrumentation& instrumentation() override; + + /// Stores the pointer \p data with the \p uuid in the runtime. This can be + /// used to store some custom data within the runtime. When the runtime is + /// destroyed, or if an entry at an existing key is overwritten, the runtime + /// will release its ownership of the held object. + void setRuntimeData(const UUID& uuid, const std::shared_ptr& data) + override; + + /// Returns the data associated with the \p uuid in the runtime. If there's no + /// data associated with the uuid, return a null pointer. + std::shared_ptr getRuntimeData(const UUID& uuid) override; + + Value getProperty(const Object&, const Value& name) override; + bool hasProperty(const Object&, const Value& name) override; + void setPropertyValue(const Object&, const Value& name, const Value& value) + override; + void deleteProperty(const Object&, const PropNameID& name) override; + void deleteProperty(const Object&, const String& name) override; + void deleteProperty(const Object&, const Value& name) override; + + void setRuntimeDataImpl( + const UUID& uuid, + const void* data, + void (*deleter)(const void* data)) override; + const void* getRuntimeDataImpl(const UUID& uuid) override; + + PropNameID createPropNameIDFromUtf16(const char16_t* utf16, size_t length) + override; + String createStringFromUtf16(const char16_t* utf16, size_t length) override; + + Value createValueFromJsonUtf8(const uint8_t* json, size_t length) override; + + Object createObjectWithPrototype(const Value& prototype) override; + void setPrototypeOf(const Object& object, const Value& prototype) override; + Value getPrototypeOf(const Object& object) override; + + ScopeState* pushScope() override; + void popScope(ScopeState*) override; + + std::u16string utf16(const String& str) override; + std::u16string utf16(const PropNameID& sym) override; + + void getStringData( + const jsi::String& str, + void* ctx, + void (*cb)(void* ctx, bool ascii, const void* data, size_t num)) override; + void getPropNameIdData( + const jsi::PropNameID& sym, + void* ctx, + void (*cb)(void* ctx, bool ascii, const void* data, size_t num)) override; + + size_t push(const Array&, const Value*, size_t) override; + + std::shared_ptr tryGetMutableBuffer( + const jsi::ArrayBuffer& arrayBuffer) override; + + bool detached(const ArrayBuffer&) override; + + ArrayBuffer buffer(const TypedArray& typedArray) override; + size_t byteOffset(const TypedArray& typedArray) override; + size_t byteLength(const TypedArray& typedArray) override; + size_t length(const TypedArray& typedArray) override; + + bool isTypedArray(const Object&) const override; + bool isUint8Array(const Object&) const override; + Uint8Array createUint8Array(size_t length) override; + Uint8Array createUint8Array( + const ArrayBuffer& buffer, + size_t offset, + size_t length) override; + + Value createError(const String& msg) override; + Value createEvalError(const String& msg) override; + Value createRangeError(const String& msg) override; + Value createReferenceError(const String& msg) override; + Value createSyntaxError(const String& msg) override; + Value createTypeError(const String& msg) override; + Value createURIError(const String& msg) override; + + size_t length(const String& str) override; + + protected: + friend class Pointer; + friend class PropNameID; + friend class Symbol; + friend class BigInt; + friend class String; + friend class Object; + friend class WeakObject; + friend class Array; + friend class ArrayBuffer; + friend class Function; + friend class Value; + friend class Scope; + friend class JSError; // These exist so derived classes can access the private parts of // Value, Symbol, String, and Object, which are all friends of Runtime. @@ -443,7 +849,7 @@ class JSI_EXPORT PropNameID : public Pointer { public: using Pointer::Pointer; - PropNameID(Runtime& runtime, const PropNameID& other) + PropNameID(IRuntime& runtime, const PropNameID& other) : Pointer(runtime.clonePropNameID(other.ptr_)) {} PropNameID(PropNameID&& other) = default; @@ -451,66 +857,98 @@ class JSI_EXPORT PropNameID : public Pointer { /// Create a JS property name id from ascii values. The data is /// copied. - static PropNameID forAscii(Runtime& runtime, const char* str, size_t length) { + static PropNameID + forAscii(IRuntime& runtime, const char* str, size_t length) { return runtime.createPropNameIDFromAscii(str, length); } /// Create a property name id from a nul-terminated C ascii name. The data is /// copied. - static PropNameID forAscii(Runtime& runtime, const char* str) { + static PropNameID forAscii(IRuntime& runtime, const char* str) { return forAscii(runtime, str, strlen(str)); } /// Create a PropNameID from a C++ string. The string is copied. - static PropNameID forAscii(Runtime& runtime, const std::string& str) { + static PropNameID forAscii(IRuntime& runtime, const std::string& str) { return forAscii(runtime, str.c_str(), str.size()); } /// Create a PropNameID from utf8 values. The data is copied. /// Results are undefined if \p utf8 contains invalid code points. static PropNameID - forUtf8(Runtime& runtime, const uint8_t* utf8, size_t length) { + forUtf8(IRuntime& runtime, const uint8_t* utf8, size_t length) { return runtime.createPropNameIDFromUtf8(utf8, length); } /// Create a PropNameID from utf8-encoded octets stored in a /// std::string. The string data is transformed and copied. /// Results are undefined if \p utf8 contains invalid code points. - static PropNameID forUtf8(Runtime& runtime, const std::string& utf8) { + static PropNameID forUtf8(IRuntime& runtime, const std::string& utf8) { return runtime.createPropNameIDFromUtf8( reinterpret_cast(utf8.data()), utf8.size()); } + /// Given a series of UTF-16 encoded code units, create a PropNameId. The + /// input may contain unpaired surrogates, which will be interpreted as a code + /// point of the same value. + static PropNameID + forUtf16(IRuntime& runtime, const char16_t* utf16, size_t length) { + return runtime.createPropNameIDFromUtf16(utf16, length); + } + + /// Given a series of UTF-16 encoded code units stored inside std::u16string, + /// create a PropNameId. The input may contain unpaired surrogates, which + /// will be interpreted as a code point of the same value. + static PropNameID forUtf16(IRuntime& runtime, const std::u16string& str) { + return runtime.createPropNameIDFromUtf16(str.data(), str.size()); + } + /// Create a PropNameID from a JS string. - static PropNameID forString(Runtime& runtime, const jsi::String& str) { + static PropNameID forString(IRuntime& runtime, const jsi::String& str) { return runtime.createPropNameIDFromString(str); } /// Create a PropNameID from a JS symbol. - static PropNameID forSymbol(Runtime& runtime, const jsi::Symbol& sym) { + static PropNameID forSymbol(IRuntime& runtime, const jsi::Symbol& sym) { return runtime.createPropNameIDFromSymbol(sym); } // Creates a vector of PropNameIDs constructed from given arguments. template - static std::vector names(Runtime& runtime, Args&&... args); + static std::vector names(IRuntime& runtime, Args&&... args); // Creates a vector of given PropNameIDs. template static std::vector names(PropNameID (&&propertyNames)[N]); /// Copies the data in a PropNameID as utf8 into a C++ string. - std::string utf8(Runtime& runtime) const { + std::string utf8(IRuntime& runtime) const { return runtime.utf8(*this); } /// Copies the data in a PropNameID as utf16 into a C++ string. - std::u16string utf16(Runtime& runtime) const { + std::u16string utf16(IRuntime& runtime) const { return runtime.utf16(*this); } + /// Invokes the user provided callback to process the content in PropNameId. + /// The callback must take in three arguments: bool ascii, const void* data, + /// and size_t num, respectively. \p ascii indicates whether the \p data + /// passed to the callback should be interpreted as a pointer to a sequence of + /// \p num ASCII characters or UTF16 characters. The function may invoke the + /// callback multiple times, with a different format on each invocation. The + /// callback must not access runtime functionality, as any operation on the + /// runtime may invalidate the data pointers. + template + void getPropNameIdData(IRuntime& runtime, CB& cb) const { + runtime.getPropNameIdData( + *this, &cb, [](void* ctx, bool ascii, const void* data, size_t num) { + (*((CB*)ctx))(ascii, data, num); + }); + } + static bool compare( - Runtime& runtime, + IRuntime& runtime, const jsi::PropNameID& a, const jsi::PropNameID& b) { return runtime.compare(a, b); @@ -533,13 +971,14 @@ class JSI_EXPORT Symbol : public Pointer { Symbol& operator=(Symbol&& other) = default; /// \return whether a and b refer to the same symbol. - static bool strictEquals(Runtime& runtime, const Symbol& a, const Symbol& b) { + static bool + strictEquals(IRuntime& runtime, const Symbol& a, const Symbol& b) { return runtime.strictEquals(a, b); } /// Converts a Symbol into a C++ string as JS .toString would. The output /// will look like \c Symbol(description) . - std::string toString(Runtime& runtime) const { + std::string toString(IRuntime& runtime) const { return runtime.symbolToString(*this); } @@ -556,51 +995,52 @@ class JSI_EXPORT BigInt : public Pointer { BigInt& operator=(BigInt&& other) = default; /// Create a BigInt representing the signed 64-bit \p value. - static BigInt fromInt64(Runtime& runtime, int64_t value) { + static BigInt fromInt64(IRuntime& runtime, int64_t value) { return runtime.createBigIntFromInt64(value); } /// Create a BigInt representing the unsigned 64-bit \p value. - static BigInt fromUint64(Runtime& runtime, uint64_t value) { + static BigInt fromUint64(IRuntime& runtime, uint64_t value) { return runtime.createBigIntFromUint64(value); } /// \return whether a === b. - static bool strictEquals(Runtime& runtime, const BigInt& a, const BigInt& b) { + static bool + strictEquals(IRuntime& runtime, const BigInt& a, const BigInt& b) { return runtime.strictEquals(a, b); } /// \returns This bigint truncated to a signed 64-bit integer. - int64_t getInt64(Runtime& runtime) const { + int64_t getInt64(IRuntime& runtime) const { return runtime.truncate(*this); } /// \returns Whether this bigint can be losslessly converted to int64_t. - bool isInt64(Runtime& runtime) const { + bool isInt64(IRuntime& runtime) const { return runtime.bigintIsInt64(*this); } /// \returns This bigint truncated to a signed 64-bit integer. Throws a /// JSIException if the truncation is lossy. - int64_t asInt64(Runtime& runtime) const; + int64_t asInt64(IRuntime& runtime) const; /// \returns This bigint truncated to an unsigned 64-bit integer. - uint64_t getUint64(Runtime& runtime) const { + uint64_t getUint64(IRuntime& runtime) const { return runtime.truncate(*this); } /// \returns Whether this bigint can be losslessly converted to uint64_t. - bool isUint64(Runtime& runtime) const { + bool isUint64(IRuntime& runtime) const { return runtime.bigintIsUint64(*this); } /// \returns This bigint truncated to an unsigned 64-bit integer. Throws a /// JSIException if the truncation is lossy. - uint64_t asUint64(Runtime& runtime) const; + uint64_t asUint64(IRuntime& runtime) const; /// \returns this BigInt converted to a String in base \p radix. Throws a /// JSIException if radix is not in the [2, 36] range. - inline String toString(Runtime& runtime, int radix = 10) const; + inline String toString(IRuntime& runtime, int radix = 10) const; friend class Runtime; friend class Value; @@ -617,19 +1057,19 @@ class JSI_EXPORT String : public Pointer { /// Create a JS string from ascii values. The string data is /// copied. static String - createFromAscii(Runtime& runtime, const char* str, size_t length) { + createFromAscii(IRuntime& runtime, const char* str, size_t length) { return runtime.createStringFromAscii(str, length); } /// Create a JS string from a nul-terminated C ascii string. The /// string data is copied. - static String createFromAscii(Runtime& runtime, const char* str) { + static String createFromAscii(IRuntime& runtime, const char* str) { return createFromAscii(runtime, str, strlen(str)); } /// Create a JS string from a C++ string. The string data is /// copied. - static String createFromAscii(Runtime& runtime, const std::string& str) { + static String createFromAscii(IRuntime& runtime, const std::string& str) { return createFromAscii(runtime, str.c_str(), str.size()); } @@ -637,33 +1077,72 @@ class JSI_EXPORT String : public Pointer { /// transformed and copied. Results are undefined if \p utf8 contains invalid /// code points. static String - createFromUtf8(Runtime& runtime, const uint8_t* utf8, size_t length) { + createFromUtf8(IRuntime& runtime, const uint8_t* utf8, size_t length) { return runtime.createStringFromUtf8(utf8, length); } /// Create a JS string from utf8-encoded octets stored in a /// std::string. The string data is transformed and copied. Results are /// undefined if \p utf8 contains invalid code points. - static String createFromUtf8(Runtime& runtime, const std::string& utf8) { + static String createFromUtf8(IRuntime& runtime, const std::string& utf8) { return runtime.createStringFromUtf8( reinterpret_cast(utf8.data()), utf8.length()); } + /// Given a series of UTF-16 encoded code units, create a JS String. The input + /// may contain unpaired surrogates, which will be interpreted as a code point + /// of the same value. + static String + createFromUtf16(IRuntime& runtime, const char16_t* utf16, size_t length) { + return runtime.createStringFromUtf16(utf16, length); + } + + /// Given a series of UTF-16 encoded code units stored inside std::u16string, + /// create a JS String. The input may contain unpaired surrogates, which will + /// be interpreted as a code point of the same value. + static String createFromUtf16( + IRuntime& runtime, + const std::u16string& utf16) { + return runtime.createStringFromUtf16(utf16.data(), utf16.length()); + } + /// \return whether a and b contain the same characters. - static bool strictEquals(Runtime& runtime, const String& a, const String& b) { + static bool + strictEquals(IRuntime& runtime, const String& a, const String& b) { return runtime.strictEquals(a, b); } + /// \return the 'length' property of this JS string. + size_t length(IRuntime& runtime) const { + return runtime.length(*this); + } + /// Copies the data in a JS string as utf8 into a C++ string. - std::string utf8(Runtime& runtime) const { + std::string utf8(IRuntime& runtime) const { return runtime.utf8(*this); } /// Copies the data in a JS string as utf16 into a C++ string. - std::u16string utf16(Runtime& runtime) const { + std::u16string utf16(IRuntime& runtime) const { return runtime.utf16(*this); } + /// Invokes the user provided callback to process content in String. The + /// callback must take in three arguments: bool ascii, const void* data, and + /// size_t num, respectively. \p ascii indicates whether the \p data passed to + /// the callback should be interpreted as a pointer to a sequence of \p num + /// ASCII characters or UTF16 characters. The function may invoke the callback + /// multiple times, with a different format on each invocation. The callback + /// must not access runtime functionality, as any operation on the runtime may + /// invalidate the data pointers. + template + void getStringData(IRuntime& runtime, CB& cb) const { + runtime.getStringData( + *this, &cb, [](void* ctx, bool ascii, const void* data, size_t num) { + (*((CB*)ctx))(ascii, data, num); + }); + } + friend class Runtime; friend class Value; }; @@ -680,84 +1159,147 @@ class JSI_EXPORT Object : public Pointer { Object& operator=(Object&& other) = default; /// Creates a new Object instance, like '{}' in JS. - Object(Runtime& runtime) : Object(runtime.createObject()) {} + explicit Object(IRuntime& runtime) : Object(runtime.createObject()) {} static Object createFromHostObject( - Runtime& runtime, + IRuntime& runtime, std::shared_ptr ho) { return runtime.createObject(ho); } + /// Creates a new Object with the custom prototype + static Object create(IRuntime& runtime, const Value& prototype) { + return runtime.createObjectWithPrototype(prototype); + } + /// \return whether this and \c obj are the same JSObject or not. - static bool strictEquals(Runtime& runtime, const Object& a, const Object& b) { + static bool + strictEquals(IRuntime& runtime, const Object& a, const Object& b) { return runtime.strictEquals(a, b); } /// \return the result of `this instanceOf ctor` in JS. - bool instanceOf(Runtime& rt, const Function& ctor) const { + bool instanceOf(IRuntime& rt, const Function& ctor) const { return rt.instanceOf(*this, ctor); } + /// Sets \p prototype as the prototype of the object. The prototype must be + /// either an Object or null. If the prototype was not set successfully, this + /// method will throw. + void setPrototype(IRuntime& runtime, const Value& prototype) const { + return runtime.setPrototypeOf(*this, prototype); + } + + /// \return the prototype of the object + inline Value getPrototype(IRuntime& runtime) const; + /// \return the property of the object with the given ascii name. /// If the name isn't a property on the object, returns the /// undefined value. - Value getProperty(Runtime& runtime, const char* name) const; + Value getProperty(IRuntime& runtime, const char* name) const; /// \return the property of the object with the String name. /// If the name isn't a property on the object, returns the /// undefined value. - Value getProperty(Runtime& runtime, const String& name) const; + Value getProperty(IRuntime& runtime, const String& name) const; /// \return the property of the object with the given JS PropNameID /// name. If the name isn't a property on the object, returns the /// undefined value. - Value getProperty(Runtime& runtime, const PropNameID& name) const; + Value getProperty(IRuntime& runtime, const PropNameID& name) const; + + /// \return the Property of the object with the given JS Value name. If the + /// name isn't a property on the object, returns the undefined value.This + /// attempts to convert the JS Value to convert to a property key. If the + /// conversion fails, this method may throw. + Value getProperty(IRuntime& runtime, const Value& name) const; /// \return true if and only if the object has a property with the /// given ascii name. - bool hasProperty(Runtime& runtime, const char* name) const; + bool hasProperty(IRuntime& runtime, const char* name) const; /// \return true if and only if the object has a property with the /// given String name. - bool hasProperty(Runtime& runtime, const String& name) const; + bool hasProperty(IRuntime& runtime, const String& name) const; /// \return true if and only if the object has a property with the /// given PropNameID name. - bool hasProperty(Runtime& runtime, const PropNameID& name) const; + bool hasProperty(IRuntime& runtime, const PropNameID& name) const; + + /// \return true if and only if the object has a property with the given + /// JS Value name. This attempts to convert the JS Value to convert to a + /// property key. If the conversion fails, this method may throw. + bool hasProperty(IRuntime& runtime, const Value& name) const; /// Sets the property value from a Value or anything which can be /// used to make one: nullptr_t, bool, double, int, const char*, /// String, or Object. template - void setProperty(Runtime& runtime, const char* name, T&& value) const; + void setProperty(IRuntime& runtime, const char* name, T&& value) const; /// Sets the property value from a Value or anything which can be /// used to make one: nullptr_t, bool, double, int, const char*, /// String, or Object. template - void setProperty(Runtime& runtime, const String& name, T&& value) const; + void setProperty(IRuntime& runtime, const String& name, T&& value) const; /// Sets the property value from a Value or anything which can be /// used to make one: nullptr_t, bool, double, int, const char*, /// String, or Object. template - void setProperty(Runtime& runtime, const PropNameID& name, T&& value) const; + void setProperty(IRuntime& runtime, const PropNameID& name, T&& value) const; + + /// Sets the property value from a Value or anything which can be + /// used to make one: nullptr_t, bool, double, int, const char*, + /// String, or Object. This takes a JS Value as the property name, and + /// attempts to convert to a property key. If the conversion fails, this + /// method may throw. + template + void setProperty(IRuntime& runtime, const Value& name, T&& value) const; + + /// Delete the property with the given ascii name. Throws if the deletion + /// failed. + void deleteProperty(IRuntime& runtime, const char* name) const; + + /// Delete the property with the given String name. Throws if the deletion + /// failed. + void deleteProperty(IRuntime& runtime, const String& name) const; + + /// Delete the property with the given PropNameID name. Throws if the deletion + /// failed. + void deleteProperty(IRuntime& runtime, const PropNameID& name) const; + + /// Delete the property with the given Value name. Throws if the deletion + /// failed. + void deleteProperty(IRuntime& runtime, const Value& name) const; /// \return true iff JS \c Array.isArray() would return \c true. If /// so, then \c getArray() will succeed. - bool isArray(Runtime& runtime) const { + bool isArray(IRuntime& runtime) const { return runtime.isArray(*this); } /// \return true iff the Object is an ArrayBuffer. If so, then \c /// getArrayBuffer() will succeed. - bool isArrayBuffer(Runtime& runtime) const { + bool isArrayBuffer(IRuntime& runtime) const { return runtime.isArrayBuffer(*this); } + /// \return true iff the Object is a TypedArray (Uint8Array, Int32Array, + /// Float64Array, etc.). If so, then \c getTypedArray() will succeed. + bool isTypedArray(IRuntime& runtime) const { + return runtime.isTypedArray(*this); + } + + /// \return true iff the Object is an Uint8Array. If so, then \c + /// getUint8Array() will succeed + bool isUint8Array(IRuntime& runtime) const { + return runtime.isUint8Array(*this); + } + /// \return true iff the Object is callable. If so, then \c /// getFunction will succeed. - bool isFunction(Runtime& runtime) const { + bool isFunction(IRuntime& runtime) const { return runtime.isFunction(*this); } @@ -765,99 +1307,117 @@ class JSI_EXPORT Object : public Pointer { /// and the HostObject passed is of type \c T. If returns \c true then /// \c getHostObject will succeed. template - bool isHostObject(Runtime& runtime) const; + bool isHostObject(IRuntime& runtime) const; /// \return an Array instance which refers to the same underlying /// object. If \c isArray() would return false, this will assert. - Array getArray(Runtime& runtime) const&; + Array getArray(IRuntime& runtime) const&; /// \return an Array instance which refers to the same underlying /// object. If \c isArray() would return false, this will assert. - Array getArray(Runtime& runtime) &&; + Array getArray(IRuntime& runtime) &&; /// \return an Array instance which refers to the same underlying /// object. If \c isArray() would return false, this will throw /// JSIException. - Array asArray(Runtime& runtime) const&; + Array asArray(IRuntime& runtime) const&; /// \return an Array instance which refers to the same underlying /// object. If \c isArray() would return false, this will throw /// JSIException. - Array asArray(Runtime& runtime) &&; + Array asArray(IRuntime& runtime) &&; + + /// \return a TypedArray instance which refers to the same underlying + /// object. If \c isTypedArray() would return false, this will throw + /// JSIException. + TypedArray asTypedArray(IRuntime& runtime) const&; + + /// \return an Uint8Array instance which refers to the same underlying + /// object. If \c isUint8Array() would return false, this will throw + /// JSIException. + Uint8Array asUint8Array(IRuntime& runtime) const&; /// \return an ArrayBuffer instance which refers to the same underlying /// object. If \c isArrayBuffer() would return false, this will assert. - ArrayBuffer getArrayBuffer(Runtime& runtime) const&; + ArrayBuffer getArrayBuffer(IRuntime& runtime) const&; /// \return an ArrayBuffer instance which refers to the same underlying /// object. If \c isArrayBuffer() would return false, this will assert. - ArrayBuffer getArrayBuffer(Runtime& runtime) &&; + ArrayBuffer getArrayBuffer(IRuntime& runtime) &&; + + /// \return a TypedArray instance which refers to the same underlying + /// object. If \c isTypedArray() would return false, this will assert. + TypedArray getTypedArray(IRuntime& runtime) const&; + + /// \return an Uint8Array instance which refers to the same underlying + /// object. If \c isUint8Array() would return false, this will assert. + Uint8Array getUint8Array(IRuntime& runtime) const&; /// \return a Function instance which refers to the same underlying /// object. If \c isFunction() would return false, this will assert. - Function getFunction(Runtime& runtime) const&; + Function getFunction(IRuntime& runtime) const&; /// \return a Function instance which refers to the same underlying /// object. If \c isFunction() would return false, this will assert. - Function getFunction(Runtime& runtime) &&; + Function getFunction(IRuntime& runtime) &&; /// \return a Function instance which refers to the same underlying /// object. If \c isFunction() would return false, this will throw /// JSIException. - Function asFunction(Runtime& runtime) const&; + Function asFunction(IRuntime& runtime) const&; /// \return a Function instance which refers to the same underlying /// object. If \c isFunction() would return false, this will throw /// JSIException. - Function asFunction(Runtime& runtime) &&; + Function asFunction(IRuntime& runtime) &&; /// \return a shared_ptr which refers to the same underlying /// \c HostObject that was used to create this object. If \c isHostObject /// is false, this will assert. Note that this does a type check and will /// assert if the underlying HostObject isn't of type \c T template - std::shared_ptr getHostObject(Runtime& runtime) const; + std::shared_ptr getHostObject(IRuntime& runtime) const; /// \return a shared_ptr which refers to the same underlying /// \c HostObject that was used to create this object. If \c isHostObject /// is false, this will throw. template - std::shared_ptr asHostObject(Runtime& runtime) const; + std::shared_ptr asHostObject(IRuntime& runtime) const; /// \return whether this object has native state of type T previously set by /// \c setNativeState. template - bool hasNativeState(Runtime& runtime) const; + bool hasNativeState(IRuntime& runtime) const; /// \return a shared_ptr to the state previously set by \c setNativeState. /// If \c hasNativeState is false, this will assert. Note that this does a /// type check and will assert if the native state isn't of type \c T template - std::shared_ptr getNativeState(Runtime& runtime) const; + std::shared_ptr getNativeState(IRuntime& runtime) const; /// Set the internal native state property of this object, overwriting any old /// value. Creates a new shared_ptr to the object managed by \p state, which /// will live until the value at this property becomes unreachable. /// /// Throws a type error if this object is a proxy or host object. - void setNativeState(Runtime& runtime, std::shared_ptr state) + void setNativeState(IRuntime& runtime, std::shared_ptr state) const; /// \return same as \c getProperty(name).asObject(), except with /// a better exception message. - Object getPropertyAsObject(Runtime& runtime, const char* name) const; + Object getPropertyAsObject(IRuntime& runtime, const char* name) const; /// \return similar to \c /// getProperty(name).getObject().getFunction(), except it will /// throw JSIException instead of asserting if the property is /// not an object, or the object is not callable. - Function getPropertyAsFunction(Runtime& runtime, const char* name) const; + Function getPropertyAsFunction(IRuntime& runtime, const char* name) const; /// \return an Array consisting of all enumerable property names in /// the object and its prototype chain. All values in the return /// will be isString(). (This is probably not optimal, but it /// works. I only need it in one place.) - Array getPropertyNames(Runtime& runtime) const; + Array getPropertyNames(IRuntime& runtime) const; /// Inform the runtime that there is additional memory associated with a given /// JavaScript object that is not visible to the GC. This can be used if an @@ -867,23 +1427,30 @@ class JSI_EXPORT Object : public Pointer { /// calls will overwrite any previously set value. Once the object is garbage /// collected, the associated external memory will be considered freed and may /// no longer factor into GC decisions. - void setExternalMemoryPressure(Runtime& runtime, size_t amt) const; + void setExternalMemoryPressure(IRuntime& runtime, size_t amt) const; protected: void setPropertyValue( - Runtime& runtime, + IRuntime& runtime, const String& name, const Value& value) const { return runtime.setPropertyValue(*this, name, value); } void setPropertyValue( - Runtime& runtime, + IRuntime& runtime, const PropNameID& name, const Value& value) const { return runtime.setPropertyValue(*this, name, value); } + void setPropertyValue( + IRuntime& runtime, + const Value& name, + const Value& value) const { + return runtime.setPropertyValue(*this, name, value); + } + friend class Runtime; friend class Value; }; @@ -899,14 +1466,14 @@ class JSI_EXPORT WeakObject : public Pointer { WeakObject& operator=(WeakObject&& other) = default; /// Create a WeakObject from an Object. - WeakObject(Runtime& runtime, const Object& o) + WeakObject(IRuntime& runtime, const Object& o) : WeakObject(runtime.createWeakObject(o)) {} /// \return a Value representing the underlying Object if it is still valid; /// otherwise returns \c undefined. Note that this method has nothing to do /// with threads or concurrency. The name is based on std::weak_ptr::lock() /// which serves a similar purpose. - Value lock(Runtime& runtime) const; + Value lock(IRuntime& runtime) const; friend class Runtime; }; @@ -917,43 +1484,54 @@ class JSI_EXPORT Array : public Object { public: Array(Array&&) = default; /// Creates a new Array instance, with \c length undefined elements. - Array(Runtime& runtime, size_t length) : Array(runtime.createArray(length)) {} + Array(IRuntime& runtime, size_t length) + : Array(runtime.createArray(length)) {} Array& operator=(Array&&) = default; /// \return the size of the Array, according to its length property. /// (C++ naming convention) - size_t size(Runtime& runtime) const { + size_t size(IRuntime& runtime) const { return runtime.size(*this); } /// \return the size of the Array, according to its length property. /// (JS naming convention) - size_t length(Runtime& runtime) const { + size_t length(IRuntime& runtime) const { return size(runtime); } /// \return the property of the array at index \c i. If there is no /// such property, returns the undefined value. If \c i is out of /// range [ 0..\c length ] throws a JSIException. - Value getValueAtIndex(Runtime& runtime, size_t i) const; + Value getValueAtIndex(IRuntime& runtime, size_t i) const; /// Sets the property of the array at index \c i. The argument /// value behaves as with Object::setProperty(). If \c i is out of /// range [ 0..\c length ] throws a JSIException. template - void setValueAtIndex(Runtime& runtime, size_t i, T&& value) const; + void setValueAtIndex(IRuntime& runtime, size_t i, T&& value) const; - /// There is no current API for changing the size of an array once - /// created. We'll probably need that eventually. + /// Appends provides values to the end of the Array in the order they appear. + /// Returns the new length of the array. + template + size_t push(IRuntime& runtime, Args&&... args); + + /// Appends everything in \p elements to the end of the Array in the order + /// they appear. Returns the new length of the array. + size_t push(IRuntime& runtime, std::initializer_list elements); + + /// Appends \p count elements at \p elements to the end of the Array in the + /// order they appear. + size_t push(IRuntime& runtime, const Value* elements, size_t count); /// Creates a new Array instance from provided values template - static Array createWithElements(Runtime&, Args&&... args); + static Array createWithElements(IRuntime&, Args&&... args); /// Creates a new Array instance from initializer list. static Array createWithElements( - Runtime& runtime, + IRuntime& runtime, std::initializer_list elements); private: @@ -961,7 +1539,7 @@ class JSI_EXPORT Array : public Object { friend class Value; friend class Runtime; - void setValueAtIndexImpl(Runtime& runtime, size_t i, const Value& value) + void setValueAtIndexImpl(IRuntime& runtime, size_t i, const Value& value) const { return runtime.setValueAtIndexImpl(*this, i, value); } @@ -975,24 +1553,33 @@ class JSI_EXPORT ArrayBuffer : public Object { ArrayBuffer(ArrayBuffer&&) = default; ArrayBuffer& operator=(ArrayBuffer&&) = default; - ArrayBuffer(Runtime& runtime, std::shared_ptr buffer) + ArrayBuffer(IRuntime& runtime, std::shared_ptr buffer) : ArrayBuffer(runtime.createArrayBuffer(std::move(buffer))) {} /// \return the size of the ArrayBuffer storage. This is not affected by /// overriding the byteLength property. /// (C++ naming convention) - size_t size(Runtime& runtime) const { + size_t size(IRuntime& runtime) const { return runtime.size(*this); } - size_t length(Runtime& runtime) const { + size_t length(IRuntime& runtime) const { return runtime.size(*this); } - uint8_t* data(Runtime& runtime) const { + uint8_t* data(IRuntime& runtime) const { return runtime.data(*this); } + std::shared_ptr tryGetMutableBuffer(IRuntime& runtime) const { + return runtime.tryGetMutableBuffer(*this); + } + + /// \return true if the ArrayBuffer is detached, false otherwise. + bool detached(IRuntime& runtime) const { + return runtime.detached(*this); + } + private: friend class Object; friend class Value; @@ -1019,7 +1606,7 @@ class JSI_EXPORT Function : public Object { /// any captured values, you are responsible for ensuring that their /// destructors are safe to call on any thread. static Function createFromHostFunction( - Runtime& runtime, + IRuntime& runtime, const jsi::PropNameID& name, unsigned int paramCount, jsi::HostFunctionType func); @@ -1030,7 +1617,7 @@ class JSI_EXPORT Function : public Object { /// \b Note: as with Function.prototype.apply, \c this may not always be /// \c undefined in the function itself. If the function is non-strict, /// \c this will be set to the global object. - Value call(Runtime& runtime, const Value* args, size_t count) const; + Value call(IRuntime& runtime, const Value* args, size_t count) const; /// Calls the function with a \c std::initializer_list of Value /// arguments. The \c this value of the JS function will not be set by the @@ -1039,7 +1626,7 @@ class JSI_EXPORT Function : public Object { /// \b Note: as with Function.prototype.apply, \c this may not always be /// \c undefined in the function itself. If the function is non-strict, /// \c this will be set to the global object. - Value call(Runtime& runtime, std::initializer_list args) const; + Value call(IRuntime& runtime, std::initializer_list args) const; /// Calls the function with any number of arguments similarly to /// Object::setProperty(). The \c this value of the JS function will not be @@ -1049,12 +1636,12 @@ class JSI_EXPORT Function : public Object { /// \c undefined in the function itself. If the function is non-strict, /// \c this will be set to the global object. template - Value call(Runtime& runtime, Args&&... args) const; + Value call(IRuntime& runtime, Args&&... args) const; /// Calls the function with \c count \c args and \c jsThis value passed /// as the \c this value. Value callWithThis( - Runtime& Runtime, + IRuntime& Runtime, const Object& jsThis, const Value* args, size_t count) const; @@ -1062,36 +1649,36 @@ class JSI_EXPORT Function : public Object { /// Calls the function with a \c std::initializer_list of Value /// arguments and \c jsThis passed as the \c this value. Value callWithThis( - Runtime& runtime, + IRuntime& runtime, const Object& jsThis, std::initializer_list args) const; /// Calls the function with any number of arguments similarly to /// Object::setProperty(), and with \c jsThis passed as the \c this value. template - Value callWithThis(Runtime& runtime, const Object& jsThis, Args&&... args) + Value callWithThis(IRuntime& runtime, const Object& jsThis, Args&&... args) const; /// Calls the function as a constructor with \c count \c args. Equivalent /// to calling `new Func` where `Func` is the js function reqresented by /// this. - Value callAsConstructor(Runtime& runtime, const Value* args, size_t count) + Value callAsConstructor(IRuntime& runtime, const Value* args, size_t count) const; /// Same as above `callAsConstructor`, except use an initializer_list to /// supply the arguments. - Value callAsConstructor(Runtime& runtime, std::initializer_list args) + Value callAsConstructor(IRuntime& runtime, std::initializer_list args) const; /// Same as above `callAsConstructor`, but automatically converts/wraps /// any argument with a jsi Value. template - Value callAsConstructor(Runtime& runtime, Args&&... args) const; + Value callAsConstructor(IRuntime& runtime, Args&&... args) const; /// Returns whether this was created with Function::createFromHostFunction. /// If true then you can use getHostFunction to get the underlying /// HostFunctionType. - bool isHostFunction(Runtime& runtime) const { + bool isHostFunction(IRuntime& runtime) const { return runtime.isHostFunction(*this); } @@ -1102,7 +1689,7 @@ class JSI_EXPORT Function : public Object { /// Note: The reference returned is borrowed from the JS object underlying /// \c this, and thus only lasts as long as the object underlying /// \c this does. - HostFunctionType& getHostFunction(Runtime& runtime) const { + HostFunctionType& getHostFunction(IRuntime& runtime) const { assert(isHostFunction(runtime)); return runtime.getHostFunction(*this); } @@ -1115,6 +1702,64 @@ class JSI_EXPORT Function : public Object { Function(Runtime::PointerValue* value) : Object(value) {} }; +/// Represents a JS TypedArray +class JSI_EXPORT TypedArray : public Object { + public: + TypedArray(TypedArray&&) = default; + TypedArray& operator=(TypedArray&&) = default; + + // Gets the buffer of this TypedArray + ArrayBuffer buffer(IRuntime& runtime) { + return runtime.buffer(*this); + } + + // Gets the byte offset of this TypedArray + size_t byteOffset(IRuntime& runtime) { + return runtime.byteOffset(*this); + } + + // Gets the byte length of this TypedArray + size_t byteLength(IRuntime& runtime) { + return runtime.byteLength(*this); + } + + // Gets the element length of this TypedArray + size_t length(IRuntime& runtime) { + return runtime.length(*this); + } + + private: + friend class Object; + friend class Value; + friend class Runtime; + friend class Uint8Array; + + explicit TypedArray(Runtime::PointerValue* value) : Object(value) {} +}; + +// Represents a JS Uint8Array +class JSI_EXPORT Uint8Array : public TypedArray { + public: + Uint8Array(Uint8Array&&) = default; + Uint8Array& operator=(Uint8Array&&) = default; + + Uint8Array(IRuntime& runtime, size_t length) + : Uint8Array(runtime.createUint8Array(length)) {} + Uint8Array( + IRuntime& runtime, + const ArrayBuffer& buffer, + size_t offset, + size_t length) + : Uint8Array(runtime.createUint8Array(buffer, offset, length)) {} + + private: + friend class Object; + friend class Value; + friend class Runtime; + + explicit Uint8Array(Runtime::PointerValue* value) : TypedArray(value) {} +}; + /// Represents any JS Value (undefined, null, boolean, number, symbol, /// string, or object). Movable, or explicitly copyable (has no copy /// ctor). @@ -1165,32 +1810,32 @@ class JSI_EXPORT Value { Value(Value&& other) noexcept; /// Copies a Symbol lvalue into a new JS value. - Value(Runtime& runtime, const Symbol& sym) : Value(SymbolKind) { + Value(IRuntime& runtime, const Symbol& sym) : Value(SymbolKind) { new (&data_.pointer) Symbol(runtime.cloneSymbol(sym.ptr_)); } /// Copies a BigInt lvalue into a new JS value. - Value(Runtime& runtime, const BigInt& bigint) : Value(BigIntKind) { + Value(IRuntime& runtime, const BigInt& bigint) : Value(BigIntKind) { new (&data_.pointer) BigInt(runtime.cloneBigInt(bigint.ptr_)); } /// Copies a String lvalue into a new JS value. - Value(Runtime& runtime, const String& str) : Value(StringKind) { + Value(IRuntime& runtime, const String& str) : Value(StringKind) { new (&data_.pointer) String(runtime.cloneString(str.ptr_)); } /// Copies a Object lvalue into a new JS value. - Value(Runtime& runtime, const Object& obj) : Value(ObjectKind) { + Value(IRuntime& runtime, const Object& obj) : Value(ObjectKind) { new (&data_.pointer) Object(runtime.cloneObject(obj.ptr_)); } /// Creates a JS value from another Value lvalue. - Value(Runtime& runtime, const Value& value); + Value(IRuntime& runtime, const Value& value); /// Value(rt, "foo") will treat foo as a bool. This makes doing /// that a compile error. template - Value(Runtime&, const char*) { + Value(IRuntime&, const char*) { static_assert( !std::is_same::value, "Value cannot be constructed directly from const char*"); @@ -1209,13 +1854,13 @@ class JSI_EXPORT Value { // \return a \c Value created from a utf8-encoded JSON string. static Value - createFromJsonUtf8(Runtime& runtime, const uint8_t* json, size_t length) { + createFromJsonUtf8(IRuntime& runtime, const uint8_t* json, size_t length) { return runtime.createValueFromJsonUtf8(json, length); } /// \return according to the Strict Equality Comparison algorithm, see: /// https://262.ecma-international.org/11.0/#sec-strict-equality-comparison - static bool strictEquals(Runtime& runtime, const Value& a, const Value& b); + static bool strictEquals(IRuntime& runtime, const Value& a, const Value& b); Value& operator=(Value&& other) noexcept { this->~Value(); @@ -1255,6 +1900,28 @@ class JSI_EXPORT Value { return kind_ == ObjectKind; } + /// \returns true if `Number.isInteger(value)` returns true, false otherwise. + bool isInteger() const { + // 1. If number is an integral Number, return true. + // 2. Return false. + + // The spec's definition of integral number: + // When the term integer is used in this specification, it refers to a + // mathematical value which is in the set of integers, unless otherwise + // stated. When the term integral Number is used in this specification, it + // refers to a finite Number value whose mathematical value is in the set of + // integers. + + if (!isNumber()) { + return false; + } + auto number = data_.number; + if (!std::isfinite(number)) { + return false; + } + return number == std::trunc(number); + } + /// \return the boolean value, or asserts if not a boolean. bool getBool() const { assert(isBool()); @@ -1276,14 +1943,14 @@ class JSI_EXPORT Value { double asNumber() const; /// \return the Symbol value, or asserts if not a symbol. - Symbol getSymbol(Runtime& runtime) const& { + Symbol getSymbol(IRuntime& runtime) const& { assert(isSymbol()); return Symbol(runtime.cloneSymbol(data_.pointer.ptr_)); } /// \return the Symbol value, or asserts if not a symbol. /// Can be used on rvalue references to avoid cloning more symbols. - Symbol getSymbol(Runtime&) && { + Symbol getSymbol(IRuntime&) && { assert(isSymbol()); auto ptr = data_.pointer.ptr_; data_.pointer.ptr_ = nullptr; @@ -1292,18 +1959,18 @@ class JSI_EXPORT Value { /// \return the Symbol value, or throws JSIException if not a /// symbol - Symbol asSymbol(Runtime& runtime) const&; - Symbol asSymbol(Runtime& runtime) &&; + Symbol asSymbol(IRuntime& runtime) const&; + Symbol asSymbol(IRuntime& runtime) &&; /// \return the BigInt value, or asserts if not a bigint. - BigInt getBigInt(Runtime& runtime) const& { + BigInt getBigInt(IRuntime& runtime) const& { assert(isBigInt()); return BigInt(runtime.cloneBigInt(data_.pointer.ptr_)); } /// \return the BigInt value, or asserts if not a bigint. /// Can be used on rvalue references to avoid cloning more bigints. - BigInt getBigInt(Runtime&) && { + BigInt getBigInt(IRuntime&) && { assert(isBigInt()); auto ptr = data_.pointer.ptr_; data_.pointer.ptr_ = nullptr; @@ -1312,18 +1979,18 @@ class JSI_EXPORT Value { /// \return the BigInt value, or throws JSIException if not a /// bigint - BigInt asBigInt(Runtime& runtime) const&; - BigInt asBigInt(Runtime& runtime) &&; + BigInt asBigInt(IRuntime& runtime) const&; + BigInt asBigInt(IRuntime& runtime) &&; /// \return the String value, or asserts if not a string. - String getString(Runtime& runtime) const& { + String getString(IRuntime& runtime) const& { assert(isString()); return String(runtime.cloneString(data_.pointer.ptr_)); } /// \return the String value, or asserts if not a string. /// Can be used on rvalue references to avoid cloning more strings. - String getString(Runtime&) && { + String getString(IRuntime&) && { assert(isString()); auto ptr = data_.pointer.ptr_; data_.pointer.ptr_ = nullptr; @@ -1332,18 +1999,18 @@ class JSI_EXPORT Value { /// \return the String value, or throws JSIException if not a /// string. - String asString(Runtime& runtime) const&; - String asString(Runtime& runtime) &&; + String asString(IRuntime& runtime) const&; + String asString(IRuntime& runtime) &&; /// \return the Object value, or asserts if not an object. - Object getObject(Runtime& runtime) const& { + Object getObject(IRuntime& runtime) const& { assert(isObject()); return Object(runtime.cloneObject(data_.pointer.ptr_)); } /// \return the Object value, or asserts if not an object. /// Can be used on rvalue references to avoid cloning more objects. - Object getObject(Runtime&) && { + Object getObject(IRuntime&) && { assert(isObject()); auto ptr = data_.pointer.ptr_; data_.pointer.ptr_ = nullptr; @@ -1352,11 +2019,11 @@ class JSI_EXPORT Value { /// \return the Object value, or throws JSIException if not an /// object. - Object asObject(Runtime& runtime) const&; - Object asObject(Runtime& runtime) &&; + Object asObject(IRuntime& runtime) const&; + Object asObject(IRuntime& runtime) &&; // \return a String like JS .toString() would do. - String toString(Runtime& runtime) const; + String toString(IRuntime& runtime) const; private: friend class Runtime; @@ -1430,7 +2097,7 @@ class JSI_EXPORT Value { /// locking, provided that the lock (if any) is managed with RAII helpers. class JSI_EXPORT Scope { public: - explicit Scope(Runtime& rt) : rt_(rt), prv_(rt.pushScope()) {} + explicit Scope(IRuntime& rt) : rt_(rt), prv_(rt.pushScope()) {} ~Scope() { rt_.popScope(prv_); } @@ -1442,13 +2109,13 @@ class JSI_EXPORT Scope { Scope& operator=(Scope&&) = delete; template - static auto callInNewScope(Runtime& rt, F f) -> decltype(f()) { + static auto callInNewScope(IRuntime& rt, F f) -> decltype(f()) { Scope s(rt); return f(); } private: - Runtime& rt_; + IRuntime& rt_; Runtime::ScopeState* prv_; }; @@ -1488,31 +2155,55 @@ class JSI_EXPORT JSINativeException : public JSIException { class JSI_EXPORT JSError : public JSIException { public: /// Creates a JSError referring to provided \c value - JSError(Runtime& r, Value&& value); + JSError(IRuntime& r, Value&& value); /// Creates a JSError referring to new \c Error instance capturing current /// JavaScript stack. The error message property is set to given \c message. - JSError(Runtime& rt, std::string message); + JSError(IRuntime& rt, std::string message); /// Creates a JSError referring to new \c Error instance capturing current /// JavaScript stack. The error message property is set to given \c message. - JSError(Runtime& rt, const char* message) + JSError(IRuntime& rt, const char* message) : JSError(rt, std::string(message)) {} /// Creates a JSError referring to a JavaScript Object having message and /// stack properties set to provided values. - JSError(Runtime& rt, std::string message, std::string stack); + JSError(IRuntime& rt, std::string message, std::string stack); /// Creates a JSError referring to provided value and what string /// set to provided message. This argument order is a bit weird, /// but necessary to avoid ambiguity with the above. - JSError(std::string what, Runtime& rt, Value&& value); + JSError(std::string what, IRuntime& rt, Value&& value); /// Creates a JSError referring to the provided value, message and stack. This /// constructor does not take a Runtime parameter, and therefore cannot result /// in recursively invoking the JSError constructor. JSError(Value&& value, std::string message, std::string stack); + /// Creates a JSError referring to new \c EvalError instance. The error + /// message property is set to given \c message. + static JSError createEvalError(IRuntime& rt, const std::string& message); + + /// Creates a JSError referring to new \c RangeError instance. The error + /// message property is set to given \c message. + static JSError createRangeError(IRuntime& rt, const std::string& message); + + /// Creates a JSError referring to new \c ReferenceError instance. The error + /// message property is set to given \c message. + static JSError createReferenceError(IRuntime& rt, const std::string& message); + + /// Creates a JSError referring to new \c SyntaxError instance. The error + /// message property is set to given \c message. + static JSError createSyntaxError(IRuntime& rt, const std::string& message); + + /// Creates a JSError referring to new \c TypeError instance. The error + /// message property is set to given \c message. + static JSError createTypeError(IRuntime& rt, const std::string& message); + + /// Creates a JSError referring to new \c URIError instance. The error + /// message property is set to given \c message. + static JSError createURIError(IRuntime& rt, const std::string& message); + JSError(const JSError&) = default; virtual ~JSError(); @@ -1534,7 +2225,7 @@ class JSI_EXPORT JSError : public JSIException { // This initializes the value_ member and does some other // validation, so it must be called by every branch through the // constructors. - void setValue(Runtime& rt, Value&& value); + void setValue(IRuntime& rt, Value&& value); // This needs to be on the heap, because throw requires the object // be copyable, and Value is not. @@ -1543,6 +2234,32 @@ class JSI_EXPORT JSError : public JSIException { std::string stack_; }; +/// Helper function to cast the object pointed to by \p ptr into an interface +/// specified by \c U. If cast is successful, return a pointer to the object +/// as a raw pointer of \c U. Otherwise, return nullptr. +/// The returned interface same lifetime as the object referenced by \p ptr. +template +U* castInterface(T* ptr) { + if (ptr) { + return static_cast(ptr->castInterface(U::uuid)); + } + return nullptr; +} + +/// Helper function to cast the object managed by the shared_ptr \p ptr into an +/// interface specified by \c U. If the cast is successful, return a shared_ptr +/// of type \c U to the object. Otherwise, return an empty pointer. +/// The returned shared_ptr shares ownership of the object with \p ptr. +template +std::shared_ptr dynamicInterfaceCast(T&& ptr) { + auto* p = ptr->castInterface(U::uuid); + U* res = static_cast(p); + if (res) { + return std::shared_ptr(std::forward(ptr), res); + } + return nullptr; +} + } // namespace jsi } // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/test/testlib.h b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/test/testlib.h index 9f30fb2d..b56d41b8 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/test/testlib.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/jsi/test/testlib.h @@ -19,7 +19,7 @@ namespace jsi { class Runtime; -using RuntimeFactory = std::function()>; +using RuntimeFactory = std::function()>; std::vector runtimeGenerators(); @@ -42,7 +42,7 @@ class JSITestBase : public ::testing::TestWithParam { } RuntimeFactory factory; - std::unique_ptr runtime; + std::shared_ptr runtime; Runtime& rt; }; } // namespace jsi diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/napi/hermes_napi.h b/test-app/runtime/src/main/cpp/napi/hermes/include/napi/hermes_napi.h new file mode 100644 index 00000000..508a04e5 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/napi/hermes_napi.h @@ -0,0 +1,269 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#ifndef HERMES_NAPI_HERMES_NAPI_H +#define HERMES_NAPI_HERMES_NAPI_H + +#include "hermes/napi/node_api.h" + +//=========================================================================== +// Host integration interface +//=========================================================================== + +/// Abstract interface that the host application can provide to integrate +/// with its runtime environment. This covers async work scheduling +/// (napi_create_async_work / napi_queue_async_work), thread-safe +/// function dispatch, libuv event loop access, and fatal exception +/// handling. Fields left as nullptr preserve default behavior — in +/// particular, async work and thread-safe function APIs will return +/// napi_generic_failure if the relevant callbacks are not provided. +/// +/// The host is responsible for the lifetime of this struct — it must +/// outlive the napi_env that references it. +struct hermes_napi_host { + /// Schedule \p execute to run on a worker thread. When execute + /// completes, schedule \p complete to run on the main (JS) thread. + /// \p data is passed through to both callbacks. + /// \p complete receives \p status == 0 on success, or + /// napi_cancelled if the work was cancelled. + void (*post_work)( + void *loop_data, + void *work_data, + void (*execute)(void *work_data), + void (*complete)(void *work_data, napi_status status)); + + /// Cancel a previously posted work item. The event loop should + /// attempt to cancel the work. If successful, the complete callback + /// from post_work should be called with status == napi_cancelled. + /// Returns true if cancellation was initiated, false if the work + /// has already started or completed. + bool (*cancel_work)(void *loop_data, void *work_data); + + /// Schedule \p callback to run on the main (JS) thread. + /// This is used by thread-safe functions to dispatch queued calls. + /// \p data is passed through to the callback. + void (*post_task)( + void *loop_data, + void *task_data, + void (*callback)(void *task_data)); + + /// Opaque data pointer passed as the first argument to post_work, + /// cancel_work, and post_task. Typically the host's event loop + /// instance. + void *data; + + /// If non-null, napi_get_uv_event_loop() returns this pointer. + /// The host is responsible for the lifetime — it must outlive the + /// napi_env. Embedders without libuv leave this nullptr (the + /// default), in which case napi_get_uv_event_loop() returns + /// napi_generic_failure. + struct uv_loop_s *uv_loop; + + /// If non-null, called by napi_fatal_exception() instead of aborting. + /// The host typically routes this to + /// process.emit('uncaughtException', err). + /// Receives the host data pointer, the napi_env, and the error value. + /// When null (the default), napi_fatal_exception() prints the error + /// and calls abort() via hermes_fatal(). + void (*fatal_exception)(void *data, napi_env env, napi_value err); + + /// Hold a long-lived reference on the event loop. The host should + /// keep the loop alive until a matching unref_loop call. Used by + /// threadsafe functions to model libuv-style "ref" semantics: while + /// any tsfn in an env is referenced, the env holds one ref so + /// producer threads can dispatch into JS without racing the loop's + /// shutdown. + /// + /// Contract: within a single napi_env, ref_loop / unref_loop calls + /// are paired and NEVER nested — every ref_loop is followed by a + /// matching unref_loop before the next ref_loop from that env. The + /// env coalesces all referenced tsfns into one ref/unref pair, so an + /// env contributes at most one outstanding ref at a time. + /// + /// Across distinct envs sharing the same host, multiple unmatched + /// refs may be in flight concurrently — one per env that has any + /// referenced tsfn — so the host implementation must accept + /// concurrent unmatched ref_loop calls (typically via a refcount + /// or its existing source-tracking mechanism). + /// + /// Optional — when null, TSFN ref/unref are tracked for API + /// compatibility only and have no effect on loop lifetime. + /// Must be paired with unref_loop. + void (*ref_loop)(void *loop_data); + + /// Release a long-lived loop reference previously taken by ref_loop. + /// Optional; null only if ref_loop is also null. + void (*unref_loop)(void *loop_data); +}; + +typedef hermes_napi_host hermes_napi_event_loop; + +//=========================================================================== +// Environment lifecycle (public API) +//=========================================================================== + +/// Create a new NAPI environment backed by a Hermes Runtime. +/// The \p hermes_runtime parameter is an opaque pointer to a +/// hermes::vm::Runtime instance. +/// +/// The env is owned by the Runtime and is automatically torn down and +/// freed when the Runtime is destroyed. The caller must keep the +/// Runtime alive for as long as it uses the returned pointer, and must +/// not free the env itself. +/// +/// Finalizer semantics at Runtime teardown: +/// +/// Finalizers registered via napi_wrap, napi_add_finalizer, +/// napi_create_external, etc. are guaranteed to be invoked exactly +/// once with the live env that owns the wrapped object. We never +/// invoke user finalizers with env == nullptr. +/// +/// Callbacks fire in one of two contexts, both with a non-null env: +/// +/// - Unrestricted: the wrapped object was collected while the GC +/// heap was fully functional — either during normal operation +/// (collection happens, callback is drained at the next +/// NAPI_PREAMBLE / drainJobs) or during the env's shutdown +/// phase (cleanup hooks, persistent-reference finalizers, the +/// instance-data finalizer, or thread-safe-function cleanup +/// transitively triggered a GC; the callback is drained at the +/// end of shutdown). The callback may freely allocate, call +/// into JS, and use the env as in any other context. +/// +/// - Restricted: the wrapped object was still reachable from JS +/// roots at teardown and was finalized by +/// getHeap().finalizeAll() itself. The callback is drained +/// after finalizeAll, with the GC heap in a post-mortem state. +/// Any NAPI call that would allocate or run JavaScript returns +/// napi_cannot_run_js instead of executing. A spec-conformant +/// finalizer (which only frees native resources — free(), +/// close(), delete, refcount decrement) is unaffected. A +/// finalizer that tries to call back into JS receives the +/// error code and may choose to log it. +/// +/// The optional \p host provides host integration callbacks (async work, +/// thread-safe functions, etc.); if nullptr, those APIs return +/// napi_generic_failure. +NAPI_EXTERN napi_env NAPI_CDECL +hermes_napi_create_env(void *hermes_runtime, hermes_napi_host *host = nullptr); + +/// Get the last module registered via the deprecated napi_module_register(). +/// Returns nullptr if no module has been registered. +NAPI_EXTERN const napi_module *NAPI_CDECL +hermes_napi_get_last_registered_module(); + +/// Load a NAPI addon from a shared library at \p path. +/// +/// This function: +/// 1. Opens the shared library via dlopen(). +/// 2. Looks up the `napi_register_module_v1` symbol (modern approach). +/// If not found, falls back to the deprecated `napi_module_register()` +/// approach (checking `hermes_napi_get_last_registered_module()`). +/// 3. Creates an empty `exports` object in the caller's env. +/// 4. Calls the module's init function with (env, exports). +/// 5. Stores the resulting exports object in \p result. +/// +/// The caller must provide a valid \p env with an open handle scope. +/// The module's CallbackBundles are owned by the caller's env. +/// +/// Returns napi_ok on success, or an error status on failure (with a +/// pending exception set on the env). +NAPI_EXTERN napi_status NAPI_CDECL +hermes_napi_load_module(napi_env env, const char *path, napi_value *result); + +//=========================================================================== +// Script execution +//=========================================================================== + +/// Flags for hermes_run_script(). The first field is the struct +/// size for ABI-stable extensibility — newer versions can append +/// fields without breaking older callers. +struct hermes_run_script_flags { + /// Size of this struct in bytes. Must be set to + /// sizeof(hermes_run_script_flags) by the caller. + size_t struct_size; + /// Run in strict mode. + bool strict; + /// Enable TypeScript support. + bool enable_ts; + /// Keep the compiled bytecode alive for the lifetime of the Runtime, + /// even after all references to it are gone. This lets the engine + /// avoid copying certain parts of the buffer, resulting in faster + /// load times. Do not set this for short-lived modules (e.g. REPL + /// input) — they would accumulate and never be freed. + bool persistent; +}; + +/// Compile and run JavaScript source in a single call. +/// +/// \p data and \p size describe a UTF-8 source buffer. If the last +/// byte is '\0', the source is used zero-copy (actual source length +/// is size-1). Otherwise, an internal copy is made to add the null +/// terminator required by the compiler. +/// +/// The runtime takes ownership of the buffer: \p finalize_cb is +/// called with (\p data, \p size, \p finalize_hint) when the buffer +/// is no longer needed. Pass NULL for \p finalize_cb if the buffer +/// is static or externally managed. +/// +/// \p source_url appears in stack traces (NULL → empty string). +/// \p flags controls compilation options (NULL → all defaults). +/// +/// Returns napi_ok on success, napi_pending_exception on JS or +/// compile error. +NAPI_EXTERN napi_status NAPI_CDECL hermes_run_script( + napi_env env, + const uint8_t *data, + size_t size, + void (*finalize_cb)(const uint8_t *data, size_t size, void *hint), + void *finalize_hint, + const char *source_url, + const hermes_run_script_flags *flags, + napi_value *result); + +//=========================================================================== +// Pre-compiled bytecode +//=========================================================================== + +/// Flags for hermes_run_bytecode(). The first field is the struct +/// size for ABI-stable extensibility — newer versions can append +/// fields without breaking older callers. +struct hermes_bytecode_flags { + size_t struct_size; + /// Keep the bytecode alive for the lifetime of the Runtime, even + /// after all references to it are gone. This lets the engine avoid + /// copying certain parts of the buffer, resulting in faster load + /// times. Do not set this for short-lived modules (e.g. REPL + /// input) — they would accumulate and never be freed. + bool persistent; + bool hides_epilogue; + bool funcs_are_builtins; +}; + +/// Run pre-compiled Hermes bytecode. +/// +/// \p data and \p size describe the bytecode buffer. The runtime +/// takes ownership: \p finalize_cb is called with (\p data, \p size, +/// \p finalize_hint) when the buffer is no longer needed. Pass NULL +/// for \p finalize_cb if the buffer is static or externally managed. +/// +/// \p source_url appears in stack traces (NULL → empty string). +/// \p flags controls runtime module behavior (NULL → all defaults). +/// +/// Returns napi_ok on success, napi_pending_exception on JS error, +/// or napi_generic_failure on bytecode validation failure. +NAPI_EXTERN napi_status NAPI_CDECL hermes_run_bytecode( + napi_env env, + const uint8_t *data, + size_t size, + void (*finalize_cb)(const uint8_t *data, size_t size, void *hint), + void *finalize_hint, + const char *source_url, + const hermes_bytecode_flags *flags, + napi_value *result); + +#endif // HERMES_NAPI_HERMES_NAPI_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/napi/hermes_napi_compile.h b/test-app/runtime/src/main/cpp/napi/hermes/include/napi/hermes_napi_compile.h new file mode 100644 index 00000000..7ce9b49a --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/napi/hermes_napi_compile.h @@ -0,0 +1,61 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#ifndef HERMES_NAPI_HERMES_NAPI_COMPILE_H +#define HERMES_NAPI_HERMES_NAPI_COMPILE_H + +#include "hermes/napi/node_api.h" + +#include + +/// Flags for hermes_compile_to_bytecode(). The first field is the struct +/// size for ABI-stable extensibility — newer versions can append +/// fields without breaking older callers. +struct hermes_compile_flags { + size_t struct_size; + /// Parse in strict mode. + bool strict; + /// Run the full optimization pipeline on the compiled IR. + bool optimize; + /// Emit async break check instructions, e.g. for enforcing execution + /// time limits. + bool emit_async_break_check; + /// Enable TypeScript support. + bool enable_ts; +}; + +/// Compile JavaScript source to serialized Hermes bytecode. +/// +/// \p source and \p source_size describe the UTF-8 source buffer. +/// For best performance, include the null terminator in the buffer +/// (i.e. source[source_size - 1] == '\0'); the actual source text is +/// then source_size - 1 bytes. If the buffer does not end with '\0', +/// the function makes an internal copy to add one. +/// +/// \p source_url appears in error messages and stack traces +/// (NULL -> empty string). +/// \p flags controls compilation behavior (NULL -> all defaults). +/// +/// On success, *bytecode_out and *bytecode_size_out receive a newly +/// allocated buffer containing the serialized bytecode. Free it with +/// hermes_free_bytecode(). +/// +/// Returns napi_ok on success, napi_pending_exception on parse/compile +/// error (the exception describes the error). +napi_status hermes_compile_to_bytecode( + napi_env env, + const uint8_t *source, + size_t source_size, + const char *source_url, + const hermes_compile_flags *flags, + uint8_t **bytecode_out, + size_t *bytecode_size_out); + +/// Free bytecode allocated by hermes_compile_to_bytecode(). +void hermes_free_bytecode(uint8_t *bytecode); + +#endif // HERMES_NAPI_HERMES_NAPI_COMPILE_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/napi/hermes_napi_impl.h b/test-app/runtime/src/main/cpp/napi/hermes/include/napi/hermes_napi_impl.h new file mode 100644 index 00000000..57d936d3 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/napi/hermes_napi_impl.h @@ -0,0 +1,606 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#ifndef HERMES_NAPI_HERMES_NAPI_IMPL_H +#define HERMES_NAPI_HERMES_NAPI_IMPL_H + +#include "hermes_napi.h" + +#include "hermes/VM/HermesValue.h" +#include "hermes/VM/Runtime.h" +#include "hermes/VM/WeakRef.h" + +#include +#include +#include +#include +#include +#include + +//=========================================================================== +// Callback info +//=========================================================================== + +/// The callback info structure passed to NAPI callbacks. +/// This is stack-allocated by the native function trampoline and holds +/// all the data that napi_get_cb_info and napi_get_new_target need. +/// +/// The \c thisArg pointer points to the 'this' value — either on the +/// register stack (for regular calls) or in a handle scope slot (for +/// constructor calls where a new 'this' object is synthesized). +/// The \c argsBase pointer always points to the 'this' slot on the +/// register stack, so that arguments can be accessed at argsBase[-(i+1)]. +struct napi_callback_info__ { + /// The NAPI environment. + napi_env env; + + /// Pointer to the 'this' PinnedHermesValue. For regular calls this + /// points into the register stack; for constructor calls it may + /// point into a handle scope slot. + const hermes::vm::PinnedHermesValue *thisArg; + + /// Pointer to the 'this' slot on the register stack. Arguments are + /// at argsBase[-(i+1)]. This always points to the register stack, + /// even for constructor calls. + const hermes::vm::PinnedHermesValue *argsBase; + + /// Number of JavaScript arguments (excluding 'this'). + unsigned argc; + + /// User data pointer from napi_create_function. + void *data; + + /// Pointer to the new.target PinnedHermesValue in the register stack. + /// Contains undefined for regular function calls. + const hermes::vm::PinnedHermesValue *newTarget; + + /// Get the i-th argument. Returns the HermesValue directly from the + /// register stack if i < argc, otherwise returns undefined. + hermes::vm::HermesValue getArg(unsigned i) const { + // Args are stored at decreasing addresses from argsBase. + // arg[i] is at argsBase[-(i+1)]. + return i < argc + ? static_cast(argsBase[-(int)(i + 1)]) + : hermes::vm::HermesValue::encodeUndefinedValue(); + } +}; + +//=========================================================================== +// Callback bundle +//=========================================================================== + +/// Data associated with each NAPI native function. Stored in a list +/// owned by napi_env__ and pointed to by the NativeFunction's context. +/// The bundle is allocated when napi_create_function is called and freed +/// when the env is destroyed. +struct CallbackBundle { + napi_env env; + napi_callback cb; + void *data; +}; + +//=========================================================================== +// Handle scope storage +//=========================================================================== + +/// A fixed-size block of PinnedHermesValue slots used for handle storage. +/// Once allocated, the block never moves in memory, so pointers to individual +/// slots (returned as napi_value) remain valid for the block's lifetime. +struct HandleBlock { + /// Number of slots per block. Chosen for cache efficiency while + /// keeping per-scope overhead low. + static constexpr size_t kSize = 64; + + hermes::vm::PinnedHermesValue slots[kSize]; +}; + +/// Descriptor for an open handle scope. Records the position in the handle +/// storage at the time the scope was opened, so that closing the scope can +/// reclaim all handles allocated since then. +struct HandleScopeDescriptor { + /// Index of the active block when this scope was opened. + size_t blockIndex; + + /// Number of used slots in that block when this scope was opened. + size_t slotIndex; + + /// Whether this is an escapable scope. + bool escapable = false; + + /// Whether napi_escape_handle has been called on this scope. + bool escapeCalled = false; + + /// For escapable scopes: pointer to the pre-allocated slot in the + /// parent scope where the escaped value will be stored. + hermes::vm::PinnedHermesValue *escapeSlot = nullptr; +}; + +//=========================================================================== +// napi_deferred__ definition +//=========================================================================== + +/// A deferred promise resolution. Stores the resolve and reject functions +/// captured from the Promise constructor's executor callback. These are +/// GC roots, marked by the env's custom roots function while the deferred +/// is active. The deferred is consumed (deleted) when +/// napi_resolve_deferred or napi_reject_deferred is called. +/// +/// Deferreds are stored in a doubly-linked list in the env for GC root +/// enumeration and cleanup. +struct napi_deferred__ { + /// The resolve function from the Promise executor. + hermes::vm::PinnedHermesValue resolve{}; + + /// The reject function from the Promise executor. + hermes::vm::PinnedHermesValue reject{}; + + /// Doubly-linked list pointers for the env's deferred list. + napi_deferred__ *prev_ = nullptr; + napi_deferred__ *next_ = nullptr; +}; + +//=========================================================================== +// napi_ref__ definition +//=========================================================================== + +/// A persistent reference to a JavaScript value that can be either strong +/// (prevents GC, refcount > 0) or weak (allows GC, refcount == 0). +/// +/// Strong references: The \c value field is marked as a GC root by the +/// env's custom roots function. The referenced value will not be collected. +/// +/// Weak references: For pointer types (objects, strings, bigints), a +/// \c WeakRef tracks GC liveness through a \c WeakRefSlot. The +/// \c value field is NOT marked as a root, so the GC may collect the +/// referent. For non-pointer types (numbers, booleans, undefined, null, +/// symbols), no GC tracking is needed — these values are always valid. +/// +/// References are stored in a doubly-linked list in the env for GC root +/// enumeration and cleanup. +/// A reference to a JS value with controllable prevent-collection semantics. +/// +/// Three states, defined by (refcount, weakSlot_): +/// +/// 1. Strong (refcount > 0, weakSlot_ == nullptr): +/// `value` holds the referenced value and is marked as a GC root. +/// +/// 2. Weak (refcount == 0, weakSlot_ != nullptr): +/// `value` is undefined. The actual value lives in the weak slot, which +/// the GC tracks — updating it if the object moves, or invalidating it +/// if collected. All value types (objects, strings, numbers, booleans, +/// symbols, etc.) go through the weak slot uniformly. +/// +/// 3. Known dead (refcount == 0, weakSlot_ == nullptr): +/// `value` is undefined. The referent was collected. Permanent state: +/// napi_reference_ref is a no-op returning 0, napi_get_reference_value +/// returns NULL. +/// +/// Transitions: +/// 1→2: napi_reference_unref to refcount 0. Value moves to a new slot. +/// 2→1: napi_reference_ref when slot is alive. Value restored from slot. +/// 2→3: napi_reference_ref when slot is dead, or env teardown. +struct napi_ref__ { + napi_env env; + + /// Reference count. >0 means strong (GC root), ==0 means weak. + uint32_t refcount; + + /// When strong (refcount > 0), contains the referenced value and is + /// marked as a GC root. When weak (refcount == 0), always undefined — + /// the actual value lives in the weakSlot_. + hermes::vm::PinnedHermesValue value{}; + + /// When weak: tracks the value and its liveness. The GC updates or + /// invalidates the slot as needed. Null for strong refs or for weak + /// refs that are known dead (referent was collected). + hermes::vm::WeakRefSlot *weakSlot_ = nullptr; + + /// Doubly-linked list pointers for the env's reference list. + napi_ref__ *prev_ = nullptr; + napi_ref__ *next_ = nullptr; + + /// Optional destructor callback. Called during GC or env teardown, + /// but NOT by napi_delete_reference (matching V8 behavior). + napi_finalize finalize_cb = nullptr; + void *finalize_data = nullptr; + void *finalize_hint = nullptr; + + /// Set to true when this reference is being cleaned up during env + /// teardown. Prevents re-entrant deletion when a finalizer calls + /// napi_delete_reference on the same reference being finalized. + bool deletionPending_ = false; + + /// Return true if this is a strong reference (refcount > 0). + bool isStrong() const { + return refcount > 0; + } + + /// Move the value into a weak slot. Called when transitioning from + /// strong to weak, or when creating a new weak reference. + void createWeakSlot(hermes::vm::Runtime &runtime) { + assert(!weakSlot_ && "weak slot already exists"); + auto shv = hermes::vm::SmallHermesValue::encodeHermesValue(value, runtime); + weakSlot_ = runtime.getHeap().allocWeakSlot(shv); + value = hermes::vm::HermesValue::encodeUndefinedValue(); + } + + /// Release the weak slot. Called when transitioning from weak to + /// strong, or when the reference is deleted. + void releaseWeakSlot() { + if (weakSlot_) { + weakSlot_->free(); + weakSlot_ = nullptr; + } + } + + /// Check if the weak reference is still valid (referent not collected). + /// Strong refs are always valid. Weak refs with no slot are known dead. + bool isWeakValid() const { + if (isStrong()) + return true; + if (!weakSlot_) + return false; // known dead + return weakSlot_->hasValue(); + } + + /// Get the referenced value from the weak slot, with a read barrier. + /// Only valid when the weak slot exists and hasValue() is true. + hermes::vm::HermesValue getWeakValue(hermes::vm::Runtime &runtime) const { + assert(weakSlot_ && "no weak slot"); + assert(weakSlot_->hasValue() && "weak ref is dead"); + return weakSlot_->getValue(runtime, runtime.getHeap()); + } +}; + +//=========================================================================== +// napi_async_cleanup_hook_handle__ definition +//=========================================================================== + +/// Handle for an async cleanup hook registered via +/// napi_add_async_cleanup_hook. Stores the user's hook function and +/// data, and is linked into the env's asyncCleanupHooks_ list. +/// During env teardown, the hook is called with this handle (so it can +/// call napi_remove_async_cleanup_hook) and the user data. +struct napi_async_cleanup_hook_handle__ { + napi_env env; + napi_async_cleanup_hook hook; + void *arg; +}; + +//=========================================================================== +// napi_env__ definition +//=========================================================================== + +/// The core environment structure for the Hermes NAPI implementation. +/// Each napi_env holds a reference to a Hermes VM Runtime and manages +/// error state, pending exceptions, handle scopes, and (in future phases) +/// persistent references and cleanup hooks. +struct napi_env__ { + /// Create a new NAPI environment backed by the given Runtime. + /// The Runtime's lifetime must exceed this env's lifetime. + /// The optional \p host provides host integration callbacks. + explicit napi_env__( + hermes::vm::Runtime &runtime, + hermes_napi_host *host = nullptr); + + /// Destructor. + ~napi_env__(); + + /// Non-copyable, non-movable. + napi_env__(const napi_env__ &) = delete; + napi_env__ &operator=(const napi_env__ &) = delete; + + //--- Handle scope management --- + + /// Allocate a new PinnedHermesValue slot in the current (topmost) handle + /// scope, store \p val in it, and return a pointer to the slot. The + /// returned pointer is valid until the enclosing handle scope is closed. + /// Returns nullptr if no handle scope is open. + napi_value addToCurrentScope(hermes::vm::HermesValue val); + + /// Mark all live handle scope slots as GC roots via \p acceptor. + void markHandleScopes(hermes::vm::RootAcceptor &acceptor); + + //--- Deferred finalization --- + + /// Queue a finalizer callback for deferred execution outside GC. + /// Called from GC finalizers (NativeState, DecoratedObject) which + /// must not call back into JS during GC sweep. + void queuePendingFinalizer(napi_finalize cb, void *data, void *hint); + + /// Drain all pending finalizer callbacks. Called at safe points + /// outside of GC (NAPI_PREAMBLE, env teardown) to execute the + /// queued callbacks. + void drainPendingFinalizers(); + + /// Drive substantive shutdown of this environment. Drains pending + /// finalizers, runs cleanup hooks, finalizes persistent references, + /// runs the instance data finalizer, and tears down deferreds and + /// thread-safe functions. Registered as a Runtime shutdown + /// callback so it runs before Runtime::~Runtime calls + /// getHeap().finalizeAll(), with a fully functional heap. + /// + /// User code invoked here (cleanup hooks, ref finalizers, etc.) + /// may transitively trigger GC, which queues wrap callbacks via + /// finalizeNapiObjectData. A final drainPendingFinalizers() at + /// the end of shutdown() runs those callbacks while the heap is + /// still fully functional, so they have unrestricted env access. + /// + /// After this returns, the env structure still exists (it must + /// outlive finalizeAll so finalizeNapiObjectData can call + /// queuePendingFinalizer for wrapped objects still alive at + /// teardown). Only callbacks queued by finalizeAll itself end + /// up in the Runtime's post-shutdown deleter, where + /// inPostShutdownDrain_ is set and NAPI calls that would + /// allocate or run JS return napi_cannot_run_js. + void shutdown(); + + //--- Reference management --- + + /// Add a reference to the env's linked list. + void addReference(napi_ref__ *ref); + + /// Remove a reference from the env's linked list. + void removeReference(napi_ref__ *ref); + + /// Mark all strong references as GC roots via \p acceptor. + void markReferences(hermes::vm::RootAcceptor &acceptor); + + //--- Deferred management --- + + /// Add a deferred to the env's linked list for GC root marking. + void addDeferred(napi_deferred__ *def); + + /// Remove a deferred from the env's linked list. + void removeDeferred(napi_deferred__ *def); + + /// Mark all active deferreds as GC roots via \p acceptor. + void markDeferreds(hermes::vm::RootAcceptor &acceptor); + + //--- Thread-safe function management --- + + /// Add a TSFN to the env's linked list for GC root marking. + void addTsfn(napi_threadsafe_function__ *tsfn); + + /// Remove a TSFN from the env's linked list. + void removeTsfn(napi_threadsafe_function__ *tsfn); + + /// Mark all active TSFNs as GC roots via \p acceptor. + void markTsfns(hermes::vm::RootAcceptor &acceptor); + + /// Acquire a tsfn loop reference. On the 0 → 1 transition, calls + /// host->ref_loop. On other increments, just bumps the counter. + void acquireTsfnLoopRef(); + + /// Release a tsfn loop reference. On the 1 → 0 transition, calls + /// host->unref_loop. On other decrements, just lowers the counter. + void releaseTsfnLoopRef(); + + /// The Hermes VM runtime this environment is bound to. + hermes::vm::Runtime &runtime; + + /// Last error information returned by napi_get_last_error_info. + napi_extended_error_info last_error{}; + + /// Whether there is a pending JavaScript exception. + bool hasPendingException = false; + + /// Storage for the pending JavaScript exception value. + /// This is a GC root — it is marked during GC via the custom roots + /// function registered in the constructor. + hermes::vm::PinnedHermesValue pendingException{}; + + /// Module API version. Defaults to NAPI_VERSION. + int32_t module_api_version = NAPI_VERSION; + + /// Number of currently open handle scopes (for validation). + int open_handle_scopes = 0; + + /// Stack of open handle scope descriptors (LIFO). + std::vector scopeStack_; + + /// Pool of handle blocks. Blocks are allocated on demand and reused + /// across scope open/close cycles to avoid repeated allocation. + /// Pointers to slots within these blocks are handed out as napi_value. + std::vector> blocks_; + + /// Index of the current (partially filled) block in blocks_. + size_t currentBlockIndex_ = 0; + + /// Number of slots used in the current block. + size_t currentSlotIndex_ = 0; + + /// Callback bundles for native functions. Each bundle is owned by the + /// env and freed when the env is destroyed. We use a deque so that + /// pointers to bundles (stored as NativeFunction context) remain stable. + std::deque callbackBundles_; + + /// Head of the doubly-linked list of persistent references (napi_ref). + /// Used for GC root marking (strong refs) and cleanup on env destruction. + napi_ref__ *refListHead_ = nullptr; + + /// Head of the doubly-linked list of active deferreds (napi_deferred). + /// Used for GC root marking of resolve/reject functions. + napi_deferred__ *deferredListHead_ = nullptr; + + /// The file name of the loaded NAPI module (set by + /// hermes_napi_load_module). Used by node_api_get_module_file_name. + std::string moduleFileName_; + + /// Registered environment cleanup hooks (LIFO order on teardown). + /// Each entry is a {function, arg} pair. Called in reverse order + /// during env destruction, before finalizers and other cleanup. + std::vector> cleanupHooks_; + + /// Registered async cleanup hooks (LIFO order on teardown). + /// Each entry is a heap-allocated handle. Called in reverse order + /// during env destruction, after sync cleanup hooks. + std::vector asyncCleanupHooks_; + + /// Per-environment instance data (set by napi_set_instance_data). + void *instanceData_ = nullptr; + + /// Finalizer callback for instance data, called on env destruction or + /// when replaced by a new napi_set_instance_data call. + napi_finalize instanceDataFinalizeCb_ = nullptr; + + /// Hint passed to the instance data finalizer. + void *instanceDataFinalizeHint_ = nullptr; + + /// Optional host integration interface provided by the host + /// application. When non-null, enables async work APIs + /// (napi_queue_async_work, napi_cancel_async_work) and thread-safe + /// functions. When null, those APIs return napi_generic_failure. + /// Owned by the host; must outlive this env. + hermes_napi_host *host_ = nullptr; + + /// Number of currently open callback scopes (for validation in + /// napi_close_callback_scope). + int open_callback_scopes = 0; + + /// Cumulative external memory hint (bytes) reported via + /// napi_adjust_external_memory. Hermes GC does not support global + /// external memory hints (its API requires a specific GCCell), so + /// this counter is maintained for reporting purposes only. + int64_t externalMemory_ = 0; + + /// Head of the doubly-linked list of active thread-safe functions. + /// Used for GC root marking of JS function values. + napi_threadsafe_function__ *tsfnListHead_ = nullptr; + + /// Number of currently referenced thread-safe functions in this env. + /// While > 0, this env holds one host loop reference via host->ref_loop. + /// Incremented by tsfn create (when is_ref) and napi_ref_tsfn; + /// decremented by napi_unref_tsfn and tsfn finalize. + /// + /// The env coalesces all referenced tsfns into a single host + /// ref_loop / unref_loop pair — see the contract on hermes_napi_host. + int activeTsfnLoopRefs_ = 0; + + /// A pending finalizer callback queued during GC for deferred execution. + struct PendingFinalizer { + napi_finalize cb; + void *data; + void *hint; + }; + + /// Queue of finalizer callbacks deferred from GC sweep. GC finalizers + /// must not call back into JS (GC reentrancy), so they queue their + /// callbacks here. The queue is drained at safe points via + /// drainPendingFinalizers(). + std::vector pendingFinalizers_; + + /// Guards pendingFinalizers_ and drainingFinalizers_. Hades GC can queue + /// finalizers from a background thread while the JS thread drains them. + std::mutex pendingFinalizersMutex_; + + /// True while drainPendingFinalizers() is executing, to prevent + /// re-entrant draining (a callback may trigger GC which queues more). + bool drainingFinalizers_ = false; + + /// True while running the final post-finalizeAll drain in the + /// post-shutdown deleter. Set by the deleter before invoking + /// drainPendingFinalizers() and never cleared (the env is deleted + /// immediately after). + /// + /// At this point Runtime::~Runtime has already called + /// getHeap().finalizeAll(), so the GC heap is in a post-mortem + /// state — allocating new JS values or triggering a collection + /// would re-finalize already-finalized cells (UB). NAPI_PREAMBLE + /// returns napi_cannot_run_js when this flag is set, so any + /// finalizer callback that calls back into JS gets a defined + /// error instead of an undefined crash. Spec-conformant + /// finalizers (which only free native resources) ignore the + /// return and complete normally. + bool inPostShutdownDrain_ = false; +}; + +//=========================================================================== +// Internal helper functions +//=========================================================================== + +/// Clear the last error state in the environment. +inline napi_status napi_clear_last_error(node_api_basic_env env) { + env->last_error.error_code = napi_ok; + env->last_error.engine_error_code = 0; + env->last_error.engine_reserved = nullptr; + env->last_error.error_message = nullptr; + return napi_ok; +} + +/// Set the last error state in the environment and return the error code. +inline napi_status napi_set_last_error( + node_api_basic_env env, + napi_status error_code, + uint32_t engine_error_code = 0, + void *engine_reserved = nullptr) { + env->last_error.error_code = error_code; + env->last_error.engine_error_code = engine_error_code; + env->last_error.engine_reserved = engine_reserved; + return error_code; +} + +//=========================================================================== +// Argument checking macros +//=========================================================================== + +/// Return napi_invalid_arg if env is null, or napi_cannot_run_js if +/// the env is in its post-shutdown drain (running queued finalizers +/// after Runtime::~Runtime's finalizeAll). At that point the GC heap +/// is in a post-mortem state; allocating new JS values or calling +/// into JS would re-finalize already-finalized cells. The flag +/// gives finalizer callbacks that try to call back into JS a defined +/// error instead of an undefined crash. Spec-conformant finalizers +/// (which only free native resources) never see this code. +#define CHECK_ENV(env) \ + do { \ + if ((env) == nullptr) { \ + return napi_invalid_arg; \ + } \ + if ((env)->inPostShutdownDrain_) \ + return napi_cannot_run_js; \ + } while (0) + +/// Return the given status if the condition is false. +#define RETURN_STATUS_IF_FALSE(env, condition, status) \ + do { \ + if (!(condition)) { \ + return napi_set_last_error((env), (status)); \ + } \ + } while (0) + +/// Return napi_invalid_arg if the argument is null. +#define CHECK_ARG(env, arg) \ + RETURN_STATUS_IF_FALSE((env), ((arg) != nullptr), napi_invalid_arg) + +/// Propagate a non-ok status from a NAPI call. +#define STATUS_CALL(call) \ + do { \ + napi_status status = (call); \ + if (status != napi_ok) \ + return status; \ + } while (0) + +/// Preamble for NAPI functions that may call into JavaScript. +/// Validates env, checks for pending exceptions, and clears last error. +/// Functions that are exception-safe (handle scopes, error info, getters +/// for singletons, type checks, value extraction) should use CHECK_ENV +/// instead. +/// +/// CHECK_ENV (called first) returns napi_cannot_run_js if the env is +/// in its post-shutdown drain, so finalizer callbacks that try to call +/// back into JS get a defined error instead of triggering re-finalization. +#define NAPI_PREAMBLE(env) \ + do { \ + CHECK_ENV((env)); \ + (env)->drainPendingFinalizers(); \ + RETURN_STATUS_IF_FALSE( \ + (env), !(env)->hasPendingException, napi_pending_exception); \ + napi_clear_last_error((env)); \ + } while (0) + +#endif // HERMES_NAPI_HERMES_NAPI_IMPL_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include/napi/hermes_napi_internal.h b/test-app/runtime/src/main/cpp/napi/hermes/include/napi/hermes_napi_internal.h new file mode 100644 index 00000000..35510b95 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/hermes/include/napi/hermes_napi_internal.h @@ -0,0 +1,151 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#ifndef HERMES_NAPI_HERMES_NAPI_INTERNAL_H +#define HERMES_NAPI_HERMES_NAPI_INTERNAL_H + +#include "hermes_napi_impl.h" + +#include "hermes/VM/Callable.h" +#include "hermes/VM/HandleRootOwner.h" +#include "hermes/VM/StringPrimitive.h" + +/// Helper: capture the runtime's thrown value as a NAPI pending +/// exception and return \p status. +inline napi_status captureRuntimeException(napi_env env, napi_status status) { + env->pendingException = env->runtime.getThrownValue(); + env->hasPendingException = true; + env->runtime.clearThrownValue(); + return napi_set_last_error(env, status); +} + +/// Helper: intern a UTF-8 name as a SymbolID. The name is first +/// created as a StringPrimitive (handling all UTF-8 correctly), then +/// interned via the identifier table. Returns the SymbolID via +/// \p symRes. On failure, captures the runtime exception and returns +/// the error status. Requires an active GCScope. +inline napi_status internUtf8AsSymbol( + napi_env env, + const char *utf8name, + hermes::vm::CallResult> &symRes) { + using namespace hermes::vm; + + Runtime &runtime = env->runtime; + + // Create a StringPrimitive from the UTF-8 name. + auto strRes = StringPrimitive::createEfficient( + runtime, + UTF8Ref( + reinterpret_cast(utf8name), std::strlen(utf8name))); + if (LLVM_UNLIKELY(strRes == ExecutionStatus::EXCEPTION)) { + return captureRuntimeException(env, napi_pending_exception); + } + + // Intern the string to get a SymbolID. + symRes = runtime.getIdentifierTable().getSymbolHandleFromPrimitive( + runtime, + PseudoHandle::create(vmcast(*strRes))); + if (LLVM_UNLIKELY(symRes == ExecutionStatus::EXCEPTION)) { + return captureRuntimeException(env, napi_pending_exception); + } + + return napi_ok; +} + +/// Linked list node for finalizer callbacks (napi_add_finalizer). +struct NapiFinalizerEntry { + void *data; + napi_finalize finalize_cb; + void *finalize_hint; + NapiFinalizerEntry *next; +}; + +/// Consolidated per-object NAPI data. One allocation backs all of +/// napi_wrap, napi_add_finalizer, and napi_type_tag_object. +struct NapiObjectData { + napi_env env; + + // -- Wrap (napi_wrap) -- + bool hasWrap = false; + void *wrapData = nullptr; + napi_finalize wrapFinalizeCb = nullptr; + void *wrapFinalizeHint = nullptr; + + // -- Type tag (napi_type_tag_object) -- + bool hasTypeTag = false; + uint64_t typeTagLower = 0; + uint64_t typeTagUpper = 0; + + // -- Finalizer chain (napi_add_finalizer) -- + NapiFinalizerEntry *finalizerChain = nullptr; +}; + +/// Read-only lookup for NapiObjectData on an object. Returns the +/// NapiObjectData pointer in *outData, or nullptr if none exists. +/// Returns napi_invalid_arg if js_object is not an object. +/// Defined in hermes_napi_wrap.cpp. +napi_status +getNapiObjectData(napi_env env, napi_value js_object, NapiObjectData **outData); + +/// Lazy-creation lookup for NapiObjectData on an object. If the +/// internal property is absent, creates a new NapiObjectData and +/// defines the property. Caller must provide an active GCScope. +/// Defined in hermes_napi_wrap.cpp. +napi_status getOrCreateNapiObjectData( + napi_env env, + hermes::vm::Handle objHandle, + NapiObjectData **outData); + +/// The trampoline function that bridges Hermes's NativeFunctionPtr +/// signature with NAPI's napi_callback signature. Defined in +/// hermes_napi_function.cpp but declared here so it can be used from +/// other translation units (e.g., hermes_napi_object.cpp for +/// napi_define_properties). +hermes::vm::CallResult napiFunctionTrampoline( + void *context, + hermes::vm::Runtime &runtime); + +/// Constructor trampoline for NAPI functions. Handles both regular calls +/// and constructor calls (creating a 'this' object when called via 'new'). +/// Defined in hermes_napi_function.cpp. +hermes::vm::CallResult napiConstructorTrampoline( + void *context, + hermes::vm::Runtime &runtime); + +/// Helper: create a NativeFunction wrapping a napi_callback for use as +/// a method, getter, or setter in napi_define_properties and +/// napi_define_class. The callback bundle is stored in the env's deque +/// for lifetime management. Requires an active GCScope. Defined in +/// hermes_napi_object.cpp. +napi_status createNapiNativeFunction( + napi_env env, + napi_callback cb, + void *data, + hermes::vm::SymbolID name, + unsigned paramCount, + hermes::vm::PseudoHandle &out); + +/// Check if a HermesValue is a NAPI external (DecoratedObject, not +/// HostObject). Defined in hermes_napi_external.cpp. +bool isNapiExternal(hermes::vm::HermesValue hv); + +/// Set the type tag on a NAPI external value. Returns napi_invalid_arg +/// if the tag is already set. Defined in hermes_napi_external.cpp. +napi_status napiExternalSetTypeTag( + napi_env env, + hermes::vm::HermesValue hv, + const napi_type_tag *type_tag); + +/// Check the type tag on a NAPI external value. Sets *result to true +/// if the tag matches. Defined in hermes_napi_external.cpp. +napi_status napiExternalCheckTypeTag( + napi_env env, + hermes::vm::HermesValue hv, + const napi_type_tag *type_tag, + bool *result); + +#endif // HERMES_NAPI_HERMES_NAPI_INTERNAL_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/AsyncDebuggerAPI.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/AsyncDebuggerAPI.h deleted file mode 100644 index ea718dd4..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/AsyncDebuggerAPI.h +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_ASYNCDEBUGGERAPI_H -#define HERMES_ASYNCDEBUGGERAPI_H - -#ifdef HERMES_ENABLE_DEBUGGER - -#include -#include -#include -#include -#include - -#include -#include -#include - -#if defined(__clang__) && (!defined(SWIG)) && defined(_LIBCPP_VERSION) && \ - defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) -#include -#else -#ifndef TSA_GUARDED_BY -#define TSA_GUARDED_BY(x) -#endif -#ifndef TSA_NO_THREAD_SAFETY_ANALYSIS -#define TSA_NO_THREAD_SAFETY_ANALYSIS -#endif -#endif - -namespace facebook { -namespace hermes { -namespace debugger { - -class AsyncDebuggerAPI; - -enum class DebuggerEventType { - // Informational Events - ScriptLoaded, /// A script file was loaded, and the debugger has requested - /// pausing after script load. - Exception, /// An Exception was thrown. - Resumed, /// Script execution has resumed. - - // Events Requiring Next Command - DebuggerStatement, /// A debugger; statement was hit. - Breakpoint, /// A breakpoint was hit. - StepFinish, /// A Step operation completed. - ExplicitPause, /// A pause requested using Explicit AsyncBreak -}; - -/// This represents the list of possible commands that can be given to -/// \p resumeFromPaused. This is used instead of DebuggerAPI's Command class in -/// order to prevent callers from constructing an eval Command. The eval -/// functionality is implemented as a separate mechansim with -/// \p evalWhilePaused. -enum class AsyncDebugCommand { - Continue, /// Continues execution - StepInto, /// Perform a step into and then pause again - StepOver, /// Steps over the current instruction and then pause again - StepOut, /// Step out from the current scope and then pause again -}; - -using DebuggerEventCallback = std::function; -using DebuggerEventCallbackID = uint32_t; -constexpr const uint32_t kInvalidDebuggerEventCallbackID = 0; -using InterruptCallback = std::function; -using EvalCompleteCallback = std::function< - void(HermesRuntime &runtime, const debugger::EvalResult &result)>; - -/// This class wraps the DebuggerAPI to expose an asynchronous didPause -/// functionality as well as an interrupt API. This class must be constructed at -/// the same time as HermesRuntime. -/// -/// Functions in this class with the suffix "_TS" (Thread-Safe) are the only -/// functions that are safe to call on any thread. All other functions must be -/// called on the runtime thread. -class HERMES_EXPORT AsyncDebuggerAPI : private debugger::EventObserver { - /// Hide the constructor so users can only construct via static create - /// methods. - AsyncDebuggerAPI(HermesRuntime &runtime); - - public: - /// Creates an AsyncDebuggerAPI for use with the provided HermesRuntime. This - /// should be called and created at the same time as creating HermesRuntime. - static std::unique_ptr create(HermesRuntime &runtime); - - /// Must be destroyed on the runtime thread or when you're sure nothing is - /// interacting with the runtime. Must be destroyed before destroying - /// HermesRuntime. - ~AsyncDebuggerAPI() override; - - /// Add a callback function to invoke when the runtime pauses due to various - /// conditions such as hitting a "debugger;" statement. Can be called from any - /// thread. If there are no DebuggerEventCallback, then any reason that might - /// trigger a pause, such as a "debugger;" statement or breakpoints, will not - /// actually pause and will simply continue execution. Any caller that adds an - /// event callback cannot just be observing events and never call - /// \p resumeFromPaused in any of its code paths. The caller must either - /// expose UI enabling human action for controlling the debugger, or it must - /// have programmatic logic that controls the debugger via - /// \p resumeFromPaused. - DebuggerEventCallbackID addDebuggerEventCallback_TS( - DebuggerEventCallback callback); - - /// Remove a previously added callback function. If there is no callback - /// registered using the provided \p id, the function does nothing. - void removeDebuggerEventCallback_TS(DebuggerEventCallbackID id); - - /// Whether the runtime is currently paused waiting for the next action. - /// Should only be called from the runtime thread. - bool isWaitingForCommand(); - - /// Whether the runtime is currently paused for any reason (e.g. script - /// parsed, running interrupts, or waiting for a command). - /// Should only be called from the runtime thread. - bool isPaused(); - - /// Provide the next action to perform. Should only be called from the runtime - /// thread and only if the next command is expected to be set. - bool resumeFromPaused(AsyncDebugCommand command); - - /// Evaluate JavaScript code \p expression in the frame at index - /// \p frameIndex. Receives evaluation result in the \p callback. Should only - /// be called from the runtime thread and only if debugger is paused waiting - /// for the next action. - bool evalWhilePaused( - const std::string &expression, - uint32_t frameIndex, - EvalCompleteCallback callback); - - /// Request to interrupt the runtime at a convenient time and get a callback - /// on the runtime thread. Guaranteed to run "exactly once". This function can - /// be called from any thread, but cannot be called while inside a - /// DebuggerEventCallback. - void triggerInterrupt_TS(InterruptCallback callback); - - /// EventObserver implementation - debugger::Command didPause(debugger::Debugger &debugger) override; - - private: - struct EventCallbackEntry { - DebuggerEventCallbackID id; - DebuggerEventCallback callback; - }; - - /// This function infinite loops and uses \p signal_ to block the runtime - /// thread. It gets woken up if new InterruptCallback is queued or if - /// DebuggerEventCallback changes. - void processInterruptWhilePaused() TSA_NO_THREAD_SAFETY_ANALYSIS; - - /// Dequeues the next InterruptCallback if any. - std::optional takeNextInterruptCallback(); - - /// If \p ignoreNextCommand is true, then runs every InterruptCallback that - /// has been queued up so far. If \p ignoreNextCommand is false, then attempt - /// to run all interrupts, but will stop if any interrupt sets a next command. - void runInterrupts(bool ignoreNextCommand = true); - - /// Returns the next DebuggerEventCallback to execute if any. - std::optional takeNextEventCallback(); - - /// Runs every DebuggerEventCallback that has been registered. - void runEventCallbacks(DebuggerEventType event); - - HermesRuntime &runtime_; - - /// Whether the runtime thread is currently paused in \p didPause and needs to - /// be told what action to take next. - bool isWaitingForCommand_; - - /// Stores the command to return from \p didPause. - debugger::Command nextCommand_; - - /// Callback function to invoke after getting EvalResult from EvalComplete in - /// didPause. Used once and then cleared out. - EvalCompleteCallback oneTimeEvalCompleteCallback_{}; - - /// Tracks whether we are already in a didPause callback to detect recursive - /// calls to didPause. - bool inDidPause_ = false; - - /// Next ID to use when adding a DebuggerEventCallback. - uint32_t nextEventCallbackID_ TSA_GUARDED_BY(mutex_); - - /// Callback functions to invoke to notify events in \p didPause. Using - /// std::list which requires O(N) search when removing an element, but removal - /// should be a rare event. So the choice of using std::list is to optimize - /// for typical usage. - std::list eventCallbacks_ TSA_GUARDED_BY(mutex_){}; - - /// Iterator for eventCallbacks_. Used to traverse through the list when - /// running the callbacks. - std::list::iterator eventCallbackIterator_ - TSA_GUARDED_BY(mutex_); - - /// Queue of interrupt callback functions to invoke. - std::queue interruptCallbacks_ TSA_GUARDED_BY(mutex_){}; - - /// Used as a mechanism to block the runtime thread in \p didPause and for - /// protecting variables used across threads. - std::mutex mutex_{}; - /// Used to implement \p triggerInterrupt while \p didPause is holding onto - /// the runtime thread. - std::condition_variable signal_{}; -}; - -} // namespace debugger -} // namespace hermes -} // namespace facebook - -#else // !HERMES_ENABLE_DEBUGGER - -#include -#include -#include - -namespace facebook { -namespace hermes { -namespace debugger { - -class AsyncDebuggerAPI; - -enum class DebuggerEventType { - // Informational Events - ScriptLoaded, /// A script file was loaded, and the debugger has requested - /// pausing after script load. - Exception, /// An Exception was thrown. - Resumed, /// Script execution has resumed. - - // Events Requiring Next Command - DebuggerStatement, /// A debugger; statement was hit. - Breakpoint, /// A breakpoint was hit. - StepFinish, /// A Step operation completed. - ExplicitPause, /// A pause requested using Explicit AsyncBreak -}; - -/// This represents the list of possible commands that can be given to -/// \p resumeFromPaused. This is used instead of DebuggerAPI's Command class in -/// order to prevent callers from constructing an eval Command. The eval -/// functionality is implemented as a separate mechansim with -/// \p evalWhilePaused. -enum class AsyncDebugCommand { - Continue, /// Continues execution - StepInto, /// Perform a step into and then pause again - StepOver, /// Steps over the current instruction and then pause again - StepOut, /// Step out from the current scope and then pause again -}; - -using DebuggerEventCallback = std::function; -using DebuggerEventCallbackID = uint32_t; -constexpr const uint32_t kInvalidDebuggerEventCallbackID = 0; -using InterruptCallback = std::function; -using EvalCompleteCallback = std::function< - void(HermesRuntime &runtime, const debugger::EvalResult &result)>; - -class HERMES_EXPORT AsyncDebuggerAPI { - public: - static std::unique_ptr create(HermesRuntime &runtime) { - return nullptr; - } - - ~AsyncDebuggerAPI() {} - - DebuggerEventCallbackID addDebuggerEventCallback_TS( - DebuggerEventCallback callback) { - return kInvalidDebuggerEventCallbackID; - } - - void removeDebuggerEventCallback_TS(DebuggerEventCallbackID id) {} - - bool isWaitingForCommand() { - return false; - } - - bool isPaused() { - return false; - } - - bool resumeFromPaused(AsyncDebugCommand command) { - return false; - } - - bool evalWhilePaused( - const std::string &expression, - uint32_t frameIndex, - EvalCompleteCallback callback) { - return false; - } - - void triggerInterrupt_TS(InterruptCallback callback) {} -}; - -} // namespace debugger -} // namespace hermes -} // namespace facebook - -#endif // !HERMES_ENABLE_DEBUGGER - -#endif // HERMES_ASYNCDEBUGGERAPI_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/CompileJS.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/CompileJS.h deleted file mode 100644 index 68db11a7..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/CompileJS.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_COMPILEJS_H -#define HERMES_COMPILEJS_H - -#include -#include -#include - -namespace hermes { - -/// Interface for receiving errors, warnings and notes produced by compileJS. -class DiagnosticHandler { - public: - enum Kind { - Error, - Warning, - Note, - }; - - struct Diagnostic { - Kind kind; - int line; /// 1-based index - int column; /// 1-based index - std::string message; - /// 0-based char indices in half-open intervals - std::vector> ranges; - }; - - /// Called once for each diagnostic message produced during compilation. - virtual void handle(const Diagnostic &diagnostic) = 0; - virtual ~DiagnosticHandler() = default; -}; - -/// Compiles JS source \p str and if compilation is successful, returns true -/// and outputs to \p bytecode otherwise returns false. -/// \param sourceURL this will be used as the "file name" of the buffer for -/// errors, stack traces, etc. -/// \param optimize this will enable optimizations. -/// \param emitAsyncBreakCheck this will make the bytecode interruptable. -/// \param diagHandler if not null, receives any and all errors, warnings and -/// notes produced during compilation. -/// \param sourceMapBuf optional source map string. -/// \param debug Wether to generate debugging information in generated bytecode. -bool compileJS( - const std::string &str, - const std::string &sourceURL, - std::string &bytecode, - bool optimize, - bool emitAsyncBreakCheck, - DiagnosticHandler *diagHandler, - std::optional sourceMapBuf = std::nullopt, - bool debug = false); - -bool compileJS( - const std::string &str, - std::string &bytecode, - bool optimize = true); - -bool compileJS( - const std::string &str, - const std::string &sourceURL, - std::string &bytecode, - bool optimize = true); - -/// Options for overload of compileJS that accepts CompileJSOptions. -struct CompileJSOptions { - /// If true, the bytecode will be optimized. - bool optimize{true}; - /// Maximum number of instructions (in addition to parameter handling) - /// that is allowed for inlining of small functions. - unsigned inlineMaxSize{50}; - /// If true, the bytecode will be interruptable. - bool emitAsyncBreakCheck{false}; - /// If true, debugging information will be generated in the bytecode. - bool debug{false}; -}; - -/// Like the other compileJS overloads, but takes a struct of options with some -/// additional configurability. -bool compileJS( - const std::string &str, - const std::string &sourceURL, - std::string &bytecode, - const CompileJSOptions &options, - DiagnosticHandler *diagHandler, - std::optional sourceMapBuf = std::nullopt); - -} // namespace hermes - -#endif diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/DebuggerAPI.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/DebuggerAPI.h deleted file mode 100644 index 61b0c48b..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/DebuggerAPI.h +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_DEBUGGERAPI_H -#define HERMES_DEBUGGERAPI_H - -#ifdef HERMES_ENABLE_DEBUGGER - -#include -#include -#include -#include - -#include "hermes/Public/DebuggerTypes.h" - -// Forward declarations of internal types. -namespace hermes { -namespace vm { -class CodeBlock; -class Debugger; -class Runtime; -struct DebugCommand; -class HermesValue; -} // namespace vm -} // namespace hermes - -namespace facebook { -namespace hermes { -class HermesRuntime; -// Forward declaration of the internal Root API class, which is marked as a -// friend of the Debugger. -class HermesRootAPI; - -namespace debugger { - -class Debugger; -class EventObserver; - -/// Represents a variable in the debugger. -struct HERMES_EXPORT VariableInfo { - /// Name of the variable in the source. - String name; - - /// Value of the variable. - ::facebook::jsi::Value value; -}; - -/// An EvalResult represents the result of an Eval command. -struct HERMES_EXPORT EvalResult { - /// The resulting JavaScript object, or the thrown exception. - ::facebook::jsi::Value value; - - /// Indicates that the result was an exception. - bool isException = false; - - /// If isException is true, details about the exception. - ExceptionDetails exceptionDetails; - - EvalResult(EvalResult &&) = default; - EvalResult() = default; - - EvalResult( - ::facebook::jsi::Value value, - bool isException, - ExceptionDetails exceptionDetails) - : value(std::move(value)), - isException(isException), - exceptionDetails(std::move(exceptionDetails)) {} -}; - -/// ProgramState represents the state of a paused program. An instance of -/// ProgramState is available as the getProgramState() member function of class -/// Debugger. -class HERMES_EXPORT ProgramState { - public: - /// \return the reason for the Pause. - PauseReason getPauseReason() const { - return pauseReason_; - } - - /// \return the breakpoint if the PauseReason is Breakpoint, otherwise - /// kInvalidBreakpoint. - BreakpointID getBreakpoint() const { - return breakpoint_; - } - - /// \return the evaluation result if the PauseReason is due to EvalComplete. - EvalResult getEvalResult() const; - - /// \returns a stack trace for the current execution. - const StackTrace &getStackTrace() const { - return stackTrace_; - } - - /// \returns lexical information about the state in a given frame. - LexicalInfo getLexicalInfo(uint32_t frameIndex) const; - - /// \return information about a variable in a given lexical scope, in a given - /// frame. - VariableInfo getVariableInfo( - uint32_t frameIndex, - ScopeDepth scopeDepth, - uint32_t variableIndexInScope) const; - - /// \return information about the `this` value at a given stack depth. - VariableInfo getVariableInfoForThis(uint32_t frameIndex) const; - - /// \return the number of variables in a given frame. - /// This is deprecated: prefer using getLexicalInfoInFrame(). - uint32_t getVariablesCountInFrame(uint32_t frameIndex) const { - auto info = getLexicalInfo(frameIndex); - uint32_t result = 0; - for (ScopeDepth i = 0, max = info.getScopesCount(); i < max; i++) - result += info.getVariablesCountInScope(i); - return result; - } - - /// \return info for a variable at a given index \p variableIndex, in a given - /// frame at index \p frameIndex. - /// This is deprecated. Prefer the getVariableInfo() that takes three - /// parameters. - VariableInfo getVariableInfo(uint32_t frameIndex, uint32_t variableIndex) - const { - LexicalInfo info = getLexicalInfo(frameIndex); - uint32_t remaining = variableIndex; - for (ScopeDepth scope = 0;; scope++) { - assert(scope < info.getScopesCount() && "Index out of bounds"); - uint32_t count = info.getVariablesCountInScope(scope); - if (remaining < count) { - return getVariableInfo(frameIndex, scope, remaining); - } - remaining -= count; - } - } - - private: - friend Debugger; - /// ProgramState must not be copied, because some of its implementation - /// requires querying the live program state and so the state must not be - /// retained after the pause returns. - /// ProgramState must not be copied. - ProgramState(const ProgramState &) = delete; - ProgramState &operator=(const ProgramState &) = delete; - - ::hermes::vm::Debugger *impl() const; - - ProgramState(Debugger *dbg) : dbg_(dbg) {} - Debugger *dbg_; - PauseReason pauseReason_{}; - StackTrace stackTrace_; - EvalResult evalResult_; - BreakpointID breakpoint_{kInvalidBreakpoint}; -}; - -/// Command represents an action that you can request the debugger to perform -/// when returned from didPause(). -class HERMES_EXPORT Command { - public: - /// Commands may be moved. - Command(Command &&); - Command &operator=(Command &&); - ~Command(); - - /// \return a Command that steps with the given StepMode \p mode. - static Command step(StepMode mode); - - /// \return a Command that continues execution. - static Command continueExecution(); - - /// \return a Command that evaluates JavaScript code \p src in the - /// frame at index \p frameIndex. - static Command eval(const String &src, uint32_t frameIndex); - - /// \return a boolean whether this Command was constructed using the static - /// eval() method - bool isEval(); - - private: - friend Debugger; - explicit Command(::hermes::vm::DebugCommand &&); - std::unique_ptr<::hermes::vm::DebugCommand> debugCommand_; -}; - -/// Debugger allows access to the Hermes debugging functionality. An instance of -/// Debugger is available from HermesRuntime, and also passed to your -/// EventObserver. -class HERMES_EXPORT Debugger { - public: - /// Set the Debugger event observer. The event observer is notified of - /// debugging event, specifically when the program pauses. This is simply a - /// raw pointer: it is the client's responsibility to clear the event observer - /// if the event observer is deallocated before the Debugger. - void setEventObserver(EventObserver *observer); - - /// Sets the property %isDebuggerAttached in %DebuggerInternal object. Can be - /// called from any thread. - void setIsDebuggerAttached(bool isAttached); - - /// Asynchronously triggers a pause. This may be called from any thread. This - /// is inherently racey and the exact point at which the program pauses is not - /// guaranteed. You can discover when the program has paused through the event - /// observer. - void triggerAsyncPause(AsyncPauseKind kind); - - /// \return the ProgramState representing the state of the paused program. - /// This may only be invoked when the program is paused. - const ProgramState &getProgramState() const { - return state_; - } - - /// \return the source map URL for the \p fileId. - String getSourceMappingUrl(uint32_t fileId) const; - - /// Gets the list of loaded scripts. The order of the scripts in the vector - /// will be the same across calls. - /// \return list of loaded scripts - std::vector getLoadedScripts() const; - - /// Gets the current stack trace. - /// \return stack trace with call frames if runtime is in the interpreter - /// loop, otherwise return no call frames - StackTrace captureStackTrace() const; - - /// -- Breakpoint Management -- - - /// Sets a breakpoint on a given SourceLocation. - /// \return the ID of the breakpoint, 0 if it wasn't created. - BreakpointID setBreakpoint(SourceLocation loc); - - /// Sets the condition on breakpoint \p breakpoint. - /// The condition will be stored with the breakpoint, - /// and if non-empty, will be executed to determine whether to actually - /// pause on the breakpoint; only if ToBoolean(condition) is true - /// and does not throw will the debugger pause on \p breakpoint. - /// \param condition the code to execute to determine whether to break; - /// if empty, the condition is considered to not be set. - void setBreakpointCondition(BreakpointID breakpoint, const String &condition); - - /// Deletes a breakpoint. - void deleteBreakpoint(BreakpointID breakpoint); - - /// Deletes all breakpoints. - void deleteAllBreakpoints(); - - /// Mark a breakpoint as enabled. Breakpoints are by default enabled. - void setBreakpointEnabled(BreakpointID breakpoint, bool enable); - - /// \return information on a breakpoint. - BreakpointInfo getBreakpointInfo(BreakpointID breakpoint); - - /// \return a list of extant breakpoints. - std::vector getBreakpoints(); - - /// Set whether the debugger should pause when an exception is thrown. - void setPauseOnThrowMode(PauseOnThrowMode mode); - - /// \return whether the debugger pauses when an exception is thrown. - PauseOnThrowMode getPauseOnThrowMode() const; - - /// Set whether the debugger should pause after a script was loaded. - void setShouldPauseOnScriptLoad(bool flag); - - /// \return whether the debugger should pause after a script was loaded. - bool getShouldPauseOnScriptLoad() const; - - /// \return the thrown value if paused on an exception, or - /// jsi::Value::undefined() if not. - ::facebook::jsi::Value getThrownValue(); - - private: - friend HermesRootAPI; - friend std::unique_ptr hermes::makeHermesRuntime( - const ::hermes::vm::RuntimeConfig &); - friend std::unique_ptr - hermes::makeThreadSafeHermesRuntime(const ::hermes::vm::RuntimeConfig &); - friend ProgramState; - - /// Debuggers may not be moved or copied. - Debugger(const Debugger &) = delete; - void operator=(const Debugger &) = delete; - Debugger(Debugger &&) = delete; - void operator=(Debugger &&) = delete; - - /// Implementation detail used by ProgramState. - ::facebook::jsi::Value jsiValueFromHermesValue(::hermes::vm::HermesValue hv); - - explicit Debugger( - ::facebook::hermes::HermesRuntime *runtime, - ::hermes::vm::Runtime &vmRuntime); - - ::facebook::hermes::HermesRuntime *const runtime_; - EventObserver *eventObserver_ = nullptr; - ::hermes::vm::Runtime &vmRuntime_; - ::hermes::vm::Debugger *impl_; - ProgramState state_; -}; - -/// A subclass of EventObserver may be set on the Debugger via -/// setEventObserver(). It receives notifications when the Debugger pauses. -class HERMES_EXPORT EventObserver { - public: - /// didPause() is invoked when the JavaScript program has paused. The - /// The Debugger \p debugger can be used to manipulate breakpoints and enqueue - /// debugger commands such as stepping, etc. It can also be used to discover - /// the call stack and variables via debugger.getProgramState(). - /// \return a Command for the debugger to perform. - virtual Command didPause(Debugger &debugger) = 0; - - /// Invoked when the debugger resolves a previously unresolved breakpoint. - /// Note that the debugger is *not* paused during this, - /// and thus debugger.getProgramState() is not valid. - /// This callback may not invoke JavaScript or enqueue debugger commands. - virtual void breakpointResolved(Debugger &debugger, BreakpointID breakpoint) { - } - - virtual ~EventObserver(); -}; - -} // namespace debugger -} // namespace hermes -} // namespace facebook - -#else // !HERMES_ENABLE_DEBUGGER - -#include - -#include "hermes/Public/DebuggerTypes.h" - -namespace facebook { -namespace hermes { -namespace debugger { - -class EventObserver; - -struct VariableInfo { - String name; - ::facebook::jsi::Value value; -}; - -struct EvalResult { - ::facebook::jsi::Value value; - bool isException = false; - ExceptionDetails exceptionDetails; - - EvalResult(EvalResult &&) = default; - EvalResult() = default; - - EvalResult( - ::facebook::jsi::Value value, - bool isException, - ExceptionDetails exceptionDetails) - : value(std::move(value)), - isException(isException), - exceptionDetails(std::move(exceptionDetails)) {} -}; - -class ProgramState { - public: - ProgramState() {} - - PauseReason getPauseReason() const { - return PauseReason::Exception; - } - - BreakpointID getBreakpoint() const { - return 0; - } - - EvalResult getEvalResult() const { - return EvalResult(); - } - - const StackTrace &getStackTrace() const { - return stackTrace_; - } - - LexicalInfo getLexicalInfo(uint32_t frameIndex) const { - return LexicalInfo(); - } - - VariableInfo getVariableInfo( - uint32_t frameIndex, - ScopeDepth scopeDepth, - uint32_t variableIndexInScope) const { - return VariableInfo(); - } - - VariableInfo getVariableInfoForThis(uint32_t frameIndex) const { - return VariableInfo(); - } - - uint32_t getVariablesCountInFrame(uint32_t frameIndex) const { - return 0; - } - - VariableInfo getVariableInfo(uint32_t frameIndex, uint32_t variableIndex) - const { - return VariableInfo(); - } - - private: - ProgramState(const ProgramState &) = delete; - ProgramState &operator=(const ProgramState &) = delete; - - StackTrace stackTrace_; -}; - -class Command { - public: - Command(Command &&) {} - Command &operator=(Command &&); - ~Command() {} - - static Command step(StepMode mode) { - return Command(); - } - static Command continueExecution() { - return Command(); - } - static Command eval(const String &src, uint32_t frameIndex) { - return Command(); - } - bool isEval() { - return false; - } - - private: - Command() {} -}; - -class Debugger { - public: - explicit Debugger() {} - - void setEventObserver(EventObserver *observer) {} - void setIsDebuggerAttached(bool isAttached) {} - void triggerAsyncPause(AsyncPauseKind kind) {} - const ProgramState &getProgramState() const { - return programState_; - } - String getSourceMappingUrl(uint32_t fileId) const { - return ""; - }; - std::vector getLoadedScripts() const { - return {}; - } - StackTrace captureStackTrace() const { - return StackTrace{}; - } - BreakpointID setBreakpoint(SourceLocation loc) { - return 0; - } - void setBreakpointCondition( - BreakpointID breakpoint, - const String &condition) {} - void deleteBreakpoint(BreakpointID breakpoint) {} - void deleteAllBreakpoints() {} - void setBreakpointEnabled(BreakpointID breakpoint, bool enable) {} - BreakpointInfo getBreakpointInfo(BreakpointID breakpoint) { - return BreakpointInfo(); - } - std::vector getBreakpoints() { - return std::vector(); - } - void setPauseOnThrowMode(PauseOnThrowMode mode) {} - PauseOnThrowMode getPauseOnThrowMode() const { - return PauseOnThrowMode::None; - } - void setShouldPauseOnScriptLoad(bool flag) {} - bool getShouldPauseOnScriptLoad() const { - return false; - } - ::facebook::jsi::Value getThrownValue() { - return ::facebook::jsi::Value::undefined(); - } - - private: - Debugger(const Debugger &) = delete; - void operator=(const Debugger &) = delete; - Debugger(Debugger &&) = delete; - void operator=(Debugger &&) = delete; - - ProgramState programState_; -}; - -class EventObserver { - public: - virtual Command didPause(Debugger &debugger) = 0; - virtual void breakpointResolved(Debugger &debugger, BreakpointID breakpoint) { - } - - virtual ~EventObserver() {} -}; - -} // namespace debugger -} // namespace hermes -} // namespace facebook - -#endif // !HERMES_ENABLE_DEBUGGER - -#endif // HERMES_DEBUGGERAPI_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/CrashManager.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/CrashManager.h deleted file mode 100644 index 07a9b592..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/CrashManager.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_PUBLIC_CRASHMANAGER_H -#define HERMES_PUBLIC_CRASHMANAGER_H - -#include - -#include -#include - -namespace hermes { -namespace vm { - -/// A CrashManager provides functions that determine what memory and data is -/// included in dumps in case of crashes. -class HERMES_EXPORT CrashManager { - public: - /// CallbackKey is the type of an identifier for a callback supplied to the - /// CrashManager. - using CallbackKey = int; - /// Type for the callback function invoked on crash. The fd supplied is a raw - /// file stream an implementation should write a JSON object to. - using CallbackFunc = std::function; - - /// Registers some memory to be included in any crash dump that occurs. - /// \param mem A pointer to allocated memory. It must be unregistered - /// before being freed. - /// \param length The number of bytes the memory controls. - virtual void registerMemory(void *mem, size_t length) = 0; - - /// Unregisters some memory from being included in any crash dump that occurs. - virtual void unregisterMemory(void *mem) = 0; - - /// Registers custom data to be included in any crash dump that occurs. - /// Calling \c setCustomData on the same key twice will overwrite the previous - /// value. - /// \param key A tag to look for in the custom data output. Distinguishes - /// between multiple values. - /// \param val The value to store for the given key. - virtual void setCustomData(const char *key, const char *val) = 0; - - /// If the given \p key has an associated custom data string, remove the - /// association. If the key hasn't been set before, is a no-op. - virtual void removeCustomData(const char *key) = 0; - - /// Same as \c setCustomData, except it is only set for the current thread. - virtual void setContextualCustomData(const char *key, const char *val) = 0; - - /// Same as \c removeCustomData, except it is for keys set with \c - /// setContextualCustomData. - virtual void removeContextualCustomData(const char *key) = 0; - - /// Registers a function to be called after a crash has occurred. This - /// function can examine memory and serialize this to a JSON output stream. - /// Implmentations decide where the stream is routed to. - /// \param callback A function to called after a crash. - /// \return A CallbackKey representing the function you provided. Pass this - /// key into unregisterCallback when it that callback is no longer needed. - virtual CallbackKey registerCallback(CallbackFunc callback) = 0; - - /// Unregisters a previously registered callback. After this function returns, - /// the previously registered function will not be executed by this - /// CrashManager during a crash. - virtual void unregisterCallback(CallbackKey key) = 0; - - /// the heap information. - struct HeapInformation { - /// The amount of memory that is currently in use - size_t used_{0}; - /// The amount of memory that can currently be allocated - /// before a full GC is triggered. - size_t size_{0}; - }; - - /// Record the heap information. - /// \param heapInfo The current heap information - virtual void setHeapInfo(const HeapInformation &heapInfo) = 0; - - virtual ~CrashManager(); -}; - -/// A CrashManager that does nothing. -class HERMES_EXPORT NopCrashManager final : public CrashManager { - public: - void registerMemory(void *, size_t) override {} - void unregisterMemory(void *) override {} - void setCustomData(const char *, const char *) override {} - void removeCustomData(const char *) override {} - void setContextualCustomData(const char *, const char *) override {} - void removeContextualCustomData(const char *) override {} - CallbackKey registerCallback(CallbackFunc /*callback*/) override { - return 0; - } - void unregisterCallback(CallbackKey /*key*/) override {} - void setHeapInfo(const HeapInformation & /*heapInfo*/) override {} - - ~NopCrashManager() override; -}; - -} // namespace vm -} // namespace hermes -#endif diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/CtorConfig.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/CtorConfig.h deleted file mode 100644 index aff3f398..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/CtorConfig.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_PUBLIC_CTORCONFIG_H -#define HERMES_PUBLIC_CTORCONFIG_H - -#include - -/// Defines a new class, called \p NAME representing a constructor config, and -/// an associated builder class. -/// -/// The fields of the class (along with their types and default values) are -/// encoded in the \p FIELDS parameter, and any logic to be run whilst building -/// the config can be passed as a code block in \p BUILD_BODY. -/// -/// Example: -/// -/// Suppose we wish to define a configuration class called Foo, with the -/// following fields and default values: -/// -/// int A = 0; -/// int B = 42; -/// std::string C = "hello"; -/// -/// Such that the value in A is at most the length of \c C. -/// -/// We can do so with the following declaration: -/// -/// " #define FIELDS(F) \ " -/// " F(int, A) \ " -/// " F(int, B, 42) \ " -/// " F(std::string, C, "hello") " -/// " " -/// " _HERMES_CTORCONFIG_STRUCT(Foo, FIELDS, { " -/// " A_ = std::min(A_, C_.length()); " -/// " }); " -/// -/// N.B. -/// - The definition of A does not mention any value -- meaning it is -/// default initialised. -/// - References to the fields in the validation logic have a trailling -/// underscore. -/// -#define _HERMES_CTORCONFIG_STRUCT(NAME, FIELDS, BUILD_BODY) \ - class NAME { \ - FIELDS(_HERMES_CTORCONFIG_FIELD_DECL) \ - \ - public: \ - class Builder; \ - friend Builder; \ - FIELDS(_HERMES_CTORCONFIG_GETTER) \ - \ - /* returns a Builder that starts with the current config. */ \ - inline Builder rebuild() const; \ - \ - private: \ - inline void doBuild(const Builder &builder); \ - }; \ - \ - class NAME::Builder { \ - NAME config_; \ - \ - FIELDS(_HERMES_CTORCONFIG_FIELD_EXPLICIT_BOOL_DECL) \ - \ - public: \ - Builder() = default; \ - \ - explicit Builder(const NAME &config) : config_(config) {} \ - \ - inline const NAME build() { \ - config_.doBuild(*this); \ - return config_; \ - } \ - \ - /* The explicitly set fields of \p newconfig update \ - * the corresponding fields of \p this. */ \ - inline Builder update(const NAME::Builder &newConfig); \ - \ - FIELDS(_HERMES_CTORCONFIG_SETTER) \ - FIELDS(_HERMES_CTORCONFIG_FIELD_EXPLICIT_BOOL_ACCESSOR) \ - }; \ - \ - NAME::Builder NAME::rebuild() const { \ - return Builder(*this); \ - } \ - \ - NAME::Builder NAME::Builder::update(const NAME::Builder &newConfig) { \ - FIELDS(_HERMES_CTORCONFIG_UPDATE) \ - return *this; \ - } \ - \ - void NAME::doBuild(const NAME::Builder &builder) { \ - (void)builder; \ - BUILD_BODY \ - } - -/// Helper Macros - -#define _HERMES_CTORCONFIG_FIELD_DECL(CX, TYPE, NAME, ...) \ - TYPE NAME##_{__VA_ARGS__}; - -/// This ignores the first and trailing arguments, and defines a member -/// indicating whether field NAME was set explicitly. -#define _HERMES_CTORCONFIG_FIELD_EXPLICIT_BOOL_DECL(CX, TYPE, NAME, ...) \ - bool NAME##Explicit_{false}; - -/// This defines an accessor for the "Explicit_" fields defined above. -#define _HERMES_CTORCONFIG_FIELD_EXPLICIT_BOOL_ACCESSOR(CX, TYPE, NAME, ...) \ - bool has##NAME() const { \ - return NAME##Explicit_; \ - } - -/// Placeholder token for fields whose defaults are not constexpr, to make the -/// listings more readable. -#define HERMES_NON_CONSTEXPR - -#define _HERMES_CTORCONFIG_GETTER(CX, TYPE, NAME, ...) \ - inline TYPE get##NAME() const { \ - return NAME##_; \ - } \ - static CX TYPE getDefault##NAME() { \ - /* Instead of parens around TYPE (non-standard) */ \ - using TypeAsSingleToken = TYPE; \ - return TypeAsSingleToken{__VA_ARGS__}; \ - } - -#define _HERMES_CTORCONFIG_SETTER(CX, TYPE, NAME, ...) \ - inline auto with##NAME(TYPE NAME)->decltype(*this) { \ - config_.NAME##_ = std::move(NAME); \ - NAME##Explicit_ = true; \ - return *this; \ - } - -#define _HERMES_CTORCONFIG_BUILDER_GETTER(CX, TYPE, NAME, ...) \ - TYPE get##NAME() const { \ - return config_.NAME##_; \ - } - -#define _HERMES_CTORCONFIG_UPDATE(CX, TYPE, NAME, ...) \ - if (newConfig.has##NAME()) { \ - with##NAME(newConfig.config_.get##NAME()); \ - } - -#endif // HERMES_PUBLIC_CTORCONFIG_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/DebuggerTypes.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/DebuggerTypes.h deleted file mode 100644 index 0763c2e9..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/DebuggerTypes.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_PUBLIC_DEBUGGERTYPES_H -#define HERMES_PUBLIC_DEBUGGERTYPES_H - -#include -#include -#include - -namespace hermes { -namespace vm { -class Debugger; -} -} // namespace hermes - -namespace facebook { -namespace hermes { -namespace debugger { - -class ProgramState; - -/// Strings in the Debugger are UTF-8 encoded. When converting from a JavaScript -/// string, valid UTF-16 surrogate pairs are decoded. Surrogate halves are -/// converted into the Unicode replacement character. -using String = std::string; - -/// Debugging entities like breakpoints are identified by a unique ID. The -/// Debugger will not re-use IDs even across different entity types. 0 is an -/// invalid ID. -using BreakpointID = uint64_t; -// NOTE: Can't be kInvalidID due to a clash with MacTypes.h's define kInvalidID. -constexpr uint64_t kInvalidBreakpoint = 0; - -/// Scripts when loaded are identified by a script ID. -/// These are not reused within one invocation of the VM. -using ScriptID = uint32_t; - -/// A SourceLocation is a small value-type representing a location in a source -/// file. -constexpr uint32_t kInvalidLocation = ~0u; -struct SourceLocation { - /// Line in the source. 1 based. - uint32_t line = kInvalidLocation; - - /// Column in the source. 1 based. - uint32_t column = kInvalidLocation; - - /// Identifier of the source file. - ScriptID fileId = kInvalidLocation; - - /// Name of the source file. - String fileName; -}; - -/// CallFrameInfo is a value type representing an entry in a call stack. -struct CallFrameInfo { - /// Name of the function executing in this frame. - String functionName; - - /// Source location of the program counter for this frame. - SourceLocation location; -}; - -/// StackTrace represents a list of call frames, either in the current execution -/// or captured in an exception. -struct StackTrace { - /// \return the number of call frames. - uint32_t callFrameCount() const { - return frames_.size(); - } - - /// \return call frame info at a given index. 0 represents the topmost - /// (current) frame on the call stack. - CallFrameInfo callFrameForIndex(uint32_t index) const { - return frames_.at(index); - } - - StackTrace() {} - - private: - explicit StackTrace(std::vector frames) - : frames_(std::move(frames)){}; - friend ProgramState; - friend ::hermes::vm::Debugger; - std::vector frames_; -}; - -/// ExceptionDetails is a value type describing an exception. -struct ExceptionDetails { - /// Textual description of the exception. - String text; - - /// Location where the exception was thrown. - SourceLocation location; - - /// Get the stack trace associated with the exception. - const StackTrace &getStackTrace() const { - return stackTrace_; - } - - private: - friend ::hermes::vm::Debugger; - StackTrace stackTrace_; -}; - -/// A list of possible reasons for a Pause. -enum class PauseReason { - ScriptLoaded, /// A script file was loaded, and the debugger has requested - /// pausing after script load. - DebuggerStatement, /// A debugger; statement was hit. - Breakpoint, /// A breakpoint was hit. - StepFinish, /// A Step operation completed. - Exception, /// An Exception was thrown. - AsyncTriggerImplicit, /// The Pause is the result of - /// triggerAsyncPause(Implicit). - AsyncTriggerExplicit, /// The Pause is the result of - /// triggerAsyncPause(Explicit). - EvalComplete, /// An eval() function finished. -}; - -/// When stepping, the mode with which to step. -enum class StepMode { - Into, /// Enter into any function calls. - Over, /// Skip over any function calls. - Out, /// Step until the current function exits. -}; - -/// When setting pause on throw, this specifies when to pause. -enum class PauseOnThrowMode { - None, /// Never pause on exceptions. - Uncaught, /// Only pause on uncaught exceptions. - All, /// Pause any time an exception is thrown. -}; - -/// When requesting an async break, this specifies whether it was an implicit -/// break from the inspector or a user-requested explicit break. -enum class AsyncPauseKind { - /// Implicit pause to allow movement of jsi::Value types between threads. - /// The user will not be running commands and the inspector will immediately - /// request a Continue. - Implicit, - - /// Explicit pause requested by the user. - /// Clears any stepping state and allows the user to run their own commands. - Explicit, -}; - -/// A type representing depth in a lexical scope chain. -using ScopeDepth = uint32_t; - -/// Information about lexical entities (for now, just variable names). -struct LexicalInfo { - /// \return the number of scopes. - ScopeDepth getScopesCount() const { - return variableCountsByScope_.size(); - } - - /// \return the number of variables in a given scope. - uint32_t getVariablesCountInScope(ScopeDepth depth) const { - return variableCountsByScope_.at(depth); - } - - private: - friend ::hermes::vm::Debugger; - std::vector variableCountsByScope_; -}; - -/// Information about a breakpoint. -struct BreakpointInfo { - /// ID of the breakpoint. - /// kInvalidBreakpoint if the info is not valid. - BreakpointID id; - - /// Whether the breakpoint is enabled. - bool enabled; - - /// Whether the breakpoint has been resolved. - bool resolved; - - /// The originally requested location of the breakpoint. - SourceLocation requestedLocation; - - /// The resolved location of the breakpoint if resolved is true. - SourceLocation resolvedLocation; -}; - -} // namespace debugger -} // namespace hermes -} // namespace facebook - -#endif diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/GCConfig.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/GCConfig.h deleted file mode 100644 index 9d95c755..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/GCConfig.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_PUBLIC_GCCONFIG_H -#define HERMES_PUBLIC_GCCONFIG_H - -#include "hermes/Public/CtorConfig.h" -#include "hermes/Public/GCTripwireContext.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace hermes { -namespace vm { - -/// A type big enough to accomodate the entire allocated address space. -/// Individual allocations are always 'uint32_t', but on a 64-bit machine we -/// might want to accommodate a larger total heap (or not, in which case we keep -/// it 32-bit). -using gcheapsize_t = uint32_t; - -/// Represents a value before and after an event. -/// NOTE: Not a std::pair because using the names are more readable than first -/// and second. -struct BeforeAndAfter { - uint64_t before; - uint64_t after; -}; - -struct GCAnalyticsEvent { - /// The same value as \p Name from GCConfig. Stored here for simplicity of - /// the API since this is passed in callbacks that might not be able to store - /// the name. For a given Runtime, this will be the same value every time. - std::string runtimeDescription; - - /// The kind of GC this was. For a given Runtime, this will be the same value - /// every time. - std::string gcKind; - - /// The type of collection that ran, typically differentiating a "young" - /// generation GC and an "old" generation GC. When other values say they're - /// "scoped to the collectionType", it means that for a generation GC - /// they're only reporting the numbers for that generation. - std::string collectionType; - - /// The cause of this GC. Can be an arbitrary string describing the cause. - /// Typically "natural" is used to mean that the GC decided it was time, and - /// other causes mean it was forced by some other condition. - std::string cause; - - /// The wall time a collection took from start to end. - std::chrono::milliseconds duration; - - /// The CPU time a collection took from start to end. This time measure will - /// exclude time waiting on disk, mutexes, or time spent not scheduled to run. - std::chrono::milliseconds cpuDuration; - - /// The number of bytes allocated in the heap before and after the collection. - /// measurement does not include fragmentation, and is the same as the sum of - /// all sizes in calls to \p GC::makeA into that generation (including any - /// rounding up the GC does). - /// The value is scoped to the \p collectionType. - BeforeAndAfter allocated; - - /// The number of bytes in use by the heap before and after the collection. - /// This measurement can include fragmentation if the \p gcKind has that - /// concept. - /// The value is scoped to the \p collectionType. - BeforeAndAfter size; - - /// The number of bytes external to the JS heap before and after the - /// collection. - /// The value is scoped to the \p collectionType. - BeforeAndAfter external; - - /// The ratio of cells that survived the collection to all cells before - /// the collection. Note that this is in term of sizes of cells, not the - /// numbers of cells. Excludes any cells not in direct use by the JS program, - /// such as FillerCell or FreelistCell. - /// The value is scoped to the \p collectionType. - double survivalRatio; - - /// A list of metadata tags to annotate this event with. - std::vector tags; -}; - -/// Parameters to control a tripwire function called when the live set size -/// surpasses a given threshold after collections. Check documentation in -/// README.md -#define GC_TRIPWIRE_FIELDS(F) \ - /* If the heap size is above this threshold after a collection, the tripwire \ - * is triggered. */ \ - F(constexpr, gcheapsize_t, Limit, std::numeric_limits::max()) \ - \ - /* The callback to call when the tripwire is considered triggered. */ \ - F(HERMES_NON_CONSTEXPR, \ - std::function, \ - Callback, \ - nullptr) \ - /* GC_TRIPWIRE_FIELDS END */ - -_HERMES_CTORCONFIG_STRUCT(GCTripwireConfig, GC_TRIPWIRE_FIELDS, {}) - -#undef HEAP_TRIPWIRE_FIELDS - -#define GC_HANDLESAN_FIELDS(F) \ - /* The probability with which the GC should keep moving the heap */ \ - /* to detect stale GC handles. */ \ - F(constexpr, double, SanitizeRate, 0.0) \ - /* Random seed to use for basis of decisions whether or not to */ \ - /* sanitize. A negative value will mean a seed will be chosen at */ \ - /* random. */ \ - F(constexpr, int64_t, RandomSeed, -1) \ - /* GC_HANDLESAN_FIELDS END */ - -_HERMES_CTORCONFIG_STRUCT(GCSanitizeConfig, GC_HANDLESAN_FIELDS, {}) - -#undef GC_HANDLESAN_FIELDS - -/// How aggressively to return unused memory to the OS. -enum ReleaseUnused { - kReleaseUnusedNone = 0, /// Don't try to release unused memory. - kReleaseUnusedOld, /// Only old gen, on full collections. - kReleaseUnusedYoungOnFull, /// Also young gen, but only on full collections. - kReleaseUnusedYoungAlways /// Also young gen, also on young gen collections. -}; - -enum class GCEventKind { - CollectionStart, - CollectionEnd, -}; - -/// Parameters for GC Initialisation. Check documentation in README.md -/// constexpr indicates that the default value is constexpr. -#define GC_FIELDS(F) \ - /* Initial heap size hint. */ \ - F(constexpr, gcheapsize_t, InitHeapSize, 32 << 20) \ - \ - /* Maximum heap size hint. */ \ - F(constexpr, gcheapsize_t, MaxHeapSize, 3u << 30) \ - \ - /* Sizing heuristic: fraction of heap to be occupied by live data. */ \ - F(constexpr, double, OccupancyTarget, 0.5) \ - \ - /* Number of consecutive full collections considered to be an OOM. */ \ - F(constexpr, \ - unsigned, \ - EffectiveOOMThreshold, \ - std::numeric_limits::max()) \ - \ - /* Sanitizer configuration for the GC. */ \ - F(constexpr, GCSanitizeConfig, SanitizeConfig) \ - \ - /* Whether to Keep track of GC Statistics. */ \ - F(constexpr, bool, ShouldRecordStats, false) \ - \ - /* How aggressively to return unused memory to the OS. */ \ - F(constexpr, ReleaseUnused, ShouldReleaseUnused, kReleaseUnusedOld) \ - \ - /* Name for this heap in logs. */ \ - F(HERMES_NON_CONSTEXPR, std::string, Name, "") \ - \ - /* Configuration for the Heap Tripwire. */ \ - F(HERMES_NON_CONSTEXPR, GCTripwireConfig, TripwireConfig) \ - \ - /* Whether to (initially) allocate from the young gen (true) or the */ \ - /* old gen (false). */ \ - F(constexpr, bool, AllocInYoung, true) \ - \ - /* Whether to fill the YG with invalid data after each collection. */ \ - F(constexpr, bool, OverwriteDeadYGObjects, false) \ - \ - /* Whether to revert, if necessary, to young-gen allocation at TTI. */ \ - F(constexpr, bool, RevertToYGAtTTI, false) \ - \ - /* Whether to use mprotect on GC metadata between GCs. */ \ - F(constexpr, bool, ProtectMetadata, false) \ - \ - /* Callout for an analytics event. */ \ - F(HERMES_NON_CONSTEXPR, \ - std::function, \ - AnalyticsCallback, \ - nullptr) \ - \ - /* Called at GC events (see GCEventKind enum for the list). The */ \ - /* second argument contains human-readable details about the event. */ \ - /* NOTE: The function MUST NOT invoke any methods on the Runtime. */ \ - F(HERMES_NON_CONSTEXPR, \ - std::function, \ - Callback, \ - nullptr) \ - /* GC_FIELDS END */ - -_HERMES_CTORCONFIG_STRUCT(GCConfig, GC_FIELDS, { - // Make sure the max is at least the Init. - MaxHeapSize_ = std::max(InitHeapSize_, MaxHeapSize_); -}) - -#undef GC_FIELDS - -} // namespace vm -} // namespace hermes - -#endif // HERMES_PUBLIC_GCCONFIG_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/GCTripwireContext.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/GCTripwireContext.h deleted file mode 100644 index 4a8f500f..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/GCTripwireContext.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_PUBLIC_GCTRIPWIRECONTEXT_H -#define HERMES_PUBLIC_GCTRIPWIRECONTEXT_H - -#include - -#include -#include -#include - -namespace hermes { -namespace vm { - -/// Interface passed to the GC tripwire callback when it fires. -class HERMES_EXPORT GCTripwireContext { - public: - virtual ~GCTripwireContext(); - - /// Captures the heap to a file. - /// \param path to save the heap capture. - /// \return Empty error code if the heap capture succeeded, else a real error - /// code. - virtual std::error_code createSnapshotToFile(const std::string &path) = 0; - - /// Captures the heap to a stream. - /// \param os stream to save the heap capture to. - /// \return Empty error code if the heap capture succeeded, else a real error - /// code. - virtual std::error_code createSnapshot( - std::ostream &os, - bool captureNumericValue) = 0; -}; - -} // namespace vm -} // namespace hermes - -#endif // HERMES_PUBLIC_GCTRIPWIRECONTEXT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/HermesExport.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/HermesExport.h deleted file mode 100644 index f9832cb5..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/HermesExport.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_EXPORT -#ifdef _MSC_VER -#define HERMES_EXPORT __declspec(dllexport) -#else // _MSC_VER -#define HERMES_EXPORT __attribute__((visibility("default"))) -#endif // _MSC_VER -#endif // !defined(HERMES_EXPORT) diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/JSOutOfMemoryError.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/JSOutOfMemoryError.h deleted file mode 100644 index 95093ab7..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/JSOutOfMemoryError.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_PUBLIC_JSOUTOFMEMORYERROR_H -#define HERMES_PUBLIC_JSOUTOFMEMORYERROR_H - -#include - -#include -#include - -namespace hermes { -namespace vm { - -/// A std::runtime_error class for out-of-memory. -class HERMES_EXPORT JSOutOfMemoryError : public std::runtime_error { - friend class GCBase; - JSOutOfMemoryError(const std::string &what_arg) - : std::runtime_error(what_arg) {} - ~JSOutOfMemoryError() override; -}; - -} // namespace vm -} // namespace hermes - -#endif // HERMES_PUBLIC_JSOUTOFMEMORYERROR_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/RuntimeConfig.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/RuntimeConfig.h deleted file mode 100644 index dc253b47..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/Public/RuntimeConfig.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_PUBLIC_RUNTIMECONFIG_H -#define HERMES_PUBLIC_RUNTIMECONFIG_H - -#include "hermes/Public/CrashManager.h" -#include "hermes/Public/CtorConfig.h" -#include "hermes/Public/GCConfig.h" - -#include -#include - -namespace hermes { -namespace vm { - -enum CompilationMode { - SmartCompilation, - ForceEagerCompilation, - ForceLazyCompilation -}; - -enum class SynthTraceMode : int8_t { - None, - Replaying, - Tracing, - TracingAndReplaying, -}; - -class PinnedHermesValue; - -// Parameters for Runtime initialisation. Check documentation in README.md -// constexpr indicates that the default value is constexpr. -#define RUNTIME_FIELDS(F) \ - /* Parameters to be passed on to the GC. */ \ - F(HERMES_NON_CONSTEXPR, vm::GCConfig, GCConfig) \ - \ - /* Pre-allocated Register Stack */ \ - F(constexpr, PinnedHermesValue *, RegisterStack, nullptr) \ - \ - /* Register Stack Size */ \ - F(constexpr, unsigned, MaxNumRegisters, 128 * 1024) \ - \ - /* Native stack remaining before assuming overflow */ \ - F(constexpr, unsigned, NativeStackGap, 64 * 1024) \ - \ - /* Whether or not the JIT is enabled */ \ - F(constexpr, bool, EnableJIT, false) \ - \ - /* Whether to allow eval and Function ctor */ \ - F(constexpr, bool, EnableEval, true) \ - \ - /* Whether to verify the IR generated by eval and Function ctor */ \ - F(constexpr, bool, VerifyEvalIR, false) \ - \ - /* Whether to optimize the code inside eval and Function ctor */ \ - F(constexpr, bool, OptimizedEval, false) \ - \ - /* Whether to emit async break check instructions in eval code */ \ - F(constexpr, bool, AsyncBreakCheckInEval, true) \ - \ - /* Support for ES6 Proxy. */ \ - F(constexpr, bool, ES6Proxy, true) \ - \ - /* Support for ES6 block scoping. */ \ - F(constexpr, bool, ES6BlockScoping, false) \ - \ - /* Support for async generators in eval. */ \ - F(constexpr, bool, EnableAsyncGenerators, false) \ - \ - /* Support for ECMA-402 Intl APIs. */ \ - F(constexpr, bool, Intl, true) \ - \ - /* Support for using microtasks. */ \ - F(constexpr, bool, MicrotaskQueue, false) \ - \ - /* Runtime set up for synth trace. */ \ - F(constexpr, SynthTraceMode, SynthTraceMode, SynthTraceMode::None) \ - \ - /* Enable sampling certain statistics. */ \ - F(constexpr, bool, EnableSampledStats, false) \ - \ - /* Whether to enable automatic sampling profiler registration */ \ - F(constexpr, bool, EnableSampleProfiling, false) \ - \ - /* Whether to randomize stack placement etc. */ \ - F(constexpr, bool, RandomizeMemoryLayout, false) \ - \ - /* Eagerly read bytecode into page cache. */ \ - F(constexpr, unsigned, BytecodeWarmupPercent, 0) \ - \ - /* Signal-based I/O tracking. Slows down execution. If enabled, */ \ - /* all bytecode buffers > 64 kB passed to Hermes must be mmap:ed. */ \ - F(constexpr, bool, TrackIO, false) \ - \ - /* Enable contents of HermesInternal */ \ - F(constexpr, bool, EnableHermesInternal, true) \ - \ - /* Enable methods exposed to JS for testing */ \ - F(constexpr, bool, EnableHermesInternalTestMethods, false) \ - \ - /* Choose lazy/eager compilation mode. */ \ - F(constexpr, \ - CompilationMode, \ - CompilationMode, \ - CompilationMode::SmartCompilation) \ - \ - /* Choose whether generators are enabled. */ \ - F(constexpr, bool, EnableGenerator, true) \ - \ - /* An interface for managing crashes. */ \ - F(HERMES_NON_CONSTEXPR, \ - std::shared_ptr, \ - CrashMgr, \ - new NopCrashManager) \ - \ - /* The flags passed from a VM experiment */ \ - F(constexpr, uint32_t, VMExperimentFlags, 0) \ - /* RUNTIME_FIELDS END */ - -_HERMES_CTORCONFIG_STRUCT(RuntimeConfig, RUNTIME_FIELDS, {}) - -#undef RUNTIME_FIELDS - -} // namespace vm -} // namespace hermes - -#endif // HERMES_PUBLIC_RUNTIMECONFIG_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/RuntimeTaskRunner.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/RuntimeTaskRunner.h deleted file mode 100644 index 367b267a..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/RuntimeTaskRunner.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_RUNTIMETASKRUNNER_H -#define HERMES_RUNTIMETASKRUNNER_H - -#include "AsyncDebuggerAPI.h" - -namespace facebook { -namespace hermes { -namespace debugger { - -using RuntimeTask = std::function; -using EnqueueRuntimeTaskFunc = std::function; - -enum class TaskQueues { - All, - Integrator, -}; - -/// Helper for users of AsyncDebuggerAPI that makes it easy to find the -/// earliest opportunity to use the runtime. There are two ways to become -/// the exclusive user of the runtime: -/// - Ask the AsyncDebuggerAPI to interrupt execution and provide a reference -/// to the runtime. Interrupting will only succeed when JavaScript is -/// running, so this method won't produce a prompt response if JavaScript is -/// not running. -/// - Ask the owner of the runtime to provide a reference to the runtime. If -/// the owner is currently running JavaScript (e.g. via a call to -/// evaluateJavaScript), this method won't produce a prompt response. -/// To cover both cases (when JavaScript is running, and when JavaScript isn't -/// running), this helper requests the runtime from both sources, executes the -/// task via the first responder, and sets a flag to indicate to the second -/// responder that nothing more needs to be done. -class RuntimeTaskRunner - : public std::enable_shared_from_this { - public: - RuntimeTaskRunner( - debugger::AsyncDebuggerAPI &debugger, - EnqueueRuntimeTaskFunc enqueueRuntimeTaskFunc); - ~RuntimeTaskRunner(); - - /// Schedule a task to be run with access to the runtime at the earliest - /// opportunity. Before returning, the task is added to the relevant task - /// queues managed by the \p AsyncDebuggerAPI and/or the intergator, with no - /// lingering references to the \p RuntimeTaskRunner. Thus, tasks can be - /// enqueued even if the task runner will be destroyed shortly after. - void enqueueTask(RuntimeTask task, TaskQueues queues = TaskQueues::All); - - private: - /// API where the runtime can be obtained when JavaScript is running. - debugger::AsyncDebuggerAPI &debugger_; - - /// Function provided by the integrator that enqueues a task to be run - /// when JavaScript is not running. - EnqueueRuntimeTaskFunc enqueueRuntimeTask_; -}; - -} // namespace debugger -} // namespace hermes -} // namespace facebook - -#endif // HERMES_RUNTIMETASKRUNNER_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/SynthTrace.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/SynthTrace.h deleted file mode 100644 index 09bd0d2d..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/SynthTrace.h +++ /dev/null @@ -1,1527 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_SYNTHTRACE_H -#define HERMES_SYNTHTRACE_H - -#include "hermes/ADT/StringSetVector.h" -#include "hermes/Public/RuntimeConfig.h" -#include "hermes/Support/JSONEmitter.h" -#include "hermes/Support/SHA1.h" -#include "hermes/VM/GCExecTrace.h" - -#include "jsi/jsi.h" - -#include -#include -#include -#include -#include -#include - -namespace llvh { -// Forward declaration to avoid including llvm headers. -class raw_ostream; -} // namespace llvh - -namespace facebook { -namespace hermes { -namespace tracing { - -/// A SynthTrace is a list of events that occur in a run of a JS file by a -/// runtime that uses JSI. -/// It can be serialized into JSON and written to a llvh::raw_ostream. -class SynthTrace { - public: - using ObjectID = uint64_t; - - /// A tagged union representing different types available in the trace. - /// We use a an API very similar to HermesValue, but: - /// a) also represent the JSI type PropNameID, and - /// b) the "payloads" for some the types (Objects, Strings, BigInts, Symbols - /// and PropNameIDs) are unique ObjectIDs, rather than actual values. - /// (This could probably become a std::variant when we could use C++17.) - class TraceValue { - public: - bool isUndefined() const { - return tag_ == Tag::Undefined; - } - - bool isNull() const { - return tag_ == Tag::Null; - } - - bool isNumber() const { - return tag_ == Tag::Number; - } - - bool isBool() const { - return tag_ == Tag::Bool; - } - - bool isObject() const { - return tag_ == Tag::Object; - } - - bool isBigInt() const { - return tag_ == Tag::BigInt; - } - - bool isString() const { - return tag_ == Tag::String; - } - - bool isPropNameID() const { - return tag_ == Tag::PropNameID; - } - - bool isSymbol() const { - return tag_ == Tag::Symbol; - } - - bool isUID() const { - return isObject() || isBigInt() || isString() || isPropNameID() || - isSymbol(); - } - - static TraceValue encodeUndefinedValue() { - return TraceValue(Tag::Undefined); - } - - static TraceValue encodeNullValue() { - return TraceValue(Tag::Null); - } - - static TraceValue encodeBoolValue(bool value) { - return TraceValue(value); - } - - static TraceValue encodeNumberValue(double value) { - return TraceValue(value); - } - - static TraceValue encodeObjectValue(uint64_t uid) { - return TraceValue(Tag::Object, uid); - } - - static TraceValue encodeBigIntValue(uint64_t uid) { - return TraceValue(Tag::BigInt, uid); - } - - static TraceValue encodeStringValue(uint64_t uid) { - return TraceValue(Tag::String, uid); - } - - static TraceValue encodePropNameIDValue(uint64_t uid) { - return TraceValue(Tag::PropNameID, uid); - } - - static TraceValue encodeSymbolValue(uint64_t uid) { - return TraceValue(Tag::Symbol, uid); - } - - bool operator==(const TraceValue &that) const; - - ObjectID getUID() const { - assert(isUID()); - return val_.uid; - } - - bool getBool() const { - assert(isBool()); - return val_.b; - } - - double getNumber() const { - assert(isNumber()); - return val_.n; - } - - private: - enum class Tag { - Undefined, - Null, - Bool, - Number, - Object, - String, - PropNameID, - Symbol, - BigInt, - }; - - explicit TraceValue(Tag tag) : tag_(tag) {} - TraceValue(bool b) : tag_(Tag::Bool) { - val_.b = b; - } - TraceValue(double n) : tag_(Tag::Number) { - val_.n = n; - } - TraceValue(Tag tag, uint64_t uid) : tag_(tag) { - val_.uid = uid; - } - - Tag tag_; - union { - bool b; - double n; - ObjectID uid; - } val_; - }; - - /// Represents the encoding type of a String or PropNameId - enum class StringEncodingType { ASCII, UTF8, UTF16 }; - - /// A TimePoint is a time when some event occurred. - using TimePoint = std::chrono::steady_clock::time_point; - using TimeSinceStart = std::chrono::milliseconds; - -#define SYNTH_TRACE_RECORD_TYPES(RECORD) \ - RECORD(BeginExecJS) \ - RECORD(EndExecJS) \ - RECORD(Marker) \ - RECORD(CreateObject) \ - RECORD(CreateObjectWithPrototype) \ - RECORD(CreateString) \ - RECORD(CreatePropNameID) \ - RECORD(CreatePropNameIDWithValue) \ - RECORD(CreateHostObject) \ - RECORD(CreateHostFunction) \ - RECORD(QueueMicrotask) \ - RECORD(DrainMicrotasks) \ - RECORD(GetProperty) \ - RECORD(SetProperty) \ - RECORD(HasProperty) \ - RECORD(GetPropertyNames) \ - RECORD(CreateArray) \ - RECORD(ArrayRead) \ - RECORD(ArrayWrite) \ - RECORD(CallFromNative) \ - RECORD(ConstructFromNative) \ - RECORD(ReturnFromNative) \ - RECORD(ReturnToNative) \ - RECORD(CallToNative) \ - RECORD(GetPropertyNative) \ - RECORD(GetPropertyNativeReturn) \ - RECORD(SetPropertyNative) \ - RECORD(SetPropertyNativeReturn) \ - RECORD(GetNativePropertyNames) \ - RECORD(GetNativePropertyNamesReturn) \ - RECORD(CreateBigInt) \ - RECORD(BigIntToString) \ - RECORD(SetExternalMemoryPressure) \ - RECORD(Utf8) \ - RECORD(Utf16) \ - RECORD(GetStringData) \ - RECORD(GetPrototype) \ - RECORD(SetPrototype) \ - RECORD(DeleteProperty) \ - RECORD(Global) - - /// RecordType is a tag used to differentiate which type of record it is. - /// There should be a unique tag for each record type. - enum class RecordType { -#define RECORD(name) name, - SYNTH_TRACE_RECORD_TYPES(RECORD) -#undef RECORD - }; - - /// A Record is one element of a trace. - struct Record { - /// The time at which this event occurred with respect to the start of - /// execution. - /// NOTE: This is not compared in the \c operator= in order for tests to - /// pass. - const TimeSinceStart time_; - explicit Record() = delete; - explicit Record(TimeSinceStart time) : time_(time) {} - virtual ~Record() = default; - - /// Write out a serialization of this Record. - /// \param json An emitter connected to an ostream which will write out - /// JSON. - void toJSON(::hermes::JSONEmitter &json) const; - virtual RecordType getType() const = 0; - - // If \p val is an object (that is, an Object or String), push its - // decoding onto objs. - static void pushIfTrackedValue( - const TraceValue &val, - std::vector &objs) { - if (val.isUID()) { - objs.push_back(val.getUID()); - } - } - - /// \return A list of object ids that are defined by this record. - /// Defined means that the record would produce that object, - /// string, or PropNameID as a locally accessible value if it were - /// executed. - virtual std::vector defs() const { - return {}; - } - - /// \return A list of object ids that are used by this record. - /// Used means that the record would use that object, string, or - /// PropNameID as a value if it were executed. - /// If a record uses an object id, then some preceding record - /// (either in the same function invocation, or somewhere - /// globally) must provide a definition. - virtual std::vector uses() const { - return {}; - } - - protected: - /// Emit JSON fields into \p os, excluding the closing curly brace. - /// NOTE: This is overridable, and non-abstract children should call the - /// parent. - virtual void toJSONInternal(::hermes::JSONEmitter &json) const; - }; - - /// If \p traceStream is non-null, the trace will be written to that - /// stream. Otherwise, no trace is written. - explicit SynthTrace( - const ::hermes::vm::RuntimeConfig &conf, - std::unique_ptr traceStream = nullptr, - std::optional = {}); - - template - void emplace_back(Args &&...args) { - records_.emplace_back(new T(std::forward(args)...)); - flushRecordsIfNecessary(); - } - - const std::vector> &records() const { - return records_; - } - - std::optional globalObjID() const { - return globalObjID_; - } - - /// Given a trace value, turn it into its typed string. - static std::string encode(TraceValue value); - /// Encode an undefined JS value for the trace. - static TraceValue encodeUndefined(); - /// Encode a null JS value for the trace. - static TraceValue encodeNull(); - /// Encode a boolean JS value for the trace. - static TraceValue encodeBool(bool value); - /// Encodes a numeric value for the trace. - static TraceValue encodeNumber(double value); - /// Encodes an object for the trace as a unique id. - static TraceValue encodeObject(ObjectID objID); - /// Encodes a bigint for the trace as a unique id. - static TraceValue encodeBigInt(ObjectID objID); - /// Encodes a string for the trace as a unique id. - static TraceValue encodeString(ObjectID objID); - /// Encodes a PropNameID for the trace as a unique id. - static TraceValue encodePropNameID(ObjectID objID); - /// Encodes a Symbol for the trace as a unique id. - static TraceValue encodeSymbol(ObjectID objID); - - /// Decodes a string into a trace value. - static TraceValue decode(const std::string &); - -#ifdef HERMESVM_API_TRACE_DEBUG - /// Given a Value, return a descriptive string. This should only be used to - /// provide more debugging info when creating records. - static std::string getDescriptiveString( - jsi::Runtime &runtime, - const jsi::Value &value); -#endif - - /// The version of the Synth Benchmark - constexpr static uint32_t synthVersion() { - return 5; - } - - static const char *nameFromReleaseUnused(::hermes::vm::ReleaseUnused ru); - static ::hermes::vm::ReleaseUnused releaseUnusedFromName(const char *name); - - private: - llvh::raw_ostream &os() const { - return (*traceStream_); - } - - /// If we're tracing to a file, and the number of accumulated - /// records has reached the limit kTraceRecordsToFlush, below, - /// flush the records to the file, and reset the accumulated records - /// to be empty. - void flushRecordsIfNecessary(); - - /// Assumes we're tracing to a file; flush accumulated records to - /// the file, and reset the accumulated records to be empty. - void flushRecords(); - - static constexpr unsigned kTraceRecordsToFlush = 100; - - /// If we're tracing to a file, pointer to a stream onto - /// traceFilename_. Null otherwise. - std::unique_ptr traceStream_; - /// If we're tracing to a file, pointer to a JSONEmitter writting - /// into *traceStream_. Null otherwise. - std::unique_ptr<::hermes::JSONEmitter> json_; - /// The records currently being accumulated in the trace. If we are - /// tracing to a file, these will be only the records not yet - /// written to the file. - std::vector> records_; - /// The id of the global object. - /// Note: Keeping this as optional to support replaying the older trace - /// records before the change of TracingRuntime's PointerValue based ObjectID. - /// We can remove this once we remove old traces. - /// TODO: T189113203 - const std::optional globalObjID_; - - public: - /// @name Record classes - /// @{ - - /// A MarkerRecord is an event that simply records an interesting event that - /// is not necessarily meaningful to the interpreter. It comes with a tag that - /// says what type of marker it was. - struct MarkerRecord : public Record { - static constexpr RecordType type{RecordType::Marker}; - const std::string tag_; - explicit MarkerRecord(TimeSinceStart time, const std::string &tag) - : Record(time), tag_(tag) {} - RecordType getType() const override { - return type; - } - - protected: - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - /// A BeginExecJSRecord is an event where execution begins of JS source - /// code. This is not necessarily the first record, since native code can - /// inject values into the VM before any source code is run. - struct BeginExecJSRecord final : public Record { - static constexpr RecordType type{RecordType::BeginExecJS}; - explicit BeginExecJSRecord( - TimeSinceStart time, - std::string sourceURL, - ::hermes::SHA1 sourceHash, - bool sourceIsBytecode) - : Record(time), - sourceURL_(std::move(sourceURL)), - sourceHash_(std::move(sourceHash)), - sourceIsBytecode_(sourceIsBytecode) {} - - RecordType getType() const override { - return type; - } - - const std::string &sourceURL() const { - return sourceURL_; - } - - const ::hermes::SHA1 &sourceHash() const { - return sourceHash_; - } - - private: - void toJSONInternal(::hermes::JSONEmitter &json) const override; - - /// The URL providing the source file mapping for the file being executed. - /// Can be empty. - std::string sourceURL_; - - /// A hash of the source that was executed. The source hash must match up - /// when the file is replayed. - /// The hash is optional, and will be all zeros if not provided. - ::hermes::SHA1 sourceHash_; - - /// Whether the input file was source or bytecode. - bool sourceIsBytecode_; - }; - - struct ReturnMixin { - const TraceValue retVal_; - - explicit ReturnMixin(TraceValue value) : retVal_(value) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const; - }; - - /// A EndExecJSRecord is an event where execution of JS source code stops. - /// This does not mean that the source code will never be entered again, just - /// that it has an entered a phase where it is waiting for native code to call - /// into the JS. This event is not guaranteed to be the last event, for the - /// aforementioned reason. The logged retVal is the result of the evaluation - /// ("undefined" in the majority of cases). - struct EndExecJSRecord final : public MarkerRecord, public ReturnMixin { - static constexpr RecordType type{RecordType::EndExecJS}; - EndExecJSRecord(TimeSinceStart time, TraceValue retVal) - : MarkerRecord(time, "end_global_code"), ReturnMixin(retVal) {} - - RecordType getType() const override { - return type; - } - virtual void toJSONInternal(::hermes::JSONEmitter &json) const final; - std::vector defs() const override { - auto defs = MarkerRecord::defs(); - pushIfTrackedValue(retVal_, defs); - return defs; - } - }; - - /// A CreateObjectRecord is an event where an empty object is created by the - /// native code. - struct CreateObjectRecord : public Record { - static constexpr RecordType type{RecordType::CreateObject}; - /// The ObjectID of the object that was created by native function calls - /// like Runtime::createObject(). - const ObjectID objID_; - - explicit CreateObjectRecord(TimeSinceStart time, ObjectID objID) - : Record(time), objID_(objID) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - RecordType getType() const override { - return type; - } - - std::vector defs() const override { - return {objID_}; - } - - std::vector uses() const override { - return {}; - } - }; - - /// A CreateBigIntRecord is an event where a jsi::BigInt (and thus a - /// Hermes BigIntPrimitive) is created by the native code. - struct CreateBigIntRecord : public Record { - static constexpr RecordType type{RecordType::CreateBigInt}; - /// The ObjectID of the BigInt that was created by - /// Runtime::createBigIntFromInt64() or Runtime::createBigIntFromUint64(). - const ObjectID objID_; - enum class Method { - FromInt64, - FromUint64, - }; - /// The method used for creating the BigInt. - Method method_; - /// The value used for creating the BigInt. - uint64_t bits_; - - CreateBigIntRecord( - TimeSinceStart time, - ObjectID objID, - Method m, - uint64_t bits) - : Record(time), objID_(objID), method_(m), bits_(bits) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - - RecordType getType() const override { - return type; - } - - std::vector defs() const override { - return {objID_}; - } - - std::vector uses() const override { - return {}; - } - }; - - /// A BigIntToStringRecord is an event where a jsi::BigInt is converted to a - /// string by native code - struct BigIntToStringRecord : public Record { - static constexpr RecordType type{RecordType::BigIntToString}; - /// The ObjectID of the string that was returned from - /// Runtime::bigintToString(). - const ObjectID strID_; - /// The ObjectID of the BigInt that was passed to Runtime::bigintToString(). - const ObjectID bigintID_; - /// The radix used for converting the BigInt to a string. - int radix_; - - BigIntToStringRecord( - TimeSinceStart time, - ObjectID strID, - ObjectID bigintID, - int radix) - : Record(time), strID_(strID), bigintID_(bigintID), radix_(radix) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - - RecordType getType() const override { - return type; - } - - std::vector defs() const override { - return {strID_}; - } - - std::vector uses() const override { - return {bigintID_}; - } - }; - - /// A CreateStringRecord is an event where a jsi::String (and thus a - /// Hermes StringPrimitive) is created by the native code. - struct CreateStringRecord : public Record { - static constexpr RecordType type{RecordType::CreateString}; - /// The ObjectID of the string that was created by - /// Runtime::createStringFromAscii() or Runtime::createStringFromUtf8(). - const ObjectID objID_; - /// The string that was passed to Runtime::createStringFromAscii() or - /// Runtime::createStringFromUtf8() when the string was created. - std::string chars_; - /// The string that was passed to Runtime::createStringFromUtf16() - std::u16string chars16_; - /// Whether the String was created from ASCII, UTF-8 or UTF-16 - StringEncodingType encodingType_; - - // General UTF-8. - CreateStringRecord( - TimeSinceStart time, - ObjectID objID, - const uint8_t *chars, - size_t length) - : Record(time), - objID_(objID), - chars_(reinterpret_cast(chars), length), - encodingType_(StringEncodingType::UTF8) {} - // Ascii. - CreateStringRecord( - TimeSinceStart time, - ObjectID objID, - const char *chars, - size_t length) - : Record(time), - objID_(objID), - chars_(chars, length), - encodingType_(StringEncodingType::ASCII) {} - // UTF-16. - CreateStringRecord( - TimeSinceStart time, - ObjectID objID, - const char16_t *chars, - size_t length) - : Record(time), - objID_(objID), - chars16_(chars, length), - encodingType_(StringEncodingType::UTF16) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - RecordType getType() const override { - return type; - } - - std::vector defs() const override { - return {objID_}; - } - - std::vector uses() const override { - return {}; - } - }; - - /// A CreatePropNameIDRecord is an event where a jsi::PropNameID is - /// created by the native code. - struct CreatePropNameIDRecord : public Record { - static constexpr RecordType type{RecordType::CreatePropNameID}; - /// The ObjectID of the PropNameID that was created. - const ObjectID propNameID_; - /// The string that was passed to Runtime::createPropNameIDFromAscii() or - /// Runtime::createPropNameIDFromUtf8(). - std::string chars_; - /// The string that was passed to Runtime::createPropNameIDFromUtf16() - std::u16string chars16_; - /// Whether the PropNameID was created from ASCII, UTF-8, or UTF-16 - StringEncodingType encodingType_; - - // General UTF-8. - CreatePropNameIDRecord( - TimeSinceStart time, - ObjectID propNameID, - const uint8_t *chars, - size_t length) - : Record(time), - propNameID_(propNameID), - chars_(reinterpret_cast(chars), length), - encodingType_(StringEncodingType::UTF8) {} - // Ascii. - CreatePropNameIDRecord( - TimeSinceStart time, - ObjectID propNameID, - const char *chars, - size_t length) - : Record(time), - propNameID_(propNameID), - chars_(chars, length), - encodingType_(StringEncodingType::ASCII) {} - // UTF16 - CreatePropNameIDRecord( - TimeSinceStart time, - ObjectID propNameID, - const char16_t *chars, - size_t length) - : Record(time), - propNameID_(propNameID), - chars16_(chars, length), - encodingType_(StringEncodingType::UTF16) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - RecordType getType() const override { - return type; - } - - std::vector defs() const override { - return {propNameID_}; - } - - std::vector uses() const override { - return {}; - } - }; - - /// A CreatePropNameIDWithValueRecord is an event where a jsi::PropNameID is - /// created by the native code from JSI Value - struct CreatePropNameIDWithValueRecord : public Record { - static constexpr RecordType type{RecordType::CreatePropNameIDWithValue}; - /// The ObjectID of the PropNameID that was created. - const ObjectID propNameID_; - /// The String or Symbol that was passed to - /// Runtime::createPropNameIDFromString() or - /// Runtime::createPropNameIDFromSymbol(). - const TraceValue traceValue_; - - // jsi::String or jsi::Symbol. - CreatePropNameIDWithValueRecord( - TimeSinceStart time, - ObjectID propNameID, - TraceValue traceValue) - : Record(time), propNameID_(propNameID), traceValue_(traceValue) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - RecordType getType() const override { - return type; - } - - std::vector defs() const override { - return {propNameID_}; - } - - std::vector uses() const override { - std::vector vec; - pushIfTrackedValue(traceValue_, vec); - return vec; - } - }; - - struct CreateObjectWithPrototypeRecord : public Record { - static constexpr RecordType type{RecordType::CreateObjectWithPrototype}; - const ObjectID objID_; - /// The prototype being assigned - const TraceValue prototype_; - - CreateObjectWithPrototypeRecord( - TimeSinceStart time, - ObjectID objID, - TraceValue prototype) - : Record(time), objID_(objID), prototype_(prototype) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - - RecordType getType() const override { - return type; - } - - std::vector uses() const override { - std::vector uses{objID_}; - pushIfTrackedValue(prototype_, uses); - return uses; - } - }; - - struct CreateHostObjectRecord final : public CreateObjectRecord { - static constexpr RecordType type{RecordType::CreateHostObject}; - using CreateObjectRecord::CreateObjectRecord; - RecordType getType() const override { - return type; - } - }; - - struct CreateHostFunctionRecord final : public CreateObjectRecord { - static constexpr RecordType type{RecordType::CreateHostFunction}; - /// The ObjectID of the PropNameID that was passed to - /// Runtime::createFromHostFunction(). - uint32_t propNameID_; -#ifdef HERMESVM_API_TRACE_DEBUG - const std::string functionName_; -#endif - /// The number of parameters that the created host function takes. - const unsigned paramCount_; - - CreateHostFunctionRecord( - TimeSinceStart time, - ObjectID objID, - ObjectID propNameID, -#ifdef HERMESVM_API_TRACE_DEBUG - std::string functionName, -#endif - unsigned paramCount) - : CreateObjectRecord(time, objID), - propNameID_(propNameID), -#ifdef HERMESVM_API_TRACE_DEBUG - functionName_(std::move(functionName)), -#endif - paramCount_(paramCount) { - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - - RecordType getType() const override { - return type; - } - - std::vector uses() const override { - return {propNameID_}; - } - }; - - struct QueueMicrotaskRecord : public Record { - static constexpr RecordType type{RecordType::QueueMicrotask}; - /// The ObjectID of the callback function that was queued. - const ObjectID callbackID_; - - QueueMicrotaskRecord(TimeSinceStart time, ObjectID callbackID) - : Record(time), callbackID_(callbackID) {} - - RecordType getType() const override { - return type; - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - - std::vector uses() const override { - return {callbackID_}; - } - }; - - struct DrainMicrotasksRecord : public Record { - static constexpr RecordType type{RecordType::DrainMicrotasks}; - /// maxMicrotasksHint value passed to Runtime::drainMicrotasks() call. - int maxMicrotasksHint_; - - DrainMicrotasksRecord(TimeSinceStart time, int tasksHint = -1) - : Record(time), maxMicrotasksHint_(tasksHint) {} - - RecordType getType() const override { - return type; - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - /// A GetPropertyRecord is an event where native code accesses the property - /// of a JS object. - struct GetPropertyRecord : public Record { - /// The ObjectID of the object that was accessed for its property. - const ObjectID objID_; - /// String or PropNameID or Value passed to getProperty. - const TraceValue propID_; -#ifdef HERMESVM_API_TRACE_DEBUG - std::string propNameDbg_; -#endif - - GetPropertyRecord( - TimeSinceStart time, - ObjectID objID, - TraceValue propID -#ifdef HERMESVM_API_TRACE_DEBUG - , - const std::string &propNameDbg -#endif - ) - : Record(time), - objID_(objID), - propID_(propID) -#ifdef HERMESVM_API_TRACE_DEBUG - , - propNameDbg_(propNameDbg) -#endif - { - } - - static constexpr RecordType type{RecordType::GetProperty}; - RecordType getType() const override { - return type; - } - - std::vector uses() const override { - std::vector uses{objID_}; - pushIfTrackedValue(propID_, uses); - return uses; - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - /// A SetPropertyRecord is an event where native code writes to the property - /// of a JS object. - struct SetPropertyRecord : public Record { - /// The ObjectID of the object that was accessed for its property. - const ObjectID objID_; - /// String or PropNameID or Value passed to setProperty. - const TraceValue propID_; -#ifdef HERMESVM_API_TRACE_DEBUG - std::string propNameDbg_; -#endif - /// The value being assigned. - const TraceValue value_; - - SetPropertyRecord( - TimeSinceStart time, - ObjectID objID, - TraceValue propID, -#ifdef HERMESVM_API_TRACE_DEBUG - const std::string &propNameDbg, -#endif - TraceValue value) - : Record(time), - objID_(objID), - propID_(propID), -#ifdef HERMESVM_API_TRACE_DEBUG - propNameDbg_(propNameDbg), -#endif - value_(value) { - } - - static constexpr RecordType type{RecordType::SetProperty}; - RecordType getType() const override { - return type; - } - - std::vector uses() const override { - std::vector uses{objID_}; - pushIfTrackedValue(propID_, uses); - pushIfTrackedValue(value_, uses); - return uses; - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - /// A HasPropertyRecord is an event where native code queries whether a - /// property exists on an object. (We don't care about the result because - /// it cannot influence the trace.) - struct HasPropertyRecord final : public Record { - static constexpr RecordType type{RecordType::HasProperty}; - /// The ObjectID of the object that was accessed for its property. - const ObjectID objID_; -#ifdef HERMESVM_API_TRACE_DEBUG - std::string propNameDbg_; -#endif - /// The property name that was passed to hasProperty(). - const TraceValue propID_; - - HasPropertyRecord( - TimeSinceStart time, - ObjectID objID, - TraceValue propID -#ifdef HERMESVM_API_TRACE_DEBUG - , - const std::string &propNameDbg -#endif - ) - : Record(time), - objID_(objID), -#ifdef HERMESVM_API_TRACE_DEBUG - propNameDbg_(propNameDbg), -#endif - propID_(propID) { - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - RecordType getType() const override { - return type; - } - std::vector uses() const override { - std::vector vec{objID_}; - pushIfTrackedValue(propID_, vec); - return vec; - } - }; - - struct GetPropertyNamesRecord final : public Record { - static constexpr RecordType type{RecordType::GetPropertyNames}; - /// The ObjectID of the object that was accessed for its property. - const ObjectID objID_; - - explicit GetPropertyNamesRecord(TimeSinceStart time, ObjectID objID) - : Record(time), objID_(objID) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - RecordType getType() const override { - return type; - } - std::vector uses() const override { - return {objID_}; - } - }; - - /// A SetPrototypeRecord is an event where native code sets the prototype of a - /// JS Object - struct SetPrototypeRecord : public Record { - static constexpr RecordType type{RecordType::SetPrototype}; - /// The ObjectID of the object that was accessed for its prototype. - const ObjectID objID_; - /// The custom prototype being assigned - const TraceValue value_; - SetPrototypeRecord(TimeSinceStart time, ObjectID objID, TraceValue value) - : Record(time), objID_(objID), value_(value) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - - RecordType getType() const override { - return type; - } - std::vector uses() const override { - std::vector uses{objID_}; - pushIfTrackedValue(value_, uses); - return uses; - } - }; - - struct DeletePropertyRecord final : public Record { - static constexpr RecordType type{RecordType::DeleteProperty}; - /// The object ID of the object that was accessed for its property - const ObjectID objID_; - /// The name of the property being deleted - const TraceValue propID_; - - DeletePropertyRecord(TimeSinceStart time, ObjectID objID, TraceValue propID) - : Record(time), objID_(objID), propID_(propID) {} - - RecordType getType() const override { - return type; - } - - std::vector uses() const override { - std::vector uses{objID_}; - pushIfTrackedValue(propID_, uses); - return uses; - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - /// A GetPrototypeRecord is an event where native code gets the prototype of a - /// JS Object - struct GetPrototypeRecord : public Record { - static constexpr RecordType type{RecordType::GetPrototype}; - /// The ObjectID of the object that was accessed for its prototype. - const ObjectID objID_; - GetPrototypeRecord(TimeSinceStart time, ObjectID objID) - : Record(time), objID_(objID) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - - RecordType getType() const override { - return type; - } - std::vector uses() const override { - return {objID_}; - } - }; - - /// A CreateArrayRecord is an event where a new array is created of a specific - /// length. - struct CreateArrayRecord final : public Record { - static constexpr RecordType type{RecordType::CreateArray}; - /// The ObjectID of the array that was created by the createArray(). - const ObjectID objID_; - /// The length of the array that was passed to createArray(). - const size_t length_; - - explicit CreateArrayRecord( - TimeSinceStart time, - ObjectID objID, - size_t length) - : Record(time), objID_(objID), length_(length) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - RecordType getType() const override { - return type; - } - std::vector defs() const override { - return {objID_}; - } - }; - - /// An ArrayReadRecord is an event where a value was read from an index - /// of an array. - /// It is modeled separately from GetProperty because it is more efficient to - /// read from a numeric index on an array than a string. - struct ArrayReadRecord final : public Record { - /// The ObjectID of the array that was accessed. - const ObjectID objID_; - /// The index of the element that was accessed in the array. - const size_t index_; - - explicit ArrayReadRecord(TimeSinceStart time, ObjectID objID, size_t index) - : Record(time), objID_(objID), index_(index) {} - - static constexpr RecordType type{RecordType::ArrayRead}; - RecordType getType() const override { - return type; - } - std::vector uses() const override { - return {objID_}; - } - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - /// An ArrayWriteRecord is an event where a value was written into an index - /// of an array. - struct ArrayWriteRecord final : public Record { - /// The ObjectID of the array that was accessed. - const ObjectID objID_; - /// The index of the element that was accessed in the array. - const size_t index_; - /// The value that was written to the array. - const TraceValue value_; - - explicit ArrayWriteRecord( - TimeSinceStart time, - ObjectID objID, - size_t index, - TraceValue value) - : Record(time), objID_(objID), index_(index), value_(value) {} - - static constexpr RecordType type{RecordType::ArrayWrite}; - RecordType getType() const override { - return type; - } - std::vector uses() const override { - std::vector uses{objID_}; - pushIfTrackedValue(value_, uses); - return uses; - } - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - struct CallRecord : public Record { - /// The ObjectID of the function JS object that was called from - /// JS or native. - const ObjectID functionID_; - /// The value of the this argument passed to the function call. - const TraceValue thisArg_; - /// The arguments given to a call (excluding the this parameter), - /// already JSON stringified. - const std::vector args_; - - explicit CallRecord( - TimeSinceStart time, - ObjectID functionID, - TraceValue thisArg, - const std::vector &args) - : Record(time), - functionID_(functionID), - thisArg_(thisArg), - args_(args) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - std::vector uses() const override { - // The function is used regardless of direction. - return {functionID_}; - } - - protected: - std::vector getArgTrackedIDs() const { - std::vector objs; - pushIfTrackedValue(thisArg_, objs); - for (const auto &arg : args_) { - pushIfTrackedValue(arg, objs); - } - return objs; - } - }; - - /// A CallFromNativeRecord is an event where native code calls into a JS - /// function. - struct CallFromNativeRecord : public CallRecord { - static constexpr RecordType type{RecordType::CallFromNative}; - using CallRecord::CallRecord; - RecordType getType() const override { - return type; - } - std::vector uses() const override { - auto uses = CallRecord::uses(); - auto objs = CallRecord::getArgTrackedIDs(); - uses.insert(uses.end(), objs.begin(), objs.end()); - return uses; - } - }; - - /// A ConstructFromNativeRecord is the same as \c CallFromNativeRecord, except - /// the function is called with the new operator. - struct ConstructFromNativeRecord final : public CallFromNativeRecord { - static constexpr RecordType type{RecordType::ConstructFromNative}; - using CallFromNativeRecord::CallFromNativeRecord; - RecordType getType() const override { - return type; - } - }; - - /// A ReturnFromNativeRecord is an event where a native function returns to a - /// JS caller. - /// It pairs with \c CallToNativeRecord. - struct ReturnFromNativeRecord final : public Record, public ReturnMixin { - static constexpr RecordType type{RecordType::ReturnFromNative}; - ReturnFromNativeRecord(TimeSinceStart time, TraceValue retVal) - : Record(time), ReturnMixin(retVal) {} - RecordType getType() const override { - return type; - } - std::vector uses() const override { - auto uses = Record::uses(); - pushIfTrackedValue(retVal_, uses); - return uses; - } - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - /// A ReturnToNativeRecord is an event where a JS function returns to a native - /// caller. - /// It pairs with \c CallFromNativeRecord. - struct ReturnToNativeRecord final : public Record, public ReturnMixin { - static constexpr RecordType type{RecordType::ReturnToNative}; - ReturnToNativeRecord(TimeSinceStart time, TraceValue retVal) - : Record(time), ReturnMixin(retVal) {} - RecordType getType() const override { - return type; - } - std::vector defs() const override { - auto defs = Record::defs(); - pushIfTrackedValue(retVal_, defs); - return defs; - } - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - /// A CallToNativeRecord is an event where JS code calls into a natively - /// defined function. - struct CallToNativeRecord final : public CallRecord { - static constexpr RecordType type{RecordType::CallToNative}; - using CallRecord::CallRecord; - RecordType getType() const override { - return type; - } - std::vector defs() const override { - auto defs = CallRecord::defs(); - auto objs = CallRecord::getArgTrackedIDs(); - defs.insert(defs.end(), objs.begin(), objs.end()); - return defs; - } - }; - - struct GetOrSetPropertyNativeRecord : public Record { - /// The ObjectID of the host object that was being accessed for its - /// property. - const ObjectID hostObjectID_; - /// The ObjectID of the PropNameID that was passed to HostObject::get() - /// or HostObject::set(). - const ObjectID propNameID_; - /// The UTF-8 string of the PropNameID that was passed to HostObject::get() - /// or HostObject::set(). - const std::string propName_; - - GetOrSetPropertyNativeRecord( - TimeSinceStart time, - ObjectID hostObjectID, - ObjectID propNameID, - const std::string &propName) - : Record(time), - hostObjectID_(hostObjectID), - propNameID_(propNameID), - propName_(propName) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - std::vector defs() const override { - return {propNameID_}; - } - std::vector uses() const override { - return {hostObjectID_}; - } - - protected: - }; - - /// A GetPropertyNativeRecord is an event where JS tries to access a property - /// on a native object. - /// This needs to be modeled as a call with no arguments, since native code - /// can arbitrarily affect the JS heap during the accessor. - struct GetPropertyNativeRecord final : public GetOrSetPropertyNativeRecord { - static constexpr RecordType type{RecordType::GetPropertyNative}; - using GetOrSetPropertyNativeRecord::GetOrSetPropertyNativeRecord; - RecordType getType() const override { - return type; - } - }; - - struct GetPropertyNativeReturnRecord final : public Record, - public ReturnMixin { - static constexpr RecordType type{RecordType::GetPropertyNativeReturn}; - GetPropertyNativeReturnRecord(TimeSinceStart time, TraceValue retVal) - : Record(time), ReturnMixin(retVal) {} - RecordType getType() const override { - return type; - } - std::vector uses() const override { - auto uses = Record::uses(); - pushIfTrackedValue(retVal_, uses); - return uses; - } - - protected: - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - /// A SetPropertyNativeRecord is an event where JS code writes to the property - /// of a Native object. - /// This needs to be modeled as a call with one argument, since native code - /// can arbitrarily affect the JS heap during the accessor. - struct SetPropertyNativeRecord final : public GetOrSetPropertyNativeRecord { - static constexpr RecordType type{RecordType::SetPropertyNative}; - /// The value that was passed to HostObject::set() call. - TraceValue value_; - - SetPropertyNativeRecord( - TimeSinceStart time, - ObjectID hostObjectID, - ObjectID propNameID, - const std::string &propName, - TraceValue value) - : GetOrSetPropertyNativeRecord( - time, - hostObjectID, - propNameID, - propName), - value_(value) {} - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - RecordType getType() const override { - return type; - } - std::vector defs() const override { - auto defs = GetOrSetPropertyNativeRecord::defs(); - pushIfTrackedValue(value_, defs); - return defs; - } - }; - - /// A SetPropertyNativeReturnRecord needs to record no extra information - struct SetPropertyNativeReturnRecord final : public Record { - static constexpr RecordType type{RecordType::SetPropertyNativeReturn}; - using Record::Record; - RecordType getType() const override { - return type; - } - }; - - /// A GetNativePropertyNamesRecord records an event where JS asked for a list - /// of property names available on a host object. It records the object, and - /// the returned list of property names. - struct GetNativePropertyNamesRecord : public Record { - static constexpr RecordType type{RecordType::GetNativePropertyNames}; - /// The ObjectID of the host object that was being accessed for - /// HostObjet::getPropertyNames() call. - const ObjectID hostObjectID_; - - explicit GetNativePropertyNamesRecord( - TimeSinceStart time, - ObjectID hostObjectID) - : Record(time), hostObjectID_(hostObjectID) {} - - RecordType getType() const override { - return type; - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - - std::vector uses() const override { - return {hostObjectID_}; - } - }; - - /// A GetNativePropertyNamesReturnRecord records what property names were - /// returned by the GetNativePropertyNames query. - struct GetNativePropertyNamesReturnRecord final : public Record { - static constexpr RecordType type{RecordType::GetNativePropertyNamesReturn}; - - /// Returned list of property names - const std::vector propNameIDs_; - - explicit GetNativePropertyNamesReturnRecord( - TimeSinceStart time, - const std::vector &propNameIDs) - : Record(time), propNameIDs_(propNameIDs) {} - - RecordType getType() const override { - return type; - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - - std::vector uses() const override { - auto uses = Record::uses(); - for (const auto &val : propNameIDs_) { - pushIfTrackedValue(val, uses); - } - return uses; - } - }; - - struct SetExternalMemoryPressureRecord final : public Record { - static constexpr RecordType type{RecordType::SetExternalMemoryPressure}; - /// The ObjectID of the object that was passed to - /// Runtime::setExternalMemoryPressure() call. - const ObjectID objID_; - /// The value passed to Runtime::setExternalMemoryPressure() call. - const size_t amount_; - - explicit SetExternalMemoryPressureRecord( - TimeSinceStart time, - const ObjectID objID, - const size_t amount) - : Record(time), objID_(objID), amount_(amount) {} - - RecordType getType() const override { - return type; - } - - std::vector uses() const override { - return {objID_}; - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - /// An Utf8Record is an event where a PropNameID or String or Symbol was - /// converted to utf8. - struct Utf8Record final : public Record { - static constexpr RecordType type{RecordType::Utf8}; - /// PropNameID, String or Symbol passed to utf8() or symbolToString() as an - /// argument - const TraceValue objID_; - /// Returned string from utf8() or symbolToString() - const std::string retVal_; - - explicit Utf8Record( - TimeSinceStart time, - const TraceValue objID, - std::string retval) - : Record(time), objID_(objID), retVal_(std::move(retval)) {} - - RecordType getType() const override { - return type; - } - - std::vector uses() const override { - std::vector vec; - pushIfTrackedValue(objID_, vec); - return vec; - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - /// A Utf16Record is an event where a PropNameID or String was converted to - /// UTF-16. - struct Utf16Record final : public Record { - static constexpr RecordType type{RecordType::Utf16}; - /// PropNameID, String passed to utf16() as an argument - const TraceValue objID_; - /// Returned string from utf16(). - const std::u16string retVal_; - - explicit Utf16Record( - TimeSinceStart time, - const TraceValue objID, - std::u16string retval) - : Record(time), objID_(objID), retVal_(std::move(retval)) {} - - RecordType getType() const override { - return type; - } - - std::vector uses() const override { - std::vector vec; - pushIfTrackedValue(objID_, vec); - return vec; - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - /// A GetStringData is an event where getStringData or getPropNameIdData was - /// invoked. - struct GetStringDataRecord final : public Record { - static constexpr RecordType type{RecordType::GetStringData}; - /// The String or PropNameID passed into getStringData or getPropNameIdData - const TraceValue objID_; - /// The string content in the String or PropNameID that was passed into the - /// callback - const std::u16string strData_; - - explicit GetStringDataRecord( - TimeSinceStart time, - const TraceValue objID, - std::u16string strData) - : Record(time), objID_(objID), strData_(std::move(strData)) {} - - RecordType getType() const override { - return type; - } - - std::vector uses() const override { - std::vector vec; - pushIfTrackedValue(objID_, vec); - return vec; - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - struct GlobalRecord final : public Record { - static constexpr RecordType type{RecordType::Global}; - const ObjectID objID_; // global's ObjectID returned from Runtime::global(). - - explicit GlobalRecord(TimeSinceStart time, ObjectID objID) - : Record(time), objID_(objID) {} - - RecordType getType() const override { - return type; - } - - std::vector defs() const override { - return {objID_}; - } - - void toJSONInternal(::hermes::JSONEmitter &json) const override; - }; - - /// Completes writing of the trace to the trace stream. If writing - /// to a file, disables further writing to the file, or accumulation - /// of data. - void flushAndDisable(const ::hermes::vm::GCExecTrace &gcTrace); -}; - -} // namespace tracing -} // namespace hermes -} // namespace facebook - -#endif // HERMES_SYNTHTRACE_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/SynthTraceParser.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/SynthTraceParser.h deleted file mode 100644 index 7844ee50..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/SynthTraceParser.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_SYNTHTRACEPARSER_H -#define HERMES_SYNTHTRACEPARSER_H - -#include - -#include "hermes/Public/RuntimeConfig.h" -#include "hermes/SynthTrace.h" - -#include "llvh/Support/MemoryBuffer.h" - -namespace facebook { -namespace hermes { -namespace tracing { - -/// Parse a trace from a JSON string stored in a MemoryBuffer. -std::tuple< - SynthTrace, - ::hermes::vm::RuntimeConfig::Builder, - ::hermes::vm::GCConfig::Builder> -parseSynthTrace(std::unique_ptr trace); - -/// Parse a trace from a JSON string stored in the given file name. -std::tuple< - SynthTrace, - ::hermes::vm::RuntimeConfig::Builder, - ::hermes::vm::GCConfig::Builder> -parseSynthTrace(const std::string &tracefile); - -} // namespace tracing -} // namespace hermes -} // namespace facebook - -#endif // HERMES_SYNTHTRACEPARSER_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/ThreadSafetyAnalysis.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/ThreadSafetyAnalysis.h deleted file mode 100644 index 39e6cf66..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/ThreadSafetyAnalysis.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -// Based on mutex.h from https://clang.llvm.org/docs/ThreadSafetyAnalysis.html - -#ifndef THREAD_SAFETY_ANALYSIS_MUTEX_H -#define THREAD_SAFETY_ANALYSIS_MUTEX_H - -// Enable thread safety attributes only with clang. -// The attributes can be safely erased when compiling with other compilers. -#if defined(__clang__) && (!defined(SWIG)) && defined(_LIBCPP_VERSION) && \ - defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) -#define TSA_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) -#else -#define TSA_THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op -#endif - -#define TSA_CAPABILITY(x) TSA_THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) - -#define TSA_SCOPED_CAPABILITY TSA_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) - -#define TSA_GUARDED_BY(x) TSA_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) - -#define TSA_PT_GUARDED_BY(x) TSA_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) - -#define TSA_ACQUIRED_BEFORE(...) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) - -#define TSA_ACQUIRED_AFTER(...) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) - -#define TSA_REQUIRES(...) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) - -#define TSA_REQUIRES_SHARED(...) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) - -#define TSA_ACQUIRE(...) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) - -#define TSA_ACQUIRE_SHARED(...) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) - -#define TSA_RELEASE(...) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) - -#define TSA_RELEASE_SHARED(...) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) - -#define TSA_RELEASE_GENERIC(...) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__)) - -#define TSA_TRY_ACQUIRE(...) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) - -#define TSA_TRY_ACQUIRE_SHARED(...) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) - -#define TSA_EXCLUDES(...) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) - -#define TSA_ASSERT_CAPABILITY(x) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) - -#define TSA_ASSERT_SHARED_CAPABILITY(x) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) - -#define TSA_RETURN_CAPABILITY(x) \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) - -#define TSA_NO_THREAD_SAFETY_ANALYSIS \ - TSA_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) - -#endif // THREAD_SAFETY_ANALYSIS_MUTEX_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/TraceInterpreter.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/TraceInterpreter.h deleted file mode 100644 index 83c8a383..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/TraceInterpreter.h +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -namespace facebook { -namespace hermes { - -namespace tracing { - -class TraceInterpreter final { - public: - /// Options for executing the trace. - struct ExecuteOptions { - /// Customizes the GCConfig of the Runtime. - ::hermes::vm::GCConfig::Builder gcConfigBuilder; - - /// If true, trace again while replaying. After normalization (see - /// hermes/tools/synth/trace_normalize.py) the output trace should be - /// identical to the input trace. If they're not, there was a bug in replay. - mutable bool traceEnabled{false}; - - /// If true, verify that the replay results such as returned values from JS - /// execution, inputs from JS to native function calls are matching with the - /// trace record. - bool verificationEnabled{false}; - - /// If true, command-line options override the config options recorded in - /// the trace. If false, start from the default config. - bool useTraceConfig{false}; - - /// Enable basic block profiling. - bool basicBlockProfiling{false}; - - // If non-empty, write profiling output to this file, rather than - // to stderr. - std::string profilingOutFile; - - /// Number of initial executions whose stats are discarded. - int warmupReps{0}; - - /// Number of repetitions of execution. Stats returned are those for the rep - /// with the median totalTime. - int reps{1}; - - /// If non-null, holds statistics for every garbage collection that occurs. - const std::vector<::hermes::vm::GCAnalyticsEvent> *gcAnalyticsEvents{ - nullptr}; - - /// If true, run a complete collection before printing stats. Useful for - /// guaranteeing there's no garbage in heap size numbers. - bool forceGCBeforeStats{false}; - - /// If true, use the Hermes VM JIT during execution. - bool enableJIT{false}; - - /// If true, remove the requirement that the input bytecode was compiled - /// from the same source used to record the trace. There must only be one - /// input bytecode file in this case. If its observable behavior deviates - /// from the trace, the results are undefined. - bool disableSourceHashCheck{false}; - - /// A trace contains many MarkerRecords which have a name used to identify - /// them. If the replay encounters this given marker, perform an action - /// described by MarkerAction. All actions will stop the trace early and - /// collect stats at the marker point, unless the marker is set to the - /// special marker "end". In that case the trace will run to completion. - std::string marker{"end"}; - - enum class MarkerAction { - NONE, - /// Take a snapshot at marker. - SNAPSHOT, - /// Take a heap timeline that ends at marker. - TIMELINE, - /// Take a sampling heap profile that ends at marker. - SAMPLE_MEMORY, - /// Take a sampling time profile that ends at marker. - SAMPLE_TIME, - }; - - /// Sets the action to take upon encountering the marker. The action will - /// write results into the \p profileFileName. - MarkerAction action{MarkerAction::NONE}; - - /// Output file name for any profiling information. - std::string profileFileName; - - // These are the config parameters. We wrap them in llvh::Optional - // to indicate whether the corresponding command line flag was set - // explicitly. We override the trace's config only when that is true. - - /// If true, track all disk I/O done by the runtime and print a report at - /// the end to stdout. - llvh::Optional shouldTrackIO; - - /// If present, do a bytecode warmup run that touches a percentage of the - /// bytecode. A value of 50 here means 50% of the bytecode should be warmed. - llvh::Optional bytecodeWarmupPercent; - }; - - private: - jsi::Runtime &rt_; - ExecuteOptions options_; - llvh::raw_ostream *traceStream_; - // Map from source hash to source file to run. - std::map<::hermes::SHA1, std::shared_ptr> bundles_; - const SynthTrace &trace_; - - /// The last use of each object. - std::unordered_map lastUsePerObj_; - - /// The list of pairs from record index to ObjectID. Each record index is the - /// lastly used position of each Object, at which we can remove the object - /// from gom_ and gpnm_. - std::vector> lastUses_; - /// Index of lastUses_ vector that the interpreter is currently processing. - uint64_t lastUsesIndex_{0}; - - // Invariant: the value is either jsi::Object, jsi::String, jsi::Symbol, - // jsi::BigInt. - std::unordered_map gom_; - // For the PropNameIDs, which are not representable as jsi::Value. - std::unordered_map gpnm_; - - std::string stats_; - /// Whether the marker was reached. - bool markerFound_{false}; - /// Depth in the execution stack. Zero is the outermost function. - uint64_t depth_{0}; - - /// The index of the record that the TraceInterpreter is executing. - uint64_t nextExecIndex_{0}; - - public: - /// Execute the trace given by \p traceFile, that was the trace of executing - /// the bundle given by \p bytecodeFile. - /// \return The stats collected by the runtime about times and memory usage. - static std::string execAndGetStats( - const std::string &traceFile, - const std::vector &bytecodeFiles, - const ExecuteOptions &options); - - /// Same as execAndGetStats, except it additionally accepts a function to - /// create the runtime instance for replaying. This can be used to pass, for - /// example, TracingRuntime to trace while replaying. - static std::string execWithRuntime( - const std::string &traceFile, - const std::vector &bytecodeFiles, - const ExecuteOptions &options, - const std::function( - const ::hermes::vm::RuntimeConfig &runtimeConfig)> &createRuntime); - - /// \param traceStream If non-null, write a trace of the execution into this - /// stream. - /// \return Tuple of GC stats and the runtime instance used for replaying. - static std::tuple> - execFromMemoryBuffer( - std::unique_ptr &&traceBuf, - std::vector> &&codeBufs, - const ExecuteOptions &options, - const std::function( - const ::hermes::vm::RuntimeConfig &runtimeConfig)> &createRuntime); - - private: - TraceInterpreter( - jsi::Runtime &rt, - const ExecuteOptions &options, - const SynthTrace &trace, - std::map<::hermes::SHA1, std::shared_ptr> bundles); - - static std::string exec( - jsi::Runtime &rt, - const ExecuteOptions &options, - const SynthTrace &trace, - std::map<::hermes::SHA1, std::shared_ptr> bundles); - - static ::hermes::vm::RuntimeConfig merge( - ::hermes::vm::RuntimeConfig::Builder &, - const ::hermes::vm::GCConfig::Builder &, - const ExecuteOptions &, - bool, - bool); - - /// Requires \p codeBufs to be the memory buffers containing the code - /// referenced (via source hash) by the given \p trace. Returns a map from - /// the source hash to the memory buffer. In addition, if \p codeIsMmapped is - /// non-null, sets \p *codeIsMmapped to indicate whether all the code is - /// mmapped, and, if \p isBytecode is non-null, sets \p *isBytecode - /// to indicate whether all the code is bytecode. - static std::map<::hermes::SHA1, std::shared_ptr> - getSourceHashToBundleMap( - std::vector> &&codeBufs, - const SynthTrace &trace, - const ExecuteOptions &options, - bool *codeIsMmapped = nullptr, - bool *isBytecode = nullptr); - - jsi::Function createHostFunction( - const SynthTrace::CreateHostFunctionRecord &rec, - const jsi::PropNameID &propNameID); - - jsi::Object createHostObject(SynthTrace::ObjectID objID); - - /// Execute the records with the given ExecuteOptions::MarkerOption - std::string executeRecordsWithMarkerOptions(); - - /// Execute the records. JS might call this recursively when HostFunction or - /// HostObject's functions are called. - void executeRecords(); - - /// Requires that \p valID is the proper id for \p val, and that a - /// defining occurrence of \p valID occurs at the current \p defIndex. Decides - /// whether the definition should be recorded, and, if so, adds the - /// association between \p valID and \p val \p gom_ as appropriate. - void addToObjectMap( - SynthTrace::ObjectID valID, - jsi::Value &&val, - uint64_t defIndex); - - /// Similar to addToObjectMap, but for PropNameIDs. - void addToPropNameIDMap( - SynthTrace::ObjectID id, - jsi::PropNameID &&val, - uint64_t defIndex); - - /// If \p traceValue specifies an Object, String, BigInt or Symbol, requires - /// \p val to be of the corresponding runtime type. Adds this \p val to gom_. - /// - /// \p isThis should be true if and only if the value is a 'this' in a call - /// (only used for validation). TODO(T84791675): Remove this parameter. - /// - /// N.B. This method should be called even if you happen to know that the - /// value cannot be an Object, String, Symbol or BigInt, since it performs - /// useful validation. - void ifObjectAddToObjectMap( - SynthTrace::TraceValue traceValue, - const jsi::Value &val, - uint64_t defIndex, - bool isThis = false); - - /// Same as above, except it avoids copies on temporary objects. - void ifObjectAddToObjectMap( - SynthTrace::TraceValue traceValue, - jsi::Value &&val, - uint64_t defIndex, - bool isThis = false); - - /// Check if the \p marker is the one that is being searched for. If this is - /// the first time encountering the matching marker, perform the actions set - /// up for that marker. - void checkMarker(const std::string &marker); - - /// Get a jsi::Value from gom_ for given ObjectID. - jsi::Value getJSIValueForUse(SynthTrace::ObjectID id); - - /// Get a jsi::PropNameID from gpnm_ for given ObjectID. - jsi::PropNameID getPropNameIDForUse(SynthTrace::ObjectID id); - - /// Convert a TraceValue to a jsi::Value. This calls \p getJSIValueForUse, - /// which will remove the entry from gom_ and globalDefsAndUses_. - jsi::Value traceValueToJSIValue(SynthTrace::TraceValue value); - - /// Erase all references to objects of which last use is before the given - /// record index. - void eraseRefsBefore(uint64_t index); - - std::string printStats(); - - LLVM_ATTRIBUTE_NORETURN void crashOnException( - const std::exception &e, - ::hermes::OptValue globalRecordNum); - - void assertMatch( - const SynthTrace::TraceValue &traceValue, - const jsi::Value &val) const; -}; - -} // namespace tracing -} // namespace hermes -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/TracingRuntime.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/TracingRuntime.h deleted file mode 100644 index a22cc8a2..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/TracingRuntime.h +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_TRACINGRUNTIME_H -#define HERMES_TRACINGRUNTIME_H - -#include "SynthTrace.h" - -#include -#include -#include "llvh/Support/raw_ostream.h" - -namespace facebook { -namespace hermes { -namespace tracing { - -class TracingRuntime : public jsi::RuntimeDecorator { - public: - using RD = RuntimeDecorator; - - TracingRuntime( - std::shared_ptr runtime, - const ::hermes::vm::RuntimeConfig &conf, - std::unique_ptr traceStream); - - /// Assign a new ObjectID for given jsi::Pointer. - SynthTrace::ObjectID defObjectID(const jsi::Pointer &p); - /// Get the ObjectID for given jsi::Pointer. - SynthTrace::ObjectID useObjectID(const jsi::Pointer &p) const; - - virtual void flushAndDisableTrace() = 0; - - /// @name jsi::Runtime methods. - /// @{ - - jsi::Value evaluateJavaScript( - const std::shared_ptr &buffer, - const std::string &sourceURL) override; - - void queueMicrotask(const jsi::Function &callback) override; - bool drainMicrotasks(int maxMicrotasksHint = -1) override; - - jsi::Object global() override; - - jsi::Object createObject() override; - jsi::Object createObjectWithPrototype(const jsi::Value &prototype) override; - jsi::Object createObject(std::shared_ptr ho) override; - - // Note that the NativeState methods do not need to be traced since they - // cannot be observed in JS. - - jsi::BigInt createBigIntFromInt64(int64_t value) override; - jsi::BigInt createBigIntFromUint64(uint64_t value) override; - jsi::String bigintToString(const jsi::BigInt &bigint, int radix) override; - - jsi::String createStringFromAscii(const char *str, size_t length) override; - jsi::String createStringFromUtf8(const uint8_t *utf8, size_t length) override; - jsi::String createStringFromUtf16(const char16_t *utf16, size_t length) - override; - std::string utf8(const jsi::PropNameID &) override; - - jsi::PropNameID createPropNameIDFromAscii(const char *str, size_t length) - override; - jsi::PropNameID createPropNameIDFromUtf8(const uint8_t *utf8, size_t length) - override; - jsi::PropNameID createPropNameIDFromUtf16( - const char16_t *utf16, - size_t length) override; - std::string utf8(const jsi::String &) override; - - std::u16string utf16(const jsi::PropNameID &) override; - std::u16string utf16(const jsi::String &) override; - - void getStringData( - const jsi::String &str, - void *ctx, - void (*cb)(void *ctx, bool ascii, const void *data, size_t num)) override; - - void getPropNameIdData( - const jsi::PropNameID &sym, - void *ctx, - void (*cb)(void *ctx, bool ascii, const void *data, size_t num)) override; - - std::string symbolToString(const jsi::Symbol &) override; - - jsi::PropNameID createPropNameIDFromString(const jsi::String &str) override; - jsi::PropNameID createPropNameIDFromSymbol(const jsi::Symbol &sym) override; - - jsi::Value getProperty(const jsi::Object &obj, const jsi::String &name) - override; - jsi::Value getProperty(const jsi::Object &obj, const jsi::PropNameID &name) - override; - jsi::Value getProperty(const jsi::Object &obj, const jsi::Value &name) - override; - - bool hasProperty(const jsi::Object &obj, const jsi::String &name) override; - bool hasProperty(const jsi::Object &obj, const jsi::PropNameID &name) - override; - bool hasProperty(const jsi::Object &obj, const jsi::Value &name) override; - - void setPropertyValue( - const jsi::Object &obj, - const jsi::String &name, - const jsi::Value &value) override; - void setPropertyValue( - const jsi::Object &obj, - const jsi::PropNameID &name, - const jsi::Value &value) override; - void setPropertyValue( - const jsi::Object &obj, - const jsi::Value &name, - const jsi::Value &value) override; - - void deleteProperty(const jsi::Object &obj, const jsi::PropNameID &name) - override; - void deleteProperty(const jsi::Object &obj, const jsi::String &name) override; - void deleteProperty(const jsi::Object &, const jsi::Value &name) override; - - void setPrototypeOf(const jsi::Object &object, const jsi::Value &prototype) - override; - jsi::Value getPrototypeOf(const jsi::Object &object) override; - - jsi::Array getPropertyNames(const jsi::Object &o) override; - - jsi::WeakObject createWeakObject(const jsi::Object &o) override; - - jsi::Value lockWeakObject(const jsi::WeakObject &wo) override; - - jsi::Array createArray(size_t length) override; - jsi::ArrayBuffer createArrayBuffer( - std::shared_ptr buffer) override; - - size_t size(const jsi::Array &arr) override; - size_t size(const jsi::ArrayBuffer &buf) override; - - uint8_t *data(const jsi::ArrayBuffer &buf) override; - - jsi::Value getValueAtIndex(const jsi::Array &arr, size_t i) override; - - void setValueAtIndexImpl( - const jsi::Array &arr, - size_t i, - const jsi::Value &value) override; - - jsi::Function createFunctionFromHostFunction( - const jsi::PropNameID &name, - unsigned int paramCount, - jsi::HostFunctionType func) override; - - jsi::Value call( - const jsi::Function &func, - const jsi::Value &jsThis, - const jsi::Value *args, - size_t count) override; - - jsi::Value callAsConstructor( - const jsi::Function &func, - const jsi::Value *args, - size_t count) override; - - void setExternalMemoryPressure(const jsi::Object &obj, size_t amount) - override; - - /// @} - - void addMarker(const std::string &marker); - - SynthTrace &trace() { - return trace_; - } - - const SynthTrace &trace() const { - return trace_; - } - - void replaceNondeterministicFuncs(); - - // This is the number of records recorded as part of the 'preamble' of a synth - // trace. This means all the records after this amount are from the actual - // execution of the trace. - uint32_t getNumPreambleRecordsForTest() const { - assert( - numPreambleRecords_ > 0 && - "Only call this method if the preamble has been executed"); - return numPreambleRecords_; - } - - private: - SynthTrace::TraceValue defTraceValue(const jsi::Value &value) { - return toTraceValue(value, true); - } - SynthTrace::TraceValue useTraceValue(const jsi::Value &value) { - return toTraceValue(value, false); - } - SynthTrace::TraceValue toTraceValue( - const jsi::Value &value, - bool assignNewUID = false); - - std::vector argStringifyer( - const jsi::Value *args, - size_t count, - bool assignNewUID = false); - - SynthTrace::TimeSinceStart getTimeSinceStart() const; - - std::shared_ptr runtime_; - SynthTrace trace_; - std::deque savedFunctions; - const SynthTrace::TimePoint startTime_{std::chrono::steady_clock::now()}; - uint32_t numPreambleRecords_; - - SynthTrace::ObjectID currentUniqueID_{0}; - - /// Map from PointerValue* to ObjectID. Except WeakRef case (see below), we - /// assign a new ObjectID whenever we see a new def of jsi::Pointer Value. - std::unordered_map - uniqueIDs_; - - /// WeakObject's PointerValue* to ObjectID mapping. - /// The key is the PointerValue of the WeakObject at the time of - /// it is created. - /// The value is newly assign ObjectID for that PointerValue. - std::unordered_map - weakRefIDs_; -}; - -// TracingRuntime is *almost* vm independent. This provides the -// vm-specific bits. And, it's not a HermesRuntime, but it holds one. -class TracingHermesRuntime final : public TracingRuntime { - public: - /// This constructor is not intended to be invoked directly. - /// Use makeTracingHermesRuntime instead. - /// - /// \p traceStream the stream to write trace to. - /// \p commitAction is invoked on completion of tracing. - /// Completion can be triggered implicitly by crash (if crash manager is - /// provided) or explicitly by invocation of flush. If the committed trace - /// can be found in a file, the callback returns the file name. Otherwise, - /// the callback returns empty. - /// \p rollbackAction is invoked if the runtime is destructed prior to - /// completion of tracing. It may or may not invoked if completion failed. - TracingHermesRuntime( - std::shared_ptr runtime, - const ::hermes::vm::RuntimeConfig &runtimeConfig, - std::unique_ptr traceStream, - std::function commitAction, - std::function rollbackAction); - - ~TracingHermesRuntime() override; - - void flushAndDisableTrace() override; - - std::string flushAndDisableBridgeTrafficTrace() override; - - jsi::Value evaluateJavaScript( - const std::shared_ptr &buffer, - const std::string &sourceURL) override; - - HermesRuntime &hermesRuntime() { - return static_cast(plain()); - } - - const HermesRuntime &hermesRuntime() const { - return static_cast(plain()); - } - - private: - void crashCallback(int fd); - - const ::hermes::vm::RuntimeConfig conf_; - const std::function commitAction_; - const std::function rollbackAction_; - const llvh::Optional<::hermes::vm::CrashManager::CallbackKey> - crashCallbackKey_; - - bool flushedAndDisabled_{false}; - std::string committedTraceFilename_; -}; - -/// Creates and returns a HermesRuntime that traces JSI interactions. -/// The trace will be written to \p traceScratchPath incrementally. -/// On completion, the file will be renamed to \p traceResultPath, and -/// \p traceCompletionCallback (for post-processing) will be invoked. -/// Completion can be triggered implicitly by crash (if crash manager is -/// provided) or explicitly by invocation of flush. -/// If the runtime is destructed without triggering trace completion, -/// the file at \p traceScratchPath will be deleted. -/// The return value of \p traceCompletionCallback indicates whether the -/// invocation completed successfully. -std::unique_ptr makeTracingHermesRuntime( - std::shared_ptr hermesRuntime, - const ::hermes::vm::RuntimeConfig &runtimeConfig, - const std::string &traceScratchPath, - const std::string &traceResultPath, - std::function traceCompletionCallback); - -/// Creates and returns a HermesRuntime that traces JSI interactions. -/// If \p traceStream is non-null, writes the trace to \p traceStream. -/// The \p forReplay parameter indicates whether the runtime is being used -/// in trace replay. (Its behavior can differ slightly in that case.) -std::unique_ptr makeTracingHermesRuntime( - std::shared_ptr hermesRuntime, - const ::hermes::vm::RuntimeConfig &runtimeConfig, - std::unique_ptr traceStream, - bool forReplay = false); - -} // namespace tracing -} // namespace hermes -} // namespace facebook - -#endif // HERMES_TRACINGRUNTIME_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/CDPAgent.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/CDPAgent.h deleted file mode 100644 index 55644044..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/CDPAgent.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_CDPAGENT_H -#define HERMES_CDP_CDPAGENT_H - -#include -#include - -#include -#include -#include -#include - -class CDPAgentTest; - -namespace facebook { -namespace hermes { -namespace cdp { - -using OutboundMessageFunc = std::function; - -class CDPAgentImpl; -class CDPDebugAPI; - -/// Public-facing wrapper for internal CDP state that can be preserved across -/// reloads. -class HERMES_EXPORT State { - public: - /// Incomplete type that stores the actual state. - struct Private; - - /// Create a new empty wrapper. - State(); - /// Create a new wrapper with the provided \p privateState. - explicit State(std::unique_ptr privateState); - - State(const State &other) = delete; - State &operator=(const State &other) = delete; - State(State &&other) noexcept; - State &operator=(State &&other) noexcept; - ~State(); - - inline operator bool() const { - return privateState_ != nullptr; - } - - /// Get the wrapped state. - inline Private &operator*() { - return *privateState_.get(); - } - - /// Get the wrapped state. - inline Private *operator->() { - return privateState_.get(); - } - - private: - /// Pointer to the actual stored state, hidden from users of this wrapper. - std::unique_ptr privateState_; -}; - -/// An agent for interacting with the provided \p runtime and -/// \p asyncDebuggerAPI via CDP messages in the Debugger, Runtime, Profiler, -/// HeapProfiler domains. -/// The integrator of the agent is expected to manage a queue of tasks to be -/// executed with exclusive access to the runtime (i.e. executed when -/// JavaScript is not running). Tasks to be run are delivered to the integrator -/// via the provided \p enqueueRuntimeTaskCallback, and should be executed in -/// order, at the first opportunity between evaluating JavaScript. -/// The integrator can deliver CDP commands to the agent via the -/// \p handleCommand method. When a CDP response or event is generated, it will -/// be delivered to the integrator via the provided \p messageCallback. -/// Both callbacks may be invoked from arbitrary threads. -class HERMES_EXPORT CDPAgent { - friend class ::CDPAgentTest; - - /// Hide the constructor so users can only construct via static create - /// methods. - CDPAgent( - int32_t executionContextID, - CDPDebugAPI &cdpDebugAPI, - debugger::EnqueueRuntimeTaskFunc enqueueRuntimeTaskCallback, - OutboundMessageFunc messageCallback, - State state, - std::shared_ptr destroyedDomainAgents); - - public: - /// Create a new CDP Agent. This can be done on an arbitrary thread; the - /// runtime will not be accessed during execution of this function. - static std::unique_ptr create( - int32_t executionContextID, - CDPDebugAPI &cdpDebugAPI, - debugger::EnqueueRuntimeTaskFunc enqueueRuntimeTaskCallback, - OutboundMessageFunc messageCallback, - State state = {}); - - /// Destroy the CDP Agent. This can be done on an arbitrary thread. - /// It's expected that the integrator will continue to process any runtime - /// tasks enqueued during destruction. - ~CDPAgent(); - - /// This function can be called from arbitrary threads. It processes a CDP - /// command encoded in \p json as UTF-8 in accordance with RFC-8259. See: - // https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/public/devtools_protocol/#wire-format_strings-and-binary-values - void handleCommand(std::string json); - - /// Enable the Runtime domain without processing a CDP command or sending a - /// CDP response. This can be called from arbitrary threads. - void enableRuntimeDomain(); - - /// Enable the Debugger domain without processing a CDP command or sending a - /// CDP response. This can be called from arbitrary threads. - void enableDebuggerDomain(); - - /// Extract state to be persisted across reloads. This can be called from - /// arbitrary threads. - State getState(); - - private: - /// This should be a unique_ptr to provide predictable destruction time lined - /// up with when CDPAgent is destroyed. Do not use shared_ptr. - std::unique_ptr impl_; -}; - -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_CDPAGENT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/CDPDebugAPI.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/CDPDebugAPI.h deleted file mode 100644 index 9809ec9a..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/CDPDebugAPI.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_CDPDEBUGAPI_H -#define HERMES_CDP_CDPDEBUGAPI_H - -#include - -#include "ConsoleMessage.h" - -namespace facebook { -namespace hermes { -namespace cdp { - -class CDPAgentImpl; - -/// Storage and interfaces for carrying out a CDP debug session. Contains -/// information and operations that correspond to a single runtime being -/// debugged, independent of any particular CDPAgent. -class HERMES_EXPORT CDPDebugAPI { - public: - /// Create a new CDPDebugAPI instance. The provided runtime must remain valid - /// until the returned CDPDebugAPI is destroyed. - static std::unique_ptr create( - HermesRuntime &runtime, - size_t maxCachedMessages = kMaxCachedConsoleMessages); - ~CDPDebugAPI(); - - /// Gets the runtime originally passed into this instance. - HermesRuntime &runtime() { - return runtime_; - } - - /// Gets the AsyncDebuggerAPI associated with this instance. - debugger::AsyncDebuggerAPI &asyncDebuggerAPI() { - return *asyncDebuggerAPI_; - } - - /// Adds a console message to the current CDPDebugAPI instance, - /// broadcasting it to all current agents, and storing it for - /// future agents (within buffer limitations). This function - /// must only be called from the runtime thread. - void addConsoleMessage(ConsoleMessage message); - - private: - /// Allow CDPAgentImpl (but not integrators) to access - /// consoleMessageStorage_. - friend class CDPAgentImpl; - - CDPDebugAPI(HermesRuntime &runtime, size_t maxCachedMessages); - - HermesRuntime &runtime_; - std::unique_ptr asyncDebuggerAPI_; - ConsoleMessageStorage consoleMessageStorage_; - ConsoleMessageDispatcher consoleMessageDispatcher_; -}; - -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_CDPDEBUGAPI_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/CallbackOStream.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/CallbackOStream.h deleted file mode 100644 index 8a846344..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/CallbackOStream.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_CALLBACKOSTREAM_H -#define HERMES_CDP_CALLBACKOSTREAM_H - -#include -#include -#include -#include -#include - -namespace facebook { -namespace hermes { -namespace cdp { - -/// Subclass of \c std::ostream where flushing is implemented through a -/// callback. Writes are collected in a buffer. When filled, the buffer's -/// contents are emptied out and sent to a callback. -class CallbackOStream : public std::ostream { - public: - /// Signature of callback called to flush buffer contents. Accepts the buffer - /// as a string. Returns a boolean indicating whether flushing succeeded. - /// Callback failure will be translated to stream failure. If the callback - /// throws an exception it will be swallowed and translated into stream - /// failure. - using Fn = std::function; - - /// Construct a new stream. - /// - /// \p sz The size of the buffer -- how large it can get before it must be - /// flushed. Must be non-zero. - /// \p cb The callback function. - CallbackOStream(size_t sz, Fn cb); - - /// This class is neither movable nor copyable. - CallbackOStream(CallbackOStream &&that) = delete; - CallbackOStream &operator=(CallbackOStream &&that) = delete; - CallbackOStream(const CallbackOStream &that) = delete; - CallbackOStream &operator=(const CallbackOStream &that) = delete; - - private: - /// \c std::streambuf sub-class backed by a std::string buffer and - /// implementing overflow by calling a callback. - class StreamBuf : public std::streambuf { - public: - /// Construct a new streambuf. Parameters are the same as those of - /// \c CallbackOStream . - StreamBuf(size_t sz, Fn cb); - - /// Destruction will flush any remaining buffer contents. - ~StreamBuf() override; - - /// StreamBufs are not copyable, to avoid the flush callback receiving - /// the contents of multiple streams. - StreamBuf(const StreamBuf &) = delete; - StreamBuf &operator=(const StreamBuf &) = delete; - - protected: - /// std::streambuf overrides - int_type overflow(int_type ch) override; - int sync() override; - - private: - /// The size of the backing buffer. Fixed for an instance of the streambuf. - size_t sz_; - - /// The backing buffer that writes will go to until full. - std::unique_ptr buf_; - - /// The function called when buf_ has been filled. - Fn cb_; - - /// Clears the backing buffer. - void reset(); - - /// Clears the backing buffer and returns it contents in a string. - std::string take(); - }; - - StreamBuf sbuf_; -}; - -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_CALLBACKOSTREAM_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/ConsoleMessage.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/ConsoleMessage.h deleted file mode 100644 index 906dbb9a..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/ConsoleMessage.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_CDPCONSOLEMESSAGESTORAGE_H -#define HERMES_CDP_CDPCONSOLEMESSAGESTORAGE_H - -#include -#include -#include - -#include - -#include - -namespace facebook { -namespace hermes { -namespace cdp { - -/// Controls the max number of message to cached in \p consoleMessageCache_. The -/// value here is chosen to match what Chromium uses in their CDP -/// implementation. -static const int kMaxCachedConsoleMessages = 1000; - -enum class ConsoleAPIType { - kLog, - kDebug, - kInfo, - kError, - kWarning, - kDir, - kDirXML, - kTable, - kTrace, - kStartGroup, - kStartGroupCollapsed, - kEndGroup, - kClear, - kAssert, - kTimeEnd, - kCount -}; - -struct ConsoleMessage { - double timestamp; - ConsoleAPIType type; - std::vector args; - debugger::StackTrace stackTrace; - - ConsoleMessage( - double timestamp, - ConsoleAPIType type, - std::vector args, - debugger::StackTrace stackTrace = {}) - : timestamp(timestamp), - type(type), - args(std::move(args)), - stackTrace(stackTrace) {} -}; - -class ConsoleMessageStorage { - public: - ConsoleMessageStorage(size_t maxCachedMessages = kMaxCachedConsoleMessages); - - void addMessage(ConsoleMessage message); - void clear(); - - const std::deque &messages() const; - size_t discarded() const; - std::optional oldestTimestamp() const; - - private: - /// Maximum number of messages to cache. - size_t maxCachedMessages_; - /// Counts the number of console messages discarded when - /// \p consoleMessageCache_ is full. - size_t numConsoleMessagesDiscardedFromCache_ = 0; - /// Cache for storing console messages. Earlier messages are discarded when - /// the cache is full. The choice to use a std::deque is for fast operations - /// at the beginning and the end, so that adding to the cache and discarding - /// from the cache are fast. - std::deque consoleMessageCache_{}; -}; - -class CDPAgent; - -/// Token that identifies a specific subscription to console messages. -using ConsoleMessageRegistration = uint32_t; - -/// Dispatcher to deliver console messages to all registered subscribers. -/// Everything in this class must be used exclusively from the runtime thread. -class ConsoleMessageDispatcher { - public: - ConsoleMessageDispatcher() {} - ~ConsoleMessageDispatcher() {} - - /// Register a subscriber and return a token that can be used to - /// unregister in the future. Must only be called from the runtime thread. - ConsoleMessageRegistration subscribe( - std::function handler) { - auto token = ++tokenCounter_; - subscribers_[token] = handler; - return token; - } - - /// Unregister a subscriber using the token returned from registration. - /// Must only be called from the runtime thread. - void unsubscribe(ConsoleMessageRegistration token) { - subscribers_.erase(token); - } - - /// Deliver a new console message to each subscriber. Must only be called - /// from the runtime thread. - void deliverMessage(const ConsoleMessage &message) { - for (auto &pair : subscribers_) { - pair.second(message); - } - } - - private: - /// Collection of subscribers, identified by registration token. - std::unordered_map< - ConsoleMessageRegistration, - std::function> - subscribers_; - - /// Counter to generate unique registration tokens. - ConsoleMessageRegistration tokenCounter_ = 0; -}; - -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_CDPCONSOLEMESSAGESTORAGE_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/DebuggerDomainAgent.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/DebuggerDomainAgent.h deleted file mode 100644 index 435cdb03..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/DebuggerDomainAgent.h +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_DEBUGGERDOMAINAGENT_H -#define HERMES_CDP_DEBUGGERDOMAINAGENT_H - -#include -#include - -#include -#include -#include - -#include "DomainAgent.h" -#include "DomainState.h" - -namespace facebook { -namespace hermes { -namespace cdp { - -enum class PausedNotificationReason; - -/// Last explicit debugger step command issued by the user. -enum class LastUserStepRequest { - StepInto, - StepOver, - StepOut, -}; - -namespace m = ::facebook::hermes::cdp::message; - -/// Details about a single Hermes breakpoint, implied by a CDP breakpoint. -struct HermesBreakpoint { - debugger::BreakpointID breakpointID; - debugger::ScriptID scriptID; -}; - -/// Type used to store CDP breakpoint identifiers. These IDs are generated by -/// the CDP Handler, so we can constrain them to a specific range. -using CDPBreakpointID = uint32_t; - -/// Description of where breakpoints should be created. -struct CDPBreakpointDescription : public StateValue { - ~CDPBreakpointDescription() override = default; - std::unique_ptr copy() const override { - auto value = std::make_unique(); - value->line = line; - value->column = column; - value->condition = condition; - value->url = url; - return value; - } - - /// Determines whether this breakpoint can be persisted across sessions - bool persistable() const { - // Only persist breakpoints that can apply to future scripts (i.e. - // breakpoints set on a set of files specified by script URL, not - // breakpoints set on an exact, session-specific script ID). - return url.has_value(); - } - - std::optional url; - long long line; - std::optional column; - std::optional condition; -}; - -/// Details of each existing CDP breakpoint, which may correspond to multiple -/// Hermes breakpoints. -struct CDPBreakpoint { - explicit CDPBreakpoint(CDPBreakpointDescription description) - : description(description) {} - - // Description of where the breakpoint should be applied - CDPBreakpointDescription description; - - // Registered breakpoints in Hermes - std::vector hermesBreakpoints; -}; - -struct HermesBreakpointLocation { - debugger::BreakpointID id; - debugger::SourceLocation location; -}; - -/// Handler for the "Debugger" domain of CDP. Accepts events from the runtime, -/// and CDP requests from the debug client belonging to the "Debugger" domain. -/// Produces CDP responses and events belonging to the "Debugger" domain. All -/// methods expect to be invoked with exclusive access to the runtime. -class DebuggerDomainAgent : public DomainAgent { - public: - DebuggerDomainAgent( - int32_t executionContextID, - HermesRuntime &runtime, - debugger::AsyncDebuggerAPI &asyncDebugger, - SynchronizedOutboundCallback messageCallback, - std::shared_ptr objTable_, - DomainState &state); - ~DebuggerDomainAgent(); - - /// Enables the Debugger domain without processing CDP message or sending a - /// CDP response. It will still send CDP notifications if needed. - void enable(); - /// Handles Debugger.enable request - /// @cdp Debugger.enable If domain is already enabled, will return success. - void enable(const m::debugger::EnableRequest &req); - /// Handles Debugger.disable request - /// @cdp Debugger.disable If domain is already disabled, will return success. - void disable(const m::debugger::DisableRequest &req); - - /// Handles Debugger.pause request - void pause(const m::debugger::PauseRequest &req); - /// Handles Debugger.resume request - void resume(const m::debugger::ResumeRequest &req); - - /// Handles Debugger.stepInto request - void stepInto(const m::debugger::StepIntoRequest &req); - /// Handles Debugger.stepOut request - void stepOut(const m::debugger::StepOutRequest &req); - /// Handles Debugger.stepOver request - void stepOver(const m::debugger::StepOverRequest &req); - - /// Handles Debugger.setBlackboxedRanges request - void setBlackboxedRanges(const m::debugger::SetBlackboxedRangesRequest &req); - /// Handles Debugger.setBlackboxPatterns request - void setBlackboxPatterns(const m::debugger::SetBlackboxPatternsRequest &req); - /// Handles Debugger.setPauseOnExceptions - void setPauseOnExceptions( - const m::debugger::SetPauseOnExceptionsRequest &req); - - /// Handles Debugger.evaluateOnCallFrame - void evaluateOnCallFrame(const m::debugger::EvaluateOnCallFrameRequest &req); - - /// Debugger.setBreakpoint creates a CDP breakpoint that applies to exactly - /// one script (identified by script ID) that does not survive reloads. - void setBreakpoint(const m::debugger::SetBreakpointRequest &req); - // Debugger.setBreakpointByUrl creates a CDP breakpoint that may apply to - // multiple scripts (identified by URL), and survives reloads. - void setBreakpointByUrl(const m::debugger::SetBreakpointByUrlRequest &req); - /// Handles Debugger.removeBreakpoint - void removeBreakpoint(const m::debugger::RemoveBreakpointRequest &req); - /// Handles Debugger.setBreakpointsActive - /// @cdp Debugger.setBreakpointsActive Allowed even if domain is not enabled. - void setBreakpointsActive( - const m::debugger::SetBreakpointsActiveRequest &req); - - private: - /// Handle an event originating from the runtime. - void handleDebuggerEvent( - HermesRuntime &runtime, - debugger::AsyncDebuggerAPI &asyncDebugger, - debugger::DebuggerEventType event); - - /// Send a Debugger.paused notification to the debug client - void sendPausedNotificationToClient(PausedNotificationReason reason); - /// Send a Debugger.scriptParsed notification to the debug client - void sendScriptParsedNotificationToClient( - const debugger::SourceLocation srcLoc); - - /// Obtain the newly loaded script and send a ScriptParsed notification to the - /// debug client - void processNewLoadedScript(); - - std::pair createCDPBreakpoint( - CDPBreakpointDescription &&description, - std::optional hermesBreakpoint = std::nullopt); - - std::optional createHermesBreakpoint( - debugger::ScriptID scriptID, - const CDPBreakpointDescription &description); - - void applyBreakpointAndSendNotification( - CDPBreakpointID cdpBreakpointID, - CDPBreakpoint &cdpBreakpoint, - const debugger::SourceLocation &srcLoc); - - std::optional applyBreakpoint( - CDPBreakpoint &cdpBreakpoint, - debugger::ScriptID scriptID); - - /// Holds a boolean that determines if scripts without a script url - /// (e.g. anonymous scripts) should be blackboxed. - /// Same as V8: - /// https://source.chromium.org/chromium/chromium/src/+/fef5d519bab86dbd712d76bfca5be90a6e03459c:v8/src/inspector/v8-debugger-agent-impl.cc;l=997-999 - bool blackboxAnonymousScripts_ = false; - /// Optionally, holds a compiled regex pattern that is used to test if - /// script urls should be blackboxed. - /// See isLocationBlackboxed below for more details. Same as V8: - /// https://source.chromium.org/chromium/chromium/src/+/fef5d519bab86dbd712d76bfca5be90a6e03459c:v8/src/inspector/v8-debugger-agent-impl.cc;l=993-996 - /// Matching using the compiled regex should be done with - /// ::hermes::regex::searchWithBytecode. - std::optional> compiledBlackboxPatternRegex_; - - /// A vector of 1-based positions per script id indicating where blackbox - /// state changes using [from inclusive, to exclusive) pairs. - /// [ (start) ... position[0]) range is not blackboxed - /// [position[0] ... position[1]) range is blackboxed - /// [position[1] ... position[2]) range is not blackboxed ... ... - /// [position[n] ... (end) ) range is blackboxed if n is even, not - /// blackboxed if odd. - /// This is used to determine if the debugger is paused on one of these - /// blackboxed ranges, to prevent the user from stopping there in the - /// following scenarios: - /// 1. Step out- repeats stepping out until reaches a non-blackboxed range. - /// 2. Step over- stepping over to a blackboxed range meaning that - /// the next un-blackboxed range would be after all the stepping in the - /// function are done (because blackboxing is per file, meaning per function - /// as well) so we can execute step out as well in this case until we - /// step out of blackboxed ranges. - /// Comparing with v8, we don’t check if the user comes from a blackboxed - /// range, but only if a stepover got you to a blackboxed range. However - /// both results in the same thing which is stepping out until reaching a - /// non-blackboxed range. - /// 3. Step into- execute another step into. - /// Repeat this step until outside of a blackboxed range. - /// 4. Exceptions triggering the debugger pause- - /// (uncaught or if the user chooses to stop on all exceptions)- - /// ignore and continue execution - /// 5. Debugger statements- ignore and continue execution - /// 6. Explicit pause- keep stepping in until reaching a non-blackboxed range - /// 7. Manual breakpoints- allow stopping in blackboxed ranges - std::unordered_map>> - blackboxedRanges_; - /// Checks whether the passed location falls within a blackboxed range - /// in blackboxedRanges_. - /// Chrome looks at full functions ("frames") to detemine this. See: - /// https://source.chromium.org/chromium/chromium/src/+/318e9cfd9fbbbc70906f6a78d017a2708248dc6d:v8/src/inspector/v8-debugger-agent-impl.cc;l=984-1026 - /// We, on the other hand, look at individual lines since there's no - /// difference in practise because the current way functions are blackboxed is - /// by using ignoreList in source maps, which blackboxes full files, which - /// means also it blackboxes full functions, so there's no difference between - /// checking if a line in a function is blackboxed or if the whole function is - /// blackboxed. - /// This means that we receive one "Debugger.setBlackboxedRanges" per bundle - /// file comprised of source js files. - /// For each file appearing in the "ignoreList" in source maps, we receive the - /// start positions and end positions of the file inside the bundle file: - /// [ file 1 start position, - /// file 1 end position, - /// file 2 start position, - /// file 2 end position, - /// ... ] - bool isLocationBlackboxed( - debugger::ScriptID scriptID, - std::string scriptName, - int lineNumber, - int columnNumber); - /// Checks whether the location of the top frame of the call stack is - /// blackboxed or not using isLocationBlackboxed - bool isTopFrameLocationBlackboxed(); - - bool checkDebuggerEnabled(const m::Request &req); - bool checkDebuggerPaused(const m::Request &req); - - /// Removes any modifications this agent made to Hermes in order to enable - /// debugging - void cleanUp(); - - HermesRuntime &runtime_; - debugger::AsyncDebuggerAPI &asyncDebugger_; - - /// ID for the registered DebuggerEventCallback - debugger::DebuggerEventCallbackID debuggerEventCallbackId_; - - /// Details of each CDP breakpoint that has been created, and not - /// yet destroyed. - std::unordered_map cdpBreakpoints_{}; - - /// CDP breakpoint IDs are assigned by the DebuggerDomainAgent. Keep track of - /// the next available ID. Starts with 100 to avoid confusion with Hermes - /// breakpoints IDs that start with 1. - CDPBreakpointID nextBreakpointID_ = 100; - - DomainState &state_; - - /// Whether the currently installed breakpoints actually take effect. If - /// they're supposed to be inactive, then debugger agent will automatically - /// resume execution when breakpoints are hit. - bool breakpointsActive_; - - /// Whether Debugger.enable was received and wasn't disabled by receiving - /// Debugger.disable - bool enabled_; - - /// Whether to consider the debugger as currently paused. There are some - /// debugger events such as ScriptLoaded where we don't consider the debugger - /// to be paused. - /// Should only be set using setPaused and setUnpaused. - bool paused_; - - /// Called when the runtime is paused. - void setPaused(PausedNotificationReason pausedNotificationReason); - - /// Called when the runtime is resumed. - void setUnpaused(); - - /// Set to true when the user selects to explicitly pause execution. - /// This is set back to false when the execution is paused. - bool explicitPausePending_ = false; - - /// Last explicit step type issued by the user. - /// * This is never reset because cdp can't tell if a step command was - /// completed since a step command that does not result in further operations - /// resolves to a "resume" without "stepFinished" or debugger pause. - /// That means that this member should only be used in situations where we are - /// sure that a step command was issued in the given scenario. For example, a - /// step into command followed by a resume would leave this member holding an - /// "StepInto" even when minutes later the execution stops on a breakpoint. - std::optional lastUserStepRequest_ = std::nullopt; -}; - -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_DEBUGGERDOMAINAGENT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/DomainAgent.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/DomainAgent.h deleted file mode 100644 index 6770e829..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/DomainAgent.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_DOMAINAGENT_H -#define HERMES_CDP_DOMAINAGENT_H - -#include -#include - -#include -#include - -#if defined(__clang__) && (!defined(SWIG)) && defined(_LIBCPP_VERSION) && \ - defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) -#include -#else -#ifndef TSA_GUARDED_BY -#define TSA_GUARDED_BY(x) -#endif -#endif - -namespace facebook { -namespace hermes { -namespace cdp { - -namespace m = ::facebook::hermes::cdp::message; - -/// A wrapper around std::function to make it safe to use from -/// multiple threads. The wrapper implements an invalidate function so that one -/// thread can clean up the underlying std::function in a thread-safe way. -template -class SynchronizedCallback { - public: - SynchronizedCallback(std::function func) - : funcContainer_(std::make_shared(func)) {} - - /// Thread-safe version that calls the underlying std::function. If the - /// underlying std::function is empty, this function is a no-op. - void operator()(Args... args) const { - std::lock_guard lock(funcContainer_->mutex); - if (funcContainer_->func) { - funcContainer_->func(args...); - } - } - - /// Reset the underlying std::function so that future invocations of - /// operator() would just be a no-op. - void invalidate() { - std::lock_guard lock(funcContainer_->mutex); - funcContainer_->func = std::function(); - } - - private: - struct FunctionContainer { - FunctionContainer(std::function func) : func(func) {} - - std::mutex mutex{}; - - /// The actual std::function to be invoked by operator() - std::function func TSA_GUARDED_BY(mutex); - }; - std::shared_ptr funcContainer_; -}; - -using SynchronizedOutboundCallback = SynchronizedCallback; - -class DomainAgent { - protected: - DomainAgent( - int32_t executionContextID, - SynchronizedOutboundCallback messageCallback, - std::shared_ptr objTable) - : executionContextID_(executionContextID), - messageCallback_(messageCallback), - objTable_(objTable) {} - virtual ~DomainAgent() {} - - /// Sends the provided string back to the debug client - void sendToClient(const std::string &str) { - messageCallback_(str); - } - - /// Sends the provided \p Response back to the debug client - void sendResponseToClient(const m::Response &resp) { - sendToClient(resp.toJsonStr()); - } - - /// Sends the provided \p Notification back to the debug client - void sendNotificationToClient(const m::Notification ¬e) { - sendToClient(note.toJsonStr()); - } - - /// Execution context ID associated with the HermesRuntime - int32_t executionContextID_; - - /// Callback function to send CDP response back to the debug client - SynchronizedOutboundCallback messageCallback_; - - std::shared_ptr objTable_; -}; - -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_DOMAINAGENT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/DomainState.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/DomainState.h deleted file mode 100644 index 5eb6bbb2..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/DomainState.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_DOMAINSTATE_H -#define HERMES_CDP_DOMAINSTATE_H - -#include -#include -#include -#include -#include - -#if defined(__clang__) && (!defined(SWIG)) && defined(_LIBCPP_VERSION) && \ - defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) -#include -#else -#ifndef TSA_GUARDED_BY -#define TSA_GUARDED_BY(x) -#endif -#ifndef TSA_REQUIRES -#define TSA_REQUIRES(x) -#endif -#endif - -namespace facebook { -namespace hermes { -namespace cdp { - -/// Base class for data to be stored in DomainState. -struct StateValue { - virtual ~StateValue() = default; - virtual std::unique_ptr copy() const = 0; -}; - -/// StateValue that can be used as a boolean flag. -struct BooleanStateValue : public StateValue { - ~BooleanStateValue() override = default; - std::unique_ptr copy() const override; - - bool value{false}; -}; - -/// StateValue that can be used as a dictionary. Used as the main storage value -/// of DomainState so that modifications can be based on keys of the dictionary -/// hierarchy. -struct DictionaryStateValue : public StateValue { - ~DictionaryStateValue() override = default; - std::unique_ptr copy() const override; - - std::unordered_map> values; -}; - -using StateModification = - std::pair, std::unique_ptr>; - -/// This class acts as container for saving state that CDP agents need after a -/// reload. Its main purpose is to synchronize the manipulation of state on the -/// runtime thread and when CDPAgent::getState() gets called on arbitrary -/// thread. Functions in this class specifically do not contain callbacks to -/// ensure the mutex locking usage remain simple with no reentrancy to think -/// about. -class DomainState { - public: - DomainState(); - explicit DomainState(std::unique_ptr dict); - - /// TSA doesn't get applied to constructors, so delete the normal mechanism. - /// There is a separate copy() function instead. - DomainState(const DomainState &) = delete; - DomainState &operator=(const DomainState &) = delete; - - /// Deep copy of the data and make a new instance. Used by - /// CDPAgent::getState() to get the state in a thread-safe manner. - std::unique_ptr copy(); - - /// This function allows the caller to access values in the saved state. This - /// obtains a copy of the data so that no further synchronization is required - /// after calling this function. This function is expected to only be called a - /// few times after reload, so it isn't used frequently. All entries in the - /// \p paths vector are expected to be pointing to DictionaryStateValue(s) - /// except the last entry, which is a key to any StateValue. - /// \return a copy of the StateValue stored at \p paths, nullptr if no value - /// exists at paths - std::unique_ptr getCopy(std::vector paths); - - /// This class is the only way for callers to manipulate the DomainState. It - /// is a scope-based commit where the modifications get saved upon the class's - /// destruction. The class must not be saved elsewhere and outlive the - /// DomainState where it came from. The intent is to nudge the caller to batch - /// modifications and commit the changes in one go. Because we make a copy of - /// the state with copy(), we want state changes to be atomic. Caller can - /// still break things up into multiple transactions, but the hope is that - /// this nudges them to think about modifications as one atomic unit. - class Transaction { - public: - explicit Transaction(DomainState &state); - ~Transaction(); - - /// Adds a value to the container. All entries in the \p paths vector are - /// expected to be pointing to DictionaryStateValue(s) except the last - /// entry, which is a key to any StateValue. - void add(std::vector paths, const StateValue &value); - - /// Removes a value from the container. All entries in the \p paths vector - /// are expected to be pointing to DictionaryStateValue(s) except the last - /// entry, which is a key to any StateValue. - void remove(std::vector paths); - - private: - friend DomainState; - - DomainState &state_; - std::vector modifications_{}; - }; - - /// Gets a Transaction for modification. - Transaction transaction(); - - private: - /// Helper function for traversing the dictionary hierarchy. - DictionaryStateValue *getDict( - const std::vector &paths, - bool createMissingDict) TSA_REQUIRES(mutex_); - - /// Save modifications to \p dict_. - void commitTransaction(Transaction &transaction); - - std::mutex mutex_{}; - - /// The actual value container. TSA doesn't work if this is just a direct - /// value on the class, so using an unique_ptr. - std::unique_ptr dict_ TSA_GUARDED_BY(mutex_){}; -}; - -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_DOMAINSTATE_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/HeapProfilerDomainAgent.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/HeapProfilerDomainAgent.h deleted file mode 100644 index 227214bc..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/HeapProfilerDomainAgent.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_HEAPPROFILERDOMAINAGENT_H -#define HERMES_CDP_HEAPPROFILERDOMAINAGENT_H - -#include - -#include "DomainAgent.h" - -namespace facebook { -namespace hermes { -namespace cdp { - -/// Handler for the "HeapProfiler" domain of CDP. All methods expect to be -/// invoked with exclusive access to the runtime. -class HeapProfilerDomainAgent : public DomainAgent { - public: - HeapProfilerDomainAgent( - int32_t executionContextID, - HermesRuntime &runtime, - SynchronizedOutboundCallback messageCallback, - std::shared_ptr objTable); - ~HeapProfilerDomainAgent(); - - /// Handles HeapProfiler.takeHeapSnapshot request - void takeHeapSnapshot(const m::heapProfiler::TakeHeapSnapshotRequest &req); - - /// Handle HeapProfiler.getObjectByHeapObjectId - void getObjectByHeapObjectId( - const m::heapProfiler::GetObjectByHeapObjectIdRequest &req); - - /// Handle HeapProfiler.getObjectByHeapObjectId - void getHeapObjectId(const m::heapProfiler::GetHeapObjectIdRequest &req); - - /// Handle HeapProfiler.collectGarbage - void collectGarbage(const m::heapProfiler::CollectGarbageRequest &req); - - /// Handle HeapProfiler.startTrackingHeapObjects - void startTrackingHeapObjects( - const m::heapProfiler::StartTrackingHeapObjectsRequest &req); - - /// Handle HeapProfiler.stopTrackingHeapObjects - void stopTrackingHeapObjects( - const m::heapProfiler::StopTrackingHeapObjectsRequest &req); - - /// Handle HeapProfiler.startSampling - void startSampling(const m::heapProfiler::StartSamplingRequest &req); - - /// Handle HeapProfiler.stopSampling - void stopSampling(const m::heapProfiler::StopSamplingRequest &req); - - private: - void sendSnapshot(int reqId, bool reportProgress, bool captureNumericValue); - - HermesRuntime &runtime_; - - /// Flag indicating whether this agent is registered to receive heap object - /// tracking callbacks. - bool trackingHeapObjectStackTraces_ = false; - - /// Flag indicating whether this agent is currently running a heap sampling - /// session. - bool samplingHeap_ = false; -}; - -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_HEAPPROFILERDOMAINAGENT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/JSONValueInterfaces.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/JSONValueInterfaces.h deleted file mode 100644 index 23a12ba8..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/JSONValueInterfaces.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_JSONVALUEINTERFACES_H -#define HERMES_CDP_JSONVALUEINTERFACES_H - -#include -#include - -#include - -namespace facebook { -namespace hermes { -namespace cdp { -using namespace ::hermes::parser; - -/// Convert a string to a JSONValue. Will return nullopt if parsing is not -/// successful. -std::optional parseStr( - const std::string &str, - JSONFactory &factory); - -/// Convert a string to a JSON object. Will return nullopt if parsing is not -/// successful, or the resulting JSON value is not an object. -std::optional parseStrAsJsonObj( - const std::string &str, - JSONFactory &factory); - -/// Convert a JSONValue to a string. -std::string jsonValToStr(const JSONValue *v); - -/// Check if two JSONValues are equal. -bool jsonValsEQ(const JSONValue *A, const JSONValue *B); - -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_JSONVALUEINTERFACES_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/MessageConverters.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/MessageConverters.h deleted file mode 100644 index 7397bd1d..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/MessageConverters.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_MESSAGECONVERTERS_H -#define HERMES_CDP_MESSAGECONVERTERS_H - -#include -#include -#include - -#include -#include -#include - -namespace facebook { -namespace hermes { -namespace cdp { -namespace message { - -template -void setChromeLocation( - T &chromeLoc, - const facebook::hermes::debugger::SourceLocation &hermesLoc) { - if (hermesLoc.line != facebook::hermes::debugger::kInvalidLocation) { - chromeLoc.lineNumber = hermesLoc.line - 1; - } - - if (hermesLoc.column != facebook::hermes::debugger::kInvalidLocation) { - chromeLoc.columnNumber = hermesLoc.column - 1; - } -} - -/// ErrorCode magic numbers match JSC's (see InspectorBackendDispatcher.cpp) -enum class ErrorCode { - ParseError = -32700, - InvalidRequest = -32600, - MethodNotFound = -32601, - InvalidParams = -32602, - InternalError = -32603, - ServerError = -32000 -}; - -ErrorResponse -makeErrorResponse(int id, ErrorCode code, const std::string &message); - -OkResponse makeOkResponse(int id); - -namespace debugger { - -Location makeLocation(const facebook::hermes::debugger::SourceLocation &loc); - -} // namespace debugger - -namespace runtime { - -CallFrame makeCallFrame(const facebook::hermes::debugger::CallFrameInfo &info); - -std::vector makeCallFrames( - const facebook::hermes::debugger::StackTrace &stackTrace); - -} // namespace runtime - -namespace heapProfiler { - -std::unique_ptr makeSamplingHeapProfile( - const std::string &value); - -} // namespace heapProfiler - -namespace profiler { - -std::unique_ptr makeProfile(const std::string &value); - -} // namespace profiler - -} // namespace message -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_MESSAGECONVERTERS_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/MessageInterfaces.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/MessageInterfaces.h deleted file mode 100644 index f19418f5..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/MessageInterfaces.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_MESSAGEINTERFACES_H -#define HERMES_CDP_MESSAGEINTERFACES_H - -#include -#include -#include -#include -#include - -#include -#include - -namespace facebook { -namespace hermes { -namespace cdp { -namespace message { -using namespace ::hermes::parser; - -struct RequestHandler; - -/// Serializable is an interface for objects that can be serialized to and from -/// JSON. -struct Serializable { - virtual ~Serializable() = default; - virtual JSONValue *toJsonVal(JSONFactory &factory) const = 0; - - std::string toJsonStr() const; -}; - -/// Requests are sent from the debugger to the target. -struct Request : public Serializable { - using ParseResult = std::variant, std::string>; - static std::unique_ptr fromJson(const std::string &str); - - Request() = default; - explicit Request(std::string method) : method(method) {} - - // accept dispatches to the appropriate handler method in RequestHandler based - // on the type of the request. - virtual void accept(RequestHandler &handler) const = 0; - - long long id = 0; - std::string method; -}; - -/// Responses are sent from the target to the debugger in response to a Request. -struct Response : public Serializable { - Response() = default; - - std::optional id = std::nullopt; -}; - -/// Notifications are sent from the target to the debugger. This is used to -/// notify the debugger about events that occur in the target, e.g. stopping -/// at a breakpoint. -struct Notification : public Serializable { - Notification() = default; - explicit Notification(std::string method) : method(method) {} - - std::string method; -}; - -} // namespace message -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_MESSAGEINTERFACES_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/MessageTypes.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/MessageTypes.h deleted file mode 100644 index bdc14d39..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/MessageTypes.h +++ /dev/null @@ -1,1279 +0,0 @@ -// Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved. -// @generated SignedSource<<1284c402aedd087ebdf70e9e76596f1c>> - -#pragma once - -#include -#include - -#include -#include - -namespace facebook { -namespace hermes { -namespace cdp { -namespace message { - -template -void deleter(T *p); -using JSONBlob = std::string; -struct UnknownRequest; - -namespace debugger { -using BreakpointId = std::string; -struct BreakpointResolvedNotification; -struct CallFrame; -using CallFrameId = std::string; -struct DisableRequest; -struct EnableRequest; -struct EvaluateOnCallFrameRequest; -struct EvaluateOnCallFrameResponse; -struct Location; -struct PauseRequest; -struct PausedNotification; -struct RemoveBreakpointRequest; -struct ResumeRequest; -struct ResumedNotification; -struct Scope; -using ScriptLanguage = std::string; -struct ScriptParsedNotification; -struct ScriptPosition; -struct SetBlackboxPatternsRequest; -struct SetBlackboxedRangesRequest; -struct SetBreakpointByUrlRequest; -struct SetBreakpointByUrlResponse; -struct SetBreakpointRequest; -struct SetBreakpointResponse; -struct SetBreakpointsActiveRequest; -struct SetInstrumentationBreakpointRequest; -struct SetInstrumentationBreakpointResponse; -struct SetPauseOnExceptionsRequest; -struct StepIntoRequest; -struct StepOutRequest; -struct StepOverRequest; -} // namespace debugger - -namespace runtime { -struct CallArgument; -struct CallFrame; -struct CallFunctionOnRequest; -struct CallFunctionOnResponse; -struct CompileScriptRequest; -struct CompileScriptResponse; -struct ConsoleAPICalledNotification; -struct CustomPreview; -struct DisableRequest; -struct DiscardConsoleEntriesRequest; -struct EnableRequest; -struct EntryPreview; -struct EvaluateRequest; -struct EvaluateResponse; -struct ExceptionDetails; -struct ExecutionContextCreatedNotification; -struct ExecutionContextDescription; -using ExecutionContextId = long long; -struct GetHeapUsageRequest; -struct GetHeapUsageResponse; -struct GetPropertiesRequest; -struct GetPropertiesResponse; -struct GlobalLexicalScopeNamesRequest; -struct GlobalLexicalScopeNamesResponse; -struct InspectRequestedNotification; -struct InternalPropertyDescriptor; -struct ObjectPreview; -struct PropertyDescriptor; -struct PropertyPreview; -struct ReleaseObjectGroupRequest; -struct ReleaseObjectRequest; -struct RemoteObject; -using RemoteObjectId = std::string; -struct RunIfWaitingForDebuggerRequest; -using ScriptId = std::string; -struct StackTrace; -using Timestamp = double; -using UnserializableValue = std::string; -} // namespace runtime - -namespace heapProfiler { -struct AddHeapSnapshotChunkNotification; -struct CollectGarbageRequest; -struct GetHeapObjectIdRequest; -struct GetHeapObjectIdResponse; -struct GetObjectByHeapObjectIdRequest; -struct GetObjectByHeapObjectIdResponse; -using HeapSnapshotObjectId = std::string; -struct HeapStatsUpdateNotification; -struct LastSeenObjectIdNotification; -struct ReportHeapSnapshotProgressNotification; -struct SamplingHeapProfile; -struct SamplingHeapProfileNode; -struct SamplingHeapProfileSample; -struct StartSamplingRequest; -struct StartTrackingHeapObjectsRequest; -struct StopSamplingRequest; -struct StopSamplingResponse; -struct StopTrackingHeapObjectsRequest; -struct TakeHeapSnapshotRequest; -} // namespace heapProfiler - -namespace profiler { -struct PositionTickInfo; -struct Profile; -struct ProfileNode; -struct StartRequest; -struct StopRequest; -struct StopResponse; -} // namespace profiler - -/// RequestHandler handles requests via the visitor pattern. -struct RequestHandler { - virtual ~RequestHandler() = default; - - virtual void handle(const UnknownRequest &req) = 0; - virtual void handle(const debugger::DisableRequest &req) = 0; - virtual void handle(const debugger::EnableRequest &req) = 0; - virtual void handle(const debugger::EvaluateOnCallFrameRequest &req) = 0; - virtual void handle(const debugger::PauseRequest &req) = 0; - virtual void handle(const debugger::RemoveBreakpointRequest &req) = 0; - virtual void handle(const debugger::ResumeRequest &req) = 0; - virtual void handle(const debugger::SetBlackboxPatternsRequest &req) = 0; - virtual void handle(const debugger::SetBlackboxedRangesRequest &req) = 0; - virtual void handle(const debugger::SetBreakpointRequest &req) = 0; - virtual void handle(const debugger::SetBreakpointByUrlRequest &req) = 0; - virtual void handle(const debugger::SetBreakpointsActiveRequest &req) = 0; - virtual void handle( - const debugger::SetInstrumentationBreakpointRequest &req) = 0; - virtual void handle(const debugger::SetPauseOnExceptionsRequest &req) = 0; - virtual void handle(const debugger::StepIntoRequest &req) = 0; - virtual void handle(const debugger::StepOutRequest &req) = 0; - virtual void handle(const debugger::StepOverRequest &req) = 0; - virtual void handle(const heapProfiler::CollectGarbageRequest &req) = 0; - virtual void handle(const heapProfiler::GetHeapObjectIdRequest &req) = 0; - virtual void handle( - const heapProfiler::GetObjectByHeapObjectIdRequest &req) = 0; - virtual void handle(const heapProfiler::StartSamplingRequest &req) = 0; - virtual void handle( - const heapProfiler::StartTrackingHeapObjectsRequest &req) = 0; - virtual void handle(const heapProfiler::StopSamplingRequest &req) = 0; - virtual void handle( - const heapProfiler::StopTrackingHeapObjectsRequest &req) = 0; - virtual void handle(const heapProfiler::TakeHeapSnapshotRequest &req) = 0; - virtual void handle(const profiler::StartRequest &req) = 0; - virtual void handle(const profiler::StopRequest &req) = 0; - virtual void handle(const runtime::CallFunctionOnRequest &req) = 0; - virtual void handle(const runtime::CompileScriptRequest &req) = 0; - virtual void handle(const runtime::DisableRequest &req) = 0; - virtual void handle(const runtime::DiscardConsoleEntriesRequest &req) = 0; - virtual void handle(const runtime::EnableRequest &req) = 0; - virtual void handle(const runtime::EvaluateRequest &req) = 0; - virtual void handle(const runtime::GetHeapUsageRequest &req) = 0; - virtual void handle(const runtime::GetPropertiesRequest &req) = 0; - virtual void handle(const runtime::GlobalLexicalScopeNamesRequest &req) = 0; - virtual void handle(const runtime::ReleaseObjectRequest &req) = 0; - virtual void handle(const runtime::ReleaseObjectGroupRequest &req) = 0; - virtual void handle(const runtime::RunIfWaitingForDebuggerRequest &req) = 0; -}; - -/// NoopRequestHandler can be subclassed to only handle some requests. -struct NoopRequestHandler : public RequestHandler { - void handle(const UnknownRequest &req) override {} - void handle(const debugger::DisableRequest &req) override {} - void handle(const debugger::EnableRequest &req) override {} - void handle(const debugger::EvaluateOnCallFrameRequest &req) override {} - void handle(const debugger::PauseRequest &req) override {} - void handle(const debugger::RemoveBreakpointRequest &req) override {} - void handle(const debugger::ResumeRequest &req) override {} - void handle(const debugger::SetBlackboxPatternsRequest &req) override {} - void handle(const debugger::SetBlackboxedRangesRequest &req) override {} - void handle(const debugger::SetBreakpointRequest &req) override {} - void handle(const debugger::SetBreakpointByUrlRequest &req) override {} - void handle(const debugger::SetBreakpointsActiveRequest &req) override {} - void handle( - const debugger::SetInstrumentationBreakpointRequest &req) override {} - void handle(const debugger::SetPauseOnExceptionsRequest &req) override {} - void handle(const debugger::StepIntoRequest &req) override {} - void handle(const debugger::StepOutRequest &req) override {} - void handle(const debugger::StepOverRequest &req) override {} - void handle(const heapProfiler::CollectGarbageRequest &req) override {} - void handle(const heapProfiler::GetHeapObjectIdRequest &req) override {} - void handle( - const heapProfiler::GetObjectByHeapObjectIdRequest &req) override {} - void handle(const heapProfiler::StartSamplingRequest &req) override {} - void handle( - const heapProfiler::StartTrackingHeapObjectsRequest &req) override {} - void handle(const heapProfiler::StopSamplingRequest &req) override {} - void handle( - const heapProfiler::StopTrackingHeapObjectsRequest &req) override {} - void handle(const heapProfiler::TakeHeapSnapshotRequest &req) override {} - void handle(const profiler::StartRequest &req) override {} - void handle(const profiler::StopRequest &req) override {} - void handle(const runtime::CallFunctionOnRequest &req) override {} - void handle(const runtime::CompileScriptRequest &req) override {} - void handle(const runtime::DisableRequest &req) override {} - void handle(const runtime::DiscardConsoleEntriesRequest &req) override {} - void handle(const runtime::EnableRequest &req) override {} - void handle(const runtime::EvaluateRequest &req) override {} - void handle(const runtime::GetHeapUsageRequest &req) override {} - void handle(const runtime::GetPropertiesRequest &req) override {} - void handle(const runtime::GlobalLexicalScopeNamesRequest &req) override {} - void handle(const runtime::ReleaseObjectRequest &req) override {} - void handle(const runtime::ReleaseObjectGroupRequest &req) override {} - void handle(const runtime::RunIfWaitingForDebuggerRequest &req) override {} -}; - -/// Types -struct debugger::Location : public Serializable { - Location() = default; - Location(Location &&) = default; - Location(const Location &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - Location &operator=(const Location &) = delete; - Location &operator=(Location &&) = default; - - runtime::ScriptId scriptId{}; - long long lineNumber{}; - std::optional columnNumber; -}; - -struct runtime::PropertyPreview : public Serializable { - PropertyPreview() = default; - PropertyPreview(PropertyPreview &&) = default; - PropertyPreview(const PropertyPreview &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - PropertyPreview &operator=(const PropertyPreview &) = delete; - PropertyPreview &operator=(PropertyPreview &&) = default; - - std::string name; - std::string type; - std::optional value; - std::unique_ptr< - runtime::ObjectPreview, - std::function> - valuePreview{nullptr, deleter}; - std::optional subtype; -}; - -struct runtime::EntryPreview : public Serializable { - EntryPreview() = default; - EntryPreview(EntryPreview &&) = default; - EntryPreview(const EntryPreview &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - EntryPreview &operator=(const EntryPreview &) = delete; - EntryPreview &operator=(EntryPreview &&) = default; - - std::unique_ptr< - runtime::ObjectPreview, - std::function> - key{nullptr, deleter}; - std::unique_ptr< - runtime::ObjectPreview, - std::function> - value{nullptr, deleter}; -}; - -struct runtime::ObjectPreview : public Serializable { - ObjectPreview() = default; - ObjectPreview(ObjectPreview &&) = default; - ObjectPreview(const ObjectPreview &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - ObjectPreview &operator=(const ObjectPreview &) = delete; - ObjectPreview &operator=(ObjectPreview &&) = default; - - std::string type; - std::optional subtype; - std::optional description; - bool overflow{}; - std::vector properties; - std::optional> entries; -}; - -struct runtime::CustomPreview : public Serializable { - CustomPreview() = default; - CustomPreview(CustomPreview &&) = default; - CustomPreview(const CustomPreview &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - CustomPreview &operator=(const CustomPreview &) = delete; - CustomPreview &operator=(CustomPreview &&) = default; - - std::string header; - std::optional bodyGetterId; -}; - -struct runtime::RemoteObject : public Serializable { - RemoteObject() = default; - RemoteObject(RemoteObject &&) = default; - RemoteObject(const RemoteObject &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - RemoteObject &operator=(const RemoteObject &) = delete; - RemoteObject &operator=(RemoteObject &&) = default; - - std::string type; - std::optional subtype; - std::optional className; - std::optional value; - std::optional unserializableValue; - std::optional description; - std::optional objectId; - std::optional preview; - std::optional customPreview; -}; - -struct runtime::CallFrame : public Serializable { - CallFrame() = default; - CallFrame(CallFrame &&) = default; - CallFrame(const CallFrame &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - CallFrame &operator=(const CallFrame &) = delete; - CallFrame &operator=(CallFrame &&) = default; - - std::string functionName; - runtime::ScriptId scriptId{}; - std::string url; - long long lineNumber{}; - long long columnNumber{}; -}; - -struct runtime::StackTrace : public Serializable { - StackTrace() = default; - StackTrace(StackTrace &&) = default; - StackTrace(const StackTrace &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - StackTrace &operator=(const StackTrace &) = delete; - StackTrace &operator=(StackTrace &&) = default; - - std::optional description; - std::vector callFrames; - std::unique_ptr parent; -}; - -struct runtime::ExceptionDetails : public Serializable { - ExceptionDetails() = default; - ExceptionDetails(ExceptionDetails &&) = default; - ExceptionDetails(const ExceptionDetails &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - ExceptionDetails &operator=(const ExceptionDetails &) = delete; - ExceptionDetails &operator=(ExceptionDetails &&) = default; - - long long exceptionId{}; - std::string text; - long long lineNumber{}; - long long columnNumber{}; - std::optional scriptId; - std::optional url; - std::optional stackTrace; - std::optional exception; - std::optional executionContextId; -}; - -struct debugger::Scope : public Serializable { - Scope() = default; - Scope(Scope &&) = default; - Scope(const Scope &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - Scope &operator=(const Scope &) = delete; - Scope &operator=(Scope &&) = default; - - std::string type; - runtime::RemoteObject object{}; - std::optional name; - std::optional startLocation; - std::optional endLocation; -}; - -struct debugger::CallFrame : public Serializable { - CallFrame() = default; - CallFrame(CallFrame &&) = default; - CallFrame(const CallFrame &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - CallFrame &operator=(const CallFrame &) = delete; - CallFrame &operator=(CallFrame &&) = default; - - debugger::CallFrameId callFrameId{}; - std::string functionName; - std::optional functionLocation; - debugger::Location location{}; - std::string url; - std::vector scopeChain; - runtime::RemoteObject thisObj{}; - std::optional returnValue; -}; - -struct debugger::ScriptPosition : public Serializable { - ScriptPosition() = default; - ScriptPosition(ScriptPosition &&) = default; - ScriptPosition(const ScriptPosition &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - ScriptPosition &operator=(const ScriptPosition &) = delete; - ScriptPosition &operator=(ScriptPosition &&) = default; - - long long lineNumber{}; - long long columnNumber{}; -}; - -struct heapProfiler::SamplingHeapProfileNode : public Serializable { - SamplingHeapProfileNode() = default; - SamplingHeapProfileNode(SamplingHeapProfileNode &&) = default; - SamplingHeapProfileNode(const SamplingHeapProfileNode &) = delete; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - SamplingHeapProfileNode &operator=(const SamplingHeapProfileNode &) = delete; - SamplingHeapProfileNode &operator=(SamplingHeapProfileNode &&) = default; - - runtime::CallFrame callFrame{}; - double selfSize{}; - long long id{}; - std::vector children; -}; - -struct heapProfiler::SamplingHeapProfileSample : public Serializable { - SamplingHeapProfileSample() = default; - SamplingHeapProfileSample(SamplingHeapProfileSample &&) = default; - SamplingHeapProfileSample(const SamplingHeapProfileSample &) = delete; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - SamplingHeapProfileSample &operator=(const SamplingHeapProfileSample &) = - delete; - SamplingHeapProfileSample &operator=(SamplingHeapProfileSample &&) = default; - - double size{}; - long long nodeId{}; - double ordinal{}; -}; - -struct heapProfiler::SamplingHeapProfile : public Serializable { - SamplingHeapProfile() = default; - SamplingHeapProfile(SamplingHeapProfile &&) = default; - SamplingHeapProfile(const SamplingHeapProfile &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - SamplingHeapProfile &operator=(const SamplingHeapProfile &) = delete; - SamplingHeapProfile &operator=(SamplingHeapProfile &&) = default; - - heapProfiler::SamplingHeapProfileNode head{}; - std::vector samples; -}; - -struct profiler::PositionTickInfo : public Serializable { - PositionTickInfo() = default; - PositionTickInfo(PositionTickInfo &&) = default; - PositionTickInfo(const PositionTickInfo &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - PositionTickInfo &operator=(const PositionTickInfo &) = delete; - PositionTickInfo &operator=(PositionTickInfo &&) = default; - - long long line{}; - long long ticks{}; -}; - -struct profiler::ProfileNode : public Serializable { - ProfileNode() = default; - ProfileNode(ProfileNode &&) = default; - ProfileNode(const ProfileNode &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - ProfileNode &operator=(const ProfileNode &) = delete; - ProfileNode &operator=(ProfileNode &&) = default; - - long long id{}; - runtime::CallFrame callFrame{}; - std::optional hitCount; - std::optional> children; - std::optional deoptReason; - std::optional> positionTicks; -}; - -struct profiler::Profile : public Serializable { - Profile() = default; - Profile(Profile &&) = default; - Profile(const Profile &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - Profile &operator=(const Profile &) = delete; - Profile &operator=(Profile &&) = default; - - std::vector nodes; - double startTime{}; - double endTime{}; - std::optional> samples; - std::optional> timeDeltas; -}; - -struct runtime::CallArgument : public Serializable { - CallArgument() = default; - CallArgument(CallArgument &&) = default; - CallArgument(const CallArgument &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - CallArgument &operator=(const CallArgument &) = delete; - CallArgument &operator=(CallArgument &&) = default; - - std::optional value; - std::optional unserializableValue; - std::optional objectId; -}; - -struct runtime::ExecutionContextDescription : public Serializable { - ExecutionContextDescription() = default; - ExecutionContextDescription(ExecutionContextDescription &&) = default; - ExecutionContextDescription(const ExecutionContextDescription &) = delete; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - ExecutionContextDescription &operator=(const ExecutionContextDescription &) = - delete; - ExecutionContextDescription &operator=(ExecutionContextDescription &&) = - default; - - runtime::ExecutionContextId id{}; - std::string origin; - std::string name; - std::optional auxData; -}; - -struct runtime::PropertyDescriptor : public Serializable { - PropertyDescriptor() = default; - PropertyDescriptor(PropertyDescriptor &&) = default; - PropertyDescriptor(const PropertyDescriptor &) = delete; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - PropertyDescriptor &operator=(const PropertyDescriptor &) = delete; - PropertyDescriptor &operator=(PropertyDescriptor &&) = default; - - std::string name; - std::optional value; - std::optional writable; - std::optional get; - std::optional set; - bool configurable{}; - bool enumerable{}; - std::optional wasThrown; - std::optional isOwn; - std::optional symbol; -}; - -struct runtime::InternalPropertyDescriptor : public Serializable { - InternalPropertyDescriptor() = default; - InternalPropertyDescriptor(InternalPropertyDescriptor &&) = default; - InternalPropertyDescriptor(const InternalPropertyDescriptor &) = delete; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - InternalPropertyDescriptor &operator=(const InternalPropertyDescriptor &) = - delete; - InternalPropertyDescriptor &operator=(InternalPropertyDescriptor &&) = - default; - - std::string name; - std::optional value; -}; - -/// Requests -struct UnknownRequest : public Request { - UnknownRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional params; -}; - -struct debugger::DisableRequest : public Request { - DisableRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct debugger::EnableRequest : public Request { - EnableRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct debugger::EvaluateOnCallFrameRequest : public Request { - EvaluateOnCallFrameRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - debugger::CallFrameId callFrameId{}; - std::string expression; - std::optional objectGroup; - std::optional includeCommandLineAPI; - std::optional silent; - std::optional returnByValue; - std::optional generatePreview; - std::optional throwOnSideEffect; -}; - -struct debugger::PauseRequest : public Request { - PauseRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct debugger::RemoveBreakpointRequest : public Request { - RemoveBreakpointRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - debugger::BreakpointId breakpointId{}; -}; - -struct debugger::ResumeRequest : public Request { - ResumeRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional terminateOnResume; -}; - -struct debugger::SetBlackboxPatternsRequest : public Request { - SetBlackboxPatternsRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::vector patterns; - std::optional skipAnonymous; -}; - -struct debugger::SetBlackboxedRangesRequest : public Request { - SetBlackboxedRangesRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - runtime::ScriptId scriptId{}; - std::vector positions; -}; - -struct debugger::SetBreakpointRequest : public Request { - SetBreakpointRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - debugger::Location location{}; - std::optional condition; -}; - -struct debugger::SetBreakpointByUrlRequest : public Request { - SetBreakpointByUrlRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - long long lineNumber{}; - std::optional url; - std::optional urlRegex; - std::optional scriptHash; - std::optional columnNumber; - std::optional condition; -}; - -struct debugger::SetBreakpointsActiveRequest : public Request { - SetBreakpointsActiveRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - bool active{}; -}; - -struct debugger::SetInstrumentationBreakpointRequest : public Request { - SetInstrumentationBreakpointRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::string instrumentation; -}; - -struct debugger::SetPauseOnExceptionsRequest : public Request { - SetPauseOnExceptionsRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::string state; -}; - -struct debugger::StepIntoRequest : public Request { - StepIntoRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct debugger::StepOutRequest : public Request { - StepOutRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct debugger::StepOverRequest : public Request { - StepOverRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct heapProfiler::CollectGarbageRequest : public Request { - CollectGarbageRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct heapProfiler::GetHeapObjectIdRequest : public Request { - GetHeapObjectIdRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - runtime::RemoteObjectId objectId{}; -}; - -struct heapProfiler::GetObjectByHeapObjectIdRequest : public Request { - GetObjectByHeapObjectIdRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - heapProfiler::HeapSnapshotObjectId objectId{}; - std::optional objectGroup; -}; - -struct heapProfiler::StartSamplingRequest : public Request { - StartSamplingRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional samplingInterval; - std::optional includeObjectsCollectedByMajorGC; - std::optional includeObjectsCollectedByMinorGC; -}; - -struct heapProfiler::StartTrackingHeapObjectsRequest : public Request { - StartTrackingHeapObjectsRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional trackAllocations; -}; - -struct heapProfiler::StopSamplingRequest : public Request { - StopSamplingRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct heapProfiler::StopTrackingHeapObjectsRequest : public Request { - StopTrackingHeapObjectsRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional reportProgress; - std::optional treatGlobalObjectsAsRoots; - std::optional captureNumericValue; -}; - -struct heapProfiler::TakeHeapSnapshotRequest : public Request { - TakeHeapSnapshotRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional reportProgress; - std::optional treatGlobalObjectsAsRoots; - std::optional captureNumericValue; -}; - -struct profiler::StartRequest : public Request { - StartRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct profiler::StopRequest : public Request { - StopRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct runtime::CallFunctionOnRequest : public Request { - CallFunctionOnRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::string functionDeclaration; - std::optional objectId; - std::optional> arguments; - std::optional silent; - std::optional returnByValue; - std::optional generatePreview; - std::optional userGesture; - std::optional awaitPromise; - std::optional executionContextId; - std::optional objectGroup; -}; - -struct runtime::CompileScriptRequest : public Request { - CompileScriptRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::string expression; - std::string sourceURL; - bool persistScript{}; - std::optional executionContextId; -}; - -struct runtime::DisableRequest : public Request { - DisableRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct runtime::DiscardConsoleEntriesRequest : public Request { - DiscardConsoleEntriesRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct runtime::EnableRequest : public Request { - EnableRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct runtime::EvaluateRequest : public Request { - EvaluateRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::string expression; - std::optional objectGroup; - std::optional includeCommandLineAPI; - std::optional silent; - std::optional contextId; - std::optional returnByValue; - std::optional generatePreview; - std::optional userGesture; - std::optional awaitPromise; -}; - -struct runtime::GetHeapUsageRequest : public Request { - GetHeapUsageRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -struct runtime::GetPropertiesRequest : public Request { - GetPropertiesRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - runtime::RemoteObjectId objectId{}; - std::optional ownProperties; - std::optional accessorPropertiesOnly; - std::optional generatePreview; -}; - -struct runtime::GlobalLexicalScopeNamesRequest : public Request { - GlobalLexicalScopeNamesRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::optional executionContextId; -}; - -struct runtime::ReleaseObjectRequest : public Request { - ReleaseObjectRequest(); - static std::unique_ptr tryMake(const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - runtime::RemoteObjectId objectId{}; -}; - -struct runtime::ReleaseObjectGroupRequest : public Request { - ReleaseObjectGroupRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; - - std::string objectGroup; -}; - -struct runtime::RunIfWaitingForDebuggerRequest : public Request { - RunIfWaitingForDebuggerRequest(); - static std::unique_ptr tryMake( - const JSONObject *obj); - - JSONValue *toJsonVal(JSONFactory &factory) const override; - void accept(RequestHandler &handler) const override; -}; - -/// Responses -struct ErrorResponse : public Response { - ErrorResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - long long code; - std::string message; - std::optional data; -}; - -struct OkResponse : public Response { - OkResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; -}; - -struct debugger::EvaluateOnCallFrameResponse : public Response { - EvaluateOnCallFrameResponse() = default; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - runtime::RemoteObject result{}; - std::optional exceptionDetails; -}; - -struct debugger::SetBreakpointResponse : public Response { - SetBreakpointResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - debugger::BreakpointId breakpointId{}; - debugger::Location actualLocation{}; -}; - -struct debugger::SetBreakpointByUrlResponse : public Response { - SetBreakpointByUrlResponse() = default; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - debugger::BreakpointId breakpointId{}; - std::vector locations; -}; - -struct debugger::SetInstrumentationBreakpointResponse : public Response { - SetInstrumentationBreakpointResponse() = default; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - debugger::BreakpointId breakpointId{}; -}; - -struct heapProfiler::GetHeapObjectIdResponse : public Response { - GetHeapObjectIdResponse() = default; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - heapProfiler::HeapSnapshotObjectId heapSnapshotObjectId{}; -}; - -struct heapProfiler::GetObjectByHeapObjectIdResponse : public Response { - GetObjectByHeapObjectIdResponse() = default; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - runtime::RemoteObject result{}; -}; - -struct heapProfiler::StopSamplingResponse : public Response { - StopSamplingResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - heapProfiler::SamplingHeapProfile profile{}; -}; - -struct profiler::StopResponse : public Response { - StopResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - profiler::Profile profile{}; -}; - -struct runtime::CallFunctionOnResponse : public Response { - CallFunctionOnResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - runtime::RemoteObject result{}; - std::optional exceptionDetails; -}; - -struct runtime::CompileScriptResponse : public Response { - CompileScriptResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::optional scriptId; - std::optional exceptionDetails; -}; - -struct runtime::EvaluateResponse : public Response { - EvaluateResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - runtime::RemoteObject result{}; - std::optional exceptionDetails; -}; - -struct runtime::GetHeapUsageResponse : public Response { - GetHeapUsageResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - double usedSize{}; - double totalSize{}; -}; - -struct runtime::GetPropertiesResponse : public Response { - GetPropertiesResponse() = default; - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::vector result; - std::optional> - internalProperties; - std::optional exceptionDetails; -}; - -struct runtime::GlobalLexicalScopeNamesResponse : public Response { - GlobalLexicalScopeNamesResponse() = default; - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::vector names; -}; - -/// Notifications -struct debugger::BreakpointResolvedNotification : public Notification { - BreakpointResolvedNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - debugger::BreakpointId breakpointId{}; - debugger::Location location{}; -}; - -struct debugger::PausedNotification : public Notification { - PausedNotification(); - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::vector callFrames; - std::string reason; - std::optional data; - std::optional> hitBreakpoints; - std::optional asyncStackTrace; -}; - -struct debugger::ResumedNotification : public Notification { - ResumedNotification(); - static std::unique_ptr tryMake(const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; -}; - -struct debugger::ScriptParsedNotification : public Notification { - ScriptParsedNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - runtime::ScriptId scriptId{}; - std::string url; - long long startLine{}; - long long startColumn{}; - long long endLine{}; - long long endColumn{}; - runtime::ExecutionContextId executionContextId{}; - std::string hash; - std::optional executionContextAuxData; - std::optional sourceMapURL; - std::optional hasSourceURL; - std::optional isModule; - std::optional length; - std::optional scriptLanguage; -}; - -struct heapProfiler::AddHeapSnapshotChunkNotification : public Notification { - AddHeapSnapshotChunkNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::string chunk; -}; - -struct heapProfiler::HeapStatsUpdateNotification : public Notification { - HeapStatsUpdateNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::vector statsUpdate; -}; - -struct heapProfiler::LastSeenObjectIdNotification : public Notification { - LastSeenObjectIdNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - long long lastSeenObjectId{}; - double timestamp{}; -}; - -struct heapProfiler::ReportHeapSnapshotProgressNotification - : public Notification { - ReportHeapSnapshotProgressNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - long long done{}; - long long total{}; - std::optional finished; -}; - -struct runtime::ConsoleAPICalledNotification : public Notification { - ConsoleAPICalledNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - std::string type; - std::vector args; - runtime::ExecutionContextId executionContextId{}; - runtime::Timestamp timestamp{}; - std::optional stackTrace; -}; - -struct runtime::ExecutionContextCreatedNotification : public Notification { - ExecutionContextCreatedNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - runtime::ExecutionContextDescription context{}; -}; - -struct runtime::InspectRequestedNotification : public Notification { - InspectRequestedNotification(); - static std::unique_ptr tryMake( - const JSONObject *obj); - JSONValue *toJsonVal(JSONFactory &factory) const override; - - runtime::RemoteObject object{}; - JSONBlob hints; - std::optional executionContextId; -}; - -} // namespace message -} // namespace cdp -} // namespace hermes -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/MessageTypesInlines.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/MessageTypesInlines.h deleted file mode 100644 index fe765f93..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/MessageTypesInlines.h +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_MESSAGETYPESINLINES_H -#define HERMES_CDP_MESSAGETYPESINLINES_H - -#include -#include -#include - -#include -#include -#include - -namespace facebook { -namespace hermes { -namespace cdp { -namespace message { - -template -using optional = std::optional; - -template -struct is_vector : std::false_type {}; - -template -struct is_vector> : std::true_type {}; - -/// valueFromJson - -/// Convert JSONValue to a Serializable type. -template -typename std:: - enable_if::value, std::unique_ptr>::type - valueFromJson(const JSONValue *v) { - auto res = llvh::dyn_cast_or_null(v); - if (!res) { - return nullptr; - } - return T::tryMake(res); -} - -/// Convert JSONValue to a bool. -template -typename std::enable_if::value, std::unique_ptr>::type -valueFromJson(const JSONValue *v) { - auto res = llvh::dyn_cast_or_null(v); - if (!res) { - return nullptr; - } - return std::make_unique(res->getValue()); -} - -/// Convert JSONValue to a long long. -template -typename std::enable_if::value, std::unique_ptr>:: - type - valueFromJson(const JSONValue *v) { - auto res = llvh::dyn_cast_or_null(v); - if (!res) { - return nullptr; - } - return std::make_unique(res->getValue()); -} - -/// Convert JSONValue to a double. -template -typename std::enable_if::value, std::unique_ptr>:: - type - valueFromJson(const JSONValue *v) { - auto res = llvh::dyn_cast_or_null(v); - if (!res) { - return nullptr; - } - return std::make_unique(res->getValue()); -} - -/// Convert JSONValue to a string. -template -typename std:: - enable_if::value, std::unique_ptr>::type - valueFromJson(const JSONValue *v) { - auto res = llvh::dyn_cast_or_null(v); - if (!res) { - return nullptr; - } - return std::make_unique(res->c_str()); -} - -/// Convert JSONValue to a vector. -template -typename std::enable_if::value, std::unique_ptr>::type -valueFromJson(const JSONValue *items) { - auto *arr = llvh::dyn_cast(items); - std::unique_ptr result = std::make_unique(); - result->reserve(arr->size()); - for (const auto &item : *arr) { - auto itemResult = valueFromJson(item); - if (!itemResult) { - return nullptr; - } - result->push_back(std::move(*itemResult)); - } - return result; -} - -/// Convert JSONValue to a JSONObject. -template -typename std:: - enable_if::value, std::unique_ptr>::type - valueFromJson(JSONValue *v) { - auto *res = llvh::dyn_cast_or_null(v); - if (!res) { - return nullptr; - } - return std::make_unique(res); -} - -/// Pass through JSONValues. -template -typename std:: - enable_if::value, std::unique_ptr>::type - valueFromJson(JSONValue *v) { - return std::make_unique(v); -} - -/// assign(lhs, obj, key) is a wrapper for: -/// -/// lhs = obj[key] -/// -/// It mainly exists so that we can choose the right version of valueFromJson -/// based on the type of lhs. - -template -bool assign(T &lhs, const JSONObject *obj, const U &key) { - JSONValue *v = obj->get(key); - if (v == nullptr) { - return false; - } - auto convertResult = valueFromJson(v); - if (convertResult) { - lhs = std::move(*convertResult); - return true; - } - return false; -} - -template -bool assign(optional &lhs, const JSONObject *obj, const U &key) { - JSONValue *v = obj->get(key); - if (v != nullptr) { - auto convertResult = valueFromJson(v); - if (convertResult) { - lhs = std::move(*convertResult); - return true; - } - return false; - } else { - lhs.reset(); - return true; - } -} - -template -bool assign(std::unique_ptr &lhs, const JSONObject *obj, const U &key) { - JSONValue *v = obj->get(key); - if (v != nullptr) { - auto convertResult = valueFromJson(v); - if (convertResult) { - lhs = std::move(convertResult); - return true; - } - return false; - } else { - lhs.reset(); - return true; - } -} - -template -bool assign( - std::unique_ptr> &lhs, - const JSONObject *obj, - const U &key) { - JSONValue *v = obj->get(key); - if (v != nullptr) { - auto convertResult = valueFromJson(v); - if (convertResult) { - lhs = std::move(convertResult); - return true; - } - return false; - } else { - lhs.reset(); - return true; - } -} - -/// valueToJson - -inline JSONValue *valueToJson(const Serializable &value, JSONFactory &factory) { - return value.toJsonVal(factory); -} - -// Convert a bool to JSONValue. -inline JSONValue *valueToJson(bool b, JSONFactory &factory) { - return factory.getBoolean(b); -} - -// Convert a long long to JSONValue. -inline JSONValue *valueToJson(long long num, JSONFactory &factory) { - return factory.getNumber(num); -} - -// Convert a double to JSONValue. -inline JSONValue *valueToJson(double num, JSONFactory &factory) { - return factory.getNumber(num); -} - -// Convert a string to JSONValue. -inline JSONValue *valueToJson(const std::string &str, JSONFactory &factory) { - return factory.getString(str); -} - -// Convert a vector to JSONValue. -template -JSONValue *valueToJson(const std::vector &items, JSONFactory &factory) { - llvh::SmallVector storage; - for (const auto &item : items) { - storage.push_back(valueToJson(item, factory)); - } - return factory.newArray(storage.size(), storage.begin(), storage.end()); -} - -// Cast a JSONObject to JSONValue. -inline JSONValue *valueToJson(JSONObject *obj, JSONFactory &factory) { - return llvh::cast(obj); -} - -// Pass through JSONValues. -inline JSONValue *valueToJson(JSONValue *v, JSONFactory &factory) { - return v; -} - -/// put(obj, key, value) is meant to be a wrapper for: -/// obj[key] = valueToJson(value); -/// However, JSONObjects are immutable, so we represent a 'put' operation as -/// pushing a new element onto a vector of JSONFactory::Props. - -using Properties = llvh::SmallVectorImpl; - -template -void put( - Properties &props, - const std::string &key, - const V &value, - JSONFactory &factory) { - JSONString *jsStr = factory.getString(key); - JSONValue *jsVal = valueToJson(value, factory); - props.push_back({jsStr, jsVal}); -} - -template -void put( - Properties &props, - const std::string &key, - const optional &optValue, - JSONFactory &factory) { - if (optValue.has_value()) { - JSONString *jsStr = factory.getString(key); - JSONValue *jsVal = valueToJson(optValue.value(), factory); - props.push_back({jsStr, jsVal}); - } -} - -template -void put( - Properties &props, - const std::string &key, - const std::unique_ptr &ptr, - JSONFactory &factory) { - if (ptr.get()) { - JSONString *jsStr = factory.getString(key); - JSONValue *jsVal = valueToJson(*ptr, factory); - props.push_back({jsStr, jsVal}); - } -} - -template -void put( - Properties &props, - const std::string &key, - const std::unique_ptr> &ptr, - JSONFactory &factory) { - if (ptr.get()) { - JSONString *jsStr = factory.getString(key); - JSONValue *jsVal = valueToJson(*ptr, factory); - props.push_back({jsStr, jsVal}); - } -} - -template -void deleter(T *p) { - delete p; -} - -} // namespace message -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_MESSAGETYPESINLINES_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/ProfilerDomainAgent.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/ProfilerDomainAgent.h deleted file mode 100644 index 6c62b9c8..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/ProfilerDomainAgent.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_PROFILERDOMAINAGENT_H -#define HERMES_CDP_PROFILERDOMAINAGENT_H - -#include -#include - -#include "DomainAgent.h" - -namespace facebook { -namespace hermes { -namespace cdp { - -/// Handler for the "Profiler" domain of CDP. All methods expect to be invoked -/// with exclusive access to the runtime. -class ProfilerDomainAgent : public DomainAgent { - public: - ProfilerDomainAgent( - int32_t executionContextID, - HermesRuntime &runtime, - SynchronizedOutboundCallback messageCallback, - std::shared_ptr objTable); - ~ProfilerDomainAgent() = default; - - void start(const m::profiler::StartRequest &req); - void stop(const m::profiler::StopRequest &req); - - private: - HermesRuntime &runtime_; -}; - -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_PROFILERDOMAINAGENT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/RemoteObjectConverters.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/RemoteObjectConverters.h deleted file mode 100644 index ae688884..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/RemoteObjectConverters.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_REMOTEOBJECTCONVERTERS_H -#define HERMES_CDP_REMOTEOBJECTCONVERTERS_H - -#include -#include -#include -#include - -namespace facebook { -namespace hermes { -namespace cdp { - -struct ObjectSerializationOptions { - bool returnByValue = false; - bool generatePreview = false; -}; - -namespace message { - -namespace debugger { - -CallFrame makeCallFrame( - uint32_t callFrameIndex, - const facebook::hermes::debugger::CallFrameInfo &callFrameInfo, - const facebook::hermes::debugger::LexicalInfo &lexicalInfo, - cdp::RemoteObjectsTable &objTable, - jsi::Runtime &runtime, - const facebook::hermes::debugger::ProgramState &state); - -std::vector makeCallFrames( - const facebook::hermes::debugger::ProgramState &state, - cdp::RemoteObjectsTable &objTable, - jsi::Runtime &runtime); - -} // namespace debugger - -namespace runtime { - -RemoteObject makeRemoteObject( - facebook::jsi::Runtime &runtime, - const facebook::jsi::Value &value, - cdp::RemoteObjectsTable &objTable, - const std::string &objectGroup, - const cdp::ObjectSerializationOptions &serializationOptions); - -RemoteObject makeRemoteObjectForError( - facebook::jsi::Runtime &runtime, - const facebook::jsi::Value &value, - cdp::RemoteObjectsTable &objTable, - const std::string &objectGroup); - -ExceptionDetails makeExceptionDetails( - jsi::Runtime &runtime, - const jsi::JSError &error, - cdp::RemoteObjectsTable &objTable, - const std::string &objectGroup); - -ExceptionDetails makeExceptionDetails(const jsi::JSIException &err); - -ExceptionDetails makeExceptionDetails( - facebook::jsi::Runtime &runtime, - const facebook::hermes::debugger::EvalResult &result, - cdp::RemoteObjectsTable &objTable, - const std::string &objectGroup); - -} // namespace runtime - -} // namespace message -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_REMOTEOBJECTCONVERTERS_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/RemoteObjectsTable.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/RemoteObjectsTable.h deleted file mode 100644 index 1b8fff5a..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/RemoteObjectsTable.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_REMOTEOBJECTSTABLE_H -#define HERMES_CDP_REMOTEOBJECTSTABLE_H - -#include -#include -#include -#include - -#include - -namespace facebook { -namespace hermes { -namespace cdp { - -/// Well-known object group names - -/** - * Objects created as a result of the Debugger.paused notification (e.g. scope - * objects) are placed in the "backtrace" object group. This object group is - * cleared when the VM resumes. - */ -extern const char *BacktraceObjectGroup; - -/** - * Objects that are created as a result of a console evaluation are placed in - * the "console" object group. This object group is cleared when the client - * clears the console. - */ -extern const char *ConsoleObjectGroup; - -/** - * RemoteObjectsTable manages the mapping of string object ids to scope metadata - * or actual JSI objects. The debugger vends these ids to the client so that the - * client can perform operations on the ids (e.g. enumerate properties on the - * object backed by the id). See Runtime.RemoteObjectId in the CDT docs for - * more details. - * - * Note that object handles are not ref-counted. Suppose an object foo is mapped - * to object id "objId" and is also in object group "objGroup". Then *either* of - * `releaseObject("objId")` or `releaseObjectGroup("objGroup")` will remove foo - * from the table. This matches the behavior of object groups in CDT. - */ -class RemoteObjectsTable { - public: - RemoteObjectsTable(); - ~RemoteObjectsTable(); - - RemoteObjectsTable(const RemoteObjectsTable &) = delete; - RemoteObjectsTable &operator=(const RemoteObjectsTable &) = delete; - - /** - * addScope adds the provided (frameIndex, scopeIndex) mapping to the table. - * If objectGroup is non-empty, then the scope object is also added to that - * object group for releasing via releaseObjectGroup. Returns an object id. - */ - std::string addScope( - std::pair frameAndScopeIndex, - const std::string &objectGroup); - - /** - * addValue adds the JSI value to the table. If objectGroup is non-empty, then - * the scope object is also added to that object group for releasing via - * releaseObjectGroup. Returns an object id. - */ - std::string addValue( - ::facebook::jsi::Value value, - const std::string &objectGroup); - - /// /param objId The object ID. - /// /return true if object ID represents a scope in the scope chain of a call - /// frame. - bool isScopeId(const std::string &objId) const; - - /** - * Retrieves the (frameIndex, scopeIndex) associated with this object id, or - * nullptr if no mapping exists. The pointer stays valid as long as you only - * call const methods on this class. - */ - const std::pair *getScope(const std::string &objId) const; - - /** - * Retrieves the JSI value associated with this object id, or nullptr if no - * mapping exists. The pointer stays valid as long as you only call const - * methods on this class. - */ - const ::facebook::jsi::Value *getValue(const std::string &objId) const; - - /** - * Retrieves the object group that this object id is in, or empty string if it - * isn't in an object group. The returned pointer is only guaranteed to be - * valid until the next call to this class. - */ - std::string getObjectGroup(const std::string &objId) const; - - /** - * Removes the scope or JSI value backed by the provided object ID from the - * table. \return true if the object was removed, false if it was not found. - */ - bool releaseObject(const std::string &objId); - - /** - * Removes all objects that are part of the provided object group from the - * table. - */ - void releaseObjectGroup(const std::string &objectGroup); - - private: - bool releaseObject(int64_t id); - - int64_t scopeId_ = -1; - int64_t valueId_ = 1; - - std::unordered_map> scopes_; - std::unordered_map values_; - std::unordered_map idToGroup_; - std::unordered_map> groupToIds_; -}; - -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_REMOTEOBJECTSTABLE_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/RuntimeDomainAgent.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/RuntimeDomainAgent.h deleted file mode 100644 index 9c8142aa..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/cdp/RuntimeDomainAgent.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_CDP_RUNTIMEDOMAINAGENT_H -#define HERMES_CDP_RUNTIMEDOMAINAGENT_H - -#include - -#include "CDPDebugAPI.h" -#include "DomainAgent.h" -#include "RemoteObjectConverters.h" - -namespace facebook { -namespace hermes { -namespace cdp { - -namespace m = ::facebook::hermes::cdp::message; - -/// Handler for the "Runtime" domain of CDP. Accepts CDP requests belonging to -/// the "Runtime" domain from the debug client. Produces CDP responses and -/// events belonging to the "Runtime" domain. All methods expect to be invoked -/// with exclusive access to the runtime. -class RuntimeDomainAgent : public DomainAgent { - public: - RuntimeDomainAgent( - int32_t executionContextID, - HermesRuntime &runtime, - debugger::AsyncDebuggerAPI &asyncDebuggerAPI, - SynchronizedOutboundCallback messageCallback, - std::shared_ptr objTable, - ConsoleMessageStorage &consoleMessageStorage, - ConsoleMessageDispatcher &consoleMessageDispatcher); - ~RuntimeDomainAgent(); - - /// Enables the Runtime domain without processing CDP message or sending a CDP - /// response. It will still send CDP notifications if needed. - void enable(); - /// Handles Runtime.enable request - /// @cdp Runtime.enable If domain is already enabled, will return success. - void enable(const m::runtime::EnableRequest &req); - /// @cdp Runtime.discardConsoleEntries - void discardConsoleEntries( - const m::runtime::DiscardConsoleEntriesRequest &req); - /// Handles Runtime.disable request - /// @cdp Runtime.disable If domain is already disabled, will return success. - void disable(const m::runtime::DisableRequest &req); - /// Handles Runtime.getHeapUsage request - /// @cdp Runtime.getHeapUsage Allowed even if domain is not enabled. - void getHeapUsage(const m::runtime::GetHeapUsageRequest &req); - /// Handles Runtime.globalLexicalScopeNames request - /// @cdp Runtime.globalLexicalScopeNames Allowed even if domain is not - /// enabled. - void globalLexicalScopeNames( - const m::runtime::GlobalLexicalScopeNamesRequest &req); - /// Handles Runtime.compileScript request - /// @cdp Runtime.compileScript Not allowed if domain is not enabled. - void compileScript(const m::runtime::CompileScriptRequest &req); - /// Handles Runtime.getProperties request - /// @cdp Runtime.getProperties Allowed even if domain is not enabled. - void getProperties(const m::runtime::GetPropertiesRequest &req); - /// Handles Runtime.evaluate request - /// @cdp Runtime.evaluate Allowed even if domain is not enabled. - void evaluate(const m::runtime::EvaluateRequest &req); - /// Handles Runtime.callFunctionOn request - /// @cdp Runtime.callFunctionOn Allowed even if domain is not enabled. - void callFunctionOn(const m::runtime::CallFunctionOnRequest &req); - /// Dispatches a Runtime.consoleAPICalled notification - void consoleAPICalled(const ConsoleMessage &message, bool isBuffered); - /// Handles Runtime.releaseObject request - /// @cdp Runtime.releaseObject Allowed even if domain is not enabled. - void releaseObject(const m::runtime::ReleaseObjectRequest &req); - /// Handles Runtime.releaseObjectGroup request - /// @cdp Runtime.releaseObjectGroup Allowed even if domain is not enabled. - void releaseObjectGroup(const m::runtime::ReleaseObjectGroupRequest &req); - - private: - struct Helpers { - jsi::Function objectGetOwnPropertySymbols; - jsi::Function objectGetOwnPropertyNames; - jsi::Function objectGetOwnPropertyDescriptor; - jsi::Function objectGetPrototypeOf; - - explicit Helpers(jsi::Runtime &runtime); - }; - - bool checkRuntimeEnabled(const m::Request &req); - - /// Ensure the provided \p executionContextId matches the one - /// indicated via the constructor. Returns true if they match. - /// Sends an error message with the specified \p commandId - /// and returns false otherwise. - bool validateExecutionContextId( - m::runtime::ExecutionContextId executionContextId, - long long commandId); - - std::optional> makePropsFromScope( - std::pair frameAndScopeIndex, - const std::string &objectGroup, - const debugger::ProgramState &state, - const ObjectSerializationOptions &serializationOptions); - std::vector makePropsFromValue( - const jsi::Value &value, - const std::string &objectGroup, - bool onlyOwnProperties, - bool accessorPropertiesOnly, - const ObjectSerializationOptions &serializationOptions); - std::vector - makeInternalPropsFromValue( - const jsi::Value &value, - const std::string &objectGroup, - const ObjectSerializationOptions &serializationOptions); - - HermesRuntime &runtime_; - debugger::AsyncDebuggerAPI &asyncDebuggerAPI_; - ConsoleMessageStorage &consoleMessageStorage_; - ConsoleMessageDispatcher &consoleMessageDispatcher_; - - /// Whether Runtime.enable was received and wasn't disabled by receiving - /// Runtime.disable - bool enabled_; - - // preparedScripts_ stores user-entered scripts that have been prepared for - // execution, and may be invoked by a later command. - std::vector> preparedScripts_; - - /// Console message subscription token, used to unsubscribe during shutdown. - ConsoleMessageRegistration consoleMessageRegistration_; - - /// Cached helper JS functions used by agent methods. - const Helpers helpers_; -}; - -} // namespace cdp -} // namespace hermes -} // namespace facebook - -#endif // HERMES_CDP_RUNTIMEDOMAINAGENT_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/hermes.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/hermes.h deleted file mode 100644 index afae8777..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/hermes.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_HERMES_H -#define HERMES_HERMES_H - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -struct HermesTestHelper; -struct SHUnit; -struct SHRuntime; - -namespace hermes { -namespace vm { -class GCExecTrace; -class Runtime; -} // namespace vm -} // namespace hermes - -namespace facebook { -namespace jsi { - -class ThreadSafeRuntime; - -} - -namespace hermes { - -namespace debugger { -class Debugger; -} - -class HermesRuntime; -/// The Hermes Root API interface. This is the entry point to create the Hermes -/// runtime and to access Hermes-specific methods that do not rely on a runtime -/// instance. -class HERMES_EXPORT IHermesRootAPI : public jsi::ICast { - public: - static constexpr jsi::UUID uuid{ - 0xb654d898, - 0xdfad, - 0x11ef, - 0x859a, - 0x325096b39f47}; - - // Returns an instance of Hermes Runtime. - virtual std::unique_ptr makeHermesRuntime( - const ::hermes::vm::RuntimeConfig &runtimeConfig) = 0; - - virtual bool isHermesBytecode(const uint8_t *data, size_t len) = 0; - - // Returns the supported bytecode version. - virtual uint32_t getBytecodeVersion() = 0; - - // (EXPERIMENTAL) Issues madvise calls for portions of the given - // bytecode file that will likely be used when loading the bytecode - // file and running its global function. - virtual void prefetchHermesBytecode(const uint8_t *data, size_t len) = 0; - - // Returns whether the data is valid HBC with more extensive checks than - // isHermesBytecode and returns why it isn't in errorMessage (if nonnull) - // if not. - virtual bool hermesBytecodeSanityCheck( - const uint8_t *data, - size_t len, - std::string *errorMessage = nullptr) = 0; - - /// Sets a global fatal handler that is shared across all active Hermes - /// runtimes. Setting fatal handler in multiple places will override the - /// previous fatal handler set by this functionality. - /// The fatal handler must not throw exceptions, as Hermes is compiled without - /// exceptions. - virtual void setFatalHandler(void (*handler)(const std::string &)) = 0; - - // Assuming that \p data is valid HBC bytecode data, returns a pointer to the - // first element of the epilogue, data append to the end of the bytecode - // stream. Return pair contain ptr to data and header. - virtual std::pair getBytecodeEpilogue( - const uint8_t *data, - size_t len) = 0; - - /// Enable sampling profiler. - /// Starts a separate thread that polls VM state with \p meanHzFreq frequency. - /// Any subsequent call to \c enableSamplingProfiler() is ignored until - /// next call to \c disableSamplingProfiler() - virtual void enableSamplingProfiler(double meanHzFreq = 100) = 0; - - /// Disable the sampling profiler - virtual void disableSamplingProfiler() = 0; - - /// Dump sampled stack trace to the given file name. - virtual void dumpSampledTraceToFile(const std::string &fileName) = 0; - - /// Dump sampled stack trace to the given stream. - virtual void dumpSampledTraceToStream(std::ostream &stream) = 0; - - /// Return the executed JavaScript function info. - /// This information holds the segmentID, Virtualoffset and sourceURL. - /// This information is needed specifically to be able to symbolicate non-CJS - /// bundles correctly. This API will be simplified later to simply return a - /// segmentID and virtualOffset, when we are able to only support CJS bundles. - virtual std::unordered_map> - getExecutedFunctions() = 0; - - /// \return whether code coverage profiler is enabled or not. - virtual bool isCodeCoverageProfilerEnabled() = 0; - - /// Enable code coverage profiler. - virtual void enableCodeCoverageProfiler() = 0; - - /// Disable code coverage profiler. - virtual void disableCodeCoverageProfiler() = 0; - - protected: - /// The destructor is protected as delete calls on interfaces must not occur. - /// It is also non-virtual to simplify the v-table. - ~IHermesRootAPI() {} -}; - -/// The setFatalHandler functionality has global effects, which may cause -/// unintended or surprising behavior for users of this API. For this reason, it -/// is not recommended and the functionality is provided by the optional -/// interface ISetFatalHandler. -class HERMES_EXPORT ISetFatalHandler : public jsi::ICast { - public: - static constexpr jsi::UUID uuid{ - 0xda98a610, - 0x09cb, - 0x11f0, - 0x87bf, - 0x325096b39f47}; - /// Sets a global fatal handler that is shared across all active Hermes - /// runtimes. Setting fatal handler in multiple places will override the - /// previous fatal handler set by this functionality. - /// The fatal handler must not throw exceptions, as Hermes is compiled without - /// exceptions. - virtual void setFatalHandler(void (*handler)(const std::string &)) = 0; - - protected: - ~ISetFatalHandler() = default; -}; - -/// Interface for methods that are exposed for test purposes. -class HERMES_EXPORT IHermesTestHelpers : public jsi::ICast { - public: - static constexpr jsi::UUID uuid{ - 0x664e489a, - 0xf941, - 0x11ef, - 0xa44c, - 0x325096b39f47}; - - virtual size_t rootsListLengthForTests() const = 0; - - protected: - ~IHermesTestHelpers() = default; -}; - -class HermesRuntime : public jsi::Runtime, - public IHermes, - public IHermesSHUnit { - public: - /// Similar to jsi::Runtime, HermesRuntime is treated as an object, rather - /// than a pure interface. This is to prevent breaking usages of - /// HermesRuntime prior to the introduction of jsi::IRuntime, IHermes, and - /// other interfaces. - ~HermesRuntime() override = default; - - using jsi::Runtime::castInterface; -}; - -/// Returns a pointer to an object that can be cast into IHermesRootAPI, which -/// can be used to create a Hermes runtime and to access global Hermes-specific -/// methods. This object has static lifetime. -HERMES_EXPORT jsi::ICast *makeHermesRootAPI(); - -/// Return a RuntimeConfig that is more suited for running untrusted JS than -/// the default config. Disables some language features and may trade off some -/// performance for security. -/// -/// Can serve as a starting point with tweaks to re-enable needed features: -/// auto conf = hardenedHermesRuntimeConfig().rebuild(); -/// conf.withArrayBuffer(true); -/// ... -/// auto runtime = makeHermesRuntime(conf.build()); -HERMES_EXPORT ::hermes::vm::RuntimeConfig hardenedHermesRuntimeConfig(); - -HERMES_EXPORT std::unique_ptr makeHermesRuntime( - const ::hermes::vm::RuntimeConfig &runtimeConfig = - ::hermes::vm::RuntimeConfig()); - -/// Create a HermesRuntime for the given config without throwing any exceptions. -/// This is safe to be called from code that is compiled without exceptions. -/// Returns nullptr on failure. -HERMES_EXPORT std::unique_ptr makeHermesRuntimeNoThrow( - const ::hermes::vm::RuntimeConfig &runtimeConfig = - ::hermes::vm::RuntimeConfig()) noexcept; - -HERMES_EXPORT std::unique_ptr -makeThreadSafeHermesRuntime( - const ::hermes::vm::RuntimeConfig &runtimeConfig = - ::hermes::vm::RuntimeConfig()); -} // namespace hermes -} // namespace facebook - -#endif diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/hermes_node_api.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/hermes_node_api.h deleted file mode 100644 index f0a08c95..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/hermes_node_api.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * Copyright (c) Microsoft Corporation. - * Licensed under the MIT license. - */ - -#ifndef HERMES_NODE_API_H -#define HERMES_NODE_API_H - -#include -#include -// #include "hermes/VM/RuntimeModule.h" -#include "js_native_api.h" - -NAPI_EXTERN napi_status NAPI_CDECL napi_run_bytecode(napi_env env, void* data, size_t size, const char* source_url, napi_value *result); - -namespace hermes::node_api { - -class NodeApiEnvironment; - -// A task to execute by TaskRunner. -class Task { - public: - virtual ~Task() = default; - virtual void invoke() noexcept = 0; -}; - -// The TaskRunner interface to schedule tasks in JavaScript thread. -class TaskRunner { - public: - virtual ~TaskRunner() = default; - virtual void post(std::unique_ptr task) noexcept = 0; -}; - -// Get or create a Node API environment associated with the given Hermes -// runtime. The Node API environment is deleted by the runtime destructor. -// HERMES_EXPORT vm::CallResult getOrCreateNodeApiEnvironment( -// vm::Runtime &runtime, -// hbc::CompileFlags compileFlags, -// std::shared_ptr taskRunner, -// const std::function &unhandledErrorCallback, -// int32_t apiVersion) noexcept; - -napi_env createNodeApiEnv( - void* vmRuntime, - std::shared_ptr<::hermes::node_api::TaskRunner> taskRunner, - const std::function &unhandledErrorCallback, - int32_t NODE_API_VERSION -) noexcept; - -// // Initialize new Node API module in a new Node API environment. -// napi_status initializeNodeApiModule( -// vm::Runtime &runtime, -// napi_addon_register_func registerModule, -// int32_t apiVersion, -// napi_value *exports) noexcept; - -// napi_status setNodeApiEnvironmentData( -// napi_env env, -// const napi_type_tag &tag, -// void *data) noexcept; - -// napi_status getNodeApiEnvironmentData( -// napi_env env, -// const napi_type_tag &tag, -// void **data) noexcept; - -// // TODO: can we remove it? -// napi_status checkNodeApiPreconditions(napi_env env) noexcept; - -// // TODO: can we remove it? -// napi_status setNodeApiValue( -// napi_env env, -// ::hermes::vm::CallResult<::hermes::vm::HermesValue> hvResult, -// napi_value *result); - -// // TODO: can we remove it? -// napi_status checkJSErrorStatus( -// napi_env env, -// vm::ExecutionStatus hermesStatus) noexcept; - -// // TODO: remove it -// napi_status queueMicrotask(napi_env env, napi_value callback) noexcept; - -// using nodeApiCallback = hermes::vm::CallResult(void *); - -// napi_status runInNodeApiContext( -// napi_env env, -// nodeApiCallback callback, -// void *data, -// napi_value *result) noexcept; - -// template -// napi_status runInNodeApiContext( -// napi_env env, -// TCallback &&callback, -// napi_value *result) noexcept { -// return runInNodeApiContext( -// env, -// [](void *data) -> ::hermes::vm::CallResult { -// std::remove_reference_t *cb = -// reinterpret_cast *>(data); -// return (*cb)(); -// }, -// &callback, -// result); -// } - -// // TODO: can we remove it? -// template -// napi_status setLastNativeError( -// napi_env env, -// napi_status status, -// const char *fileName, -// uint32_t line, -// TArgs &&...args) noexcept { -// std::ostringstream sb; -// (void)(sb << ... << args); -// const std::string message = sb.str(); -// return setLastNativeError(env, status, fileName, line, message); -// } - -// // TODO: can we remove it? -// template <> -// napi_status setLastNativeError( -// napi_env env, -// napi_status status, -// const char *fileName, -// uint32_t line, -// const std::string &message) noexcept; - -// // TODO: can we remove it? -// napi_status clearLastNativeError(napi_env env) noexcept; - -// // TODO: can we replace it with something else? -// napi_status openNodeApiScope(napi_env env, void **scope) noexcept; - -// // TODO: can we replace it with something else? -// napi_status closeNodeApiScope(napi_env env, void *scope) noexcept; - -} // namespace hermes::node_api - -#endif // HERMES_NODE_API_H diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/hermes_tracing.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/hermes_tracing.h deleted file mode 100644 index bb33b357..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/hermes/hermes_tracing.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifndef HERMES_HERMES_TRACING_H -#define HERMES_HERMES_TRACING_H - -#include - -namespace llvh { -class raw_ostream; -} // namespace llvh - -namespace facebook { -namespace hermes { - -/// Creates and returns a tracing runtime if \p runtimeConfig.SynthTraceMode is -/// either SynthTraceMode::Tracing or SynthTraceMode::TracingAndReplaying. -/// Otherwise, returns the passed \n hermesRuntime as is. -/// The trace will be written to \p traceScratchPath incrementally. -/// On completion, the file will be renamed to \p traceResultPath, and -/// \p traceCompletionCallback (for post-processing) will be invoked. -/// Completion can be triggered implicitly by crash (if crash manager is -/// provided) or explicitly by invocation of flush. -/// If the runtime is destructed without triggering trace completion, -/// the file at \p traceScratchPath will be deleted. -/// The return value of \p traceCompletionCallback indicates whether the -/// invocation completed successfully. If \p traceCompletionCallback is null, it -/// also assumes as if the callback is successful. -std::shared_ptr makeTracingHermesRuntime( - std::shared_ptr hermesRuntime, - const ::hermes::vm::RuntimeConfig &runtimeConfig, - const std::string &traceScratchPath, - const std::string &traceResultPath, - std::function traceCompletionCallback); - -/// Creates and returns a tracing runtime that wrapps the passed -/// \p hermesRuntime. This API is mainly for Synth Trace replay (and tracing), -/// and for testing. -/// \p traceStream the stream to write trace to. -/// \p forReplay indicates whether the runtime is being used in trace replay and -/// tracing. -std::shared_ptr makeTracingHermesRuntime( - std::shared_ptr hermesRuntime, - const ::hermes::vm::RuntimeConfig &runtimeConfig, - std::unique_ptr traceStream, - bool forReplay = false); - -} // namespace hermes -} // namespace facebook - -#endif diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/JSIDynamic.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/JSIDynamic.h deleted file mode 100644 index d022b639..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/JSIDynamic.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include - -namespace facebook { -namespace jsi { - -facebook::jsi::Value valueFromDynamic( - facebook::jsi::Runtime& runtime, - const folly::dynamic& dyn); - -folly::dynamic dynamicFromValue( - facebook::jsi::Runtime& runtime, - const facebook::jsi::Value& value, - const std::function& filterObjectKeys = nullptr); - -} // namespace jsi -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/decorator.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/decorator.h deleted file mode 100644 index 7e46db66..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/decorator.h +++ /dev/null @@ -1,1064 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -#include -#include - -// This file contains objects to help API users create their own -// runtime adapters, i.e. if you want to compose runtimes to add your -// own behavior. - -namespace facebook { -namespace jsi { - -// Use this to wrap host functions. It will pass the member runtime as -// the first arg to the callback. The first argument to the ctor -// should be the decorated runtime, not the plain one. -class DecoratedHostFunction { - public: - DecoratedHostFunction(Runtime& drt, HostFunctionType plainHF) - : drt_(drt), plainHF_(std::move(plainHF)) {} - - Runtime& decoratedRuntime() { - return drt_; - } - - Value - operator()(Runtime&, const Value& thisVal, const Value* args, size_t count) { - return plainHF_(decoratedRuntime(), thisVal, args, count); - } - - private: - template - friend class RuntimeDecorator; - - Runtime& drt_; - HostFunctionType plainHF_; -}; - -// From the perspective of the caller, a plain HostObject is passed to -// the decorated Runtime, and the HostObject methods expect to get -// passed that Runtime. But the plain Runtime will pass itself to its -// callback, so we need a helper here which curries the decorated -// Runtime, and calls the plain HostObject with it. -// -// If the concrete RuntimeDecorator derives DecoratedHostObject, it -// should call the base class get() and set() to invoke the plain -// HostObject functionality. The Runtime& it passes does not matter, -// as it is not used. -class DecoratedHostObject : public HostObject { - public: - DecoratedHostObject(Runtime& drt, std::shared_ptr plainHO) - : drt_(drt), plainHO_(plainHO) {} - - // The derived class methods can call this to get a reference to the - // decorated runtime, since the rt passed to the callback will be - // the plain runtime. - Runtime& decoratedRuntime() { - return drt_; - } - - Value get(Runtime&, const PropNameID& name) override { - return plainHO_->get(decoratedRuntime(), name); - } - - void set(Runtime&, const PropNameID& name, const Value& value) override { - plainHO_->set(decoratedRuntime(), name, value); - } - - std::vector getPropertyNames(Runtime&) override { - return plainHO_->getPropertyNames(decoratedRuntime()); - } - - private: - template - friend class RuntimeDecorator; - - Runtime& drt_; - std::shared_ptr plainHO_; -}; - -/// C++ variant on a standard Decorator pattern, using template -/// parameters. The \c Plain template parameter type is the -/// undecorated Runtime type. You can usually use \c Runtime here, -/// but if you know the concrete type ahead of time and it's final, -/// the compiler can devirtualize calls to the decorated -/// implementation. The \c Base template parameter type will be used -/// as the base class of the decorated type. Here, too, you can -/// usually use \c Runtime, but if you want the decorated type to -/// implement a derived class of Runtime, you can specify that here. -/// For an example, see threadsafe.h. -template -class RuntimeDecorator : public Base, private jsi::Instrumentation { - public: - Plain& plain() { - static_assert( - std::is_base_of::value, - "RuntimeDecorator's Plain type must derive from jsi::Runtime"); - static_assert( - std::is_base_of::value, - "RuntimeDecorator's Base type must derive from jsi::Runtime"); - return plain_; - } - const Plain& plain() const { - return plain_; - } - - ICast* castInterface(const UUID& interfaceUUID) override { - return plain().castInterface(interfaceUUID); - } - - Value evaluateJavaScript( - const std::shared_ptr& buffer, - const std::string& sourceURL) override { - return plain().evaluateJavaScript(buffer, sourceURL); - } - std::shared_ptr prepareJavaScript( - const std::shared_ptr& buffer, - std::string sourceURL) override { - return plain().prepareJavaScript(buffer, std::move(sourceURL)); - } - Value evaluatePreparedJavaScript( - const std::shared_ptr& js) override { - return plain().evaluatePreparedJavaScript(js); - } - void queueMicrotask(const jsi::Function& callback) override { - return plain().queueMicrotask(callback); - } - bool drainMicrotasks(int maxMicrotasksHint) override { - return plain().drainMicrotasks(maxMicrotasksHint); - } - Object global() override { - return plain().global(); - } - std::string description() override { - return plain().description(); - } - bool isInspectable() override { - return plain().isInspectable(); - } - Instrumentation& instrumentation() override { - return *this; - } - - protected: - // plain is generally going to be a reference to an object managed - // by a derived class. We cache it here so this class can be - // concrete, and avoid making virtual calls to find the plain - // Runtime. Note that the ctor and dtor do not access through the - // reference, so passing a reference to an object before its - // lifetime has started is ok. - RuntimeDecorator(Plain& plain) : plain_(plain) {} - - Runtime::PointerValue* cloneSymbol(const Runtime::PointerValue* pv) override { - return plain_.cloneSymbol(pv); - } - Runtime::PointerValue* cloneBigInt(const Runtime::PointerValue* pv) override { - return plain_.cloneBigInt(pv); - } - Runtime::PointerValue* cloneString(const Runtime::PointerValue* pv) override { - return plain_.cloneString(pv); - } - Runtime::PointerValue* cloneObject(const Runtime::PointerValue* pv) override { - return plain_.cloneObject(pv); - } - Runtime::PointerValue* clonePropNameID( - const Runtime::PointerValue* pv) override { - return plain_.clonePropNameID(pv); - } - - PropNameID createPropNameIDFromAscii(const char* str, size_t length) - override { - return plain_.createPropNameIDFromAscii(str, length); - } - PropNameID createPropNameIDFromUtf8(const uint8_t* utf8, size_t length) - override { - return plain_.createPropNameIDFromUtf8(utf8, length); - } - PropNameID createPropNameIDFromString(const String& str) override { - return plain_.createPropNameIDFromString(str); - } - PropNameID createPropNameIDFromUtf16(const char16_t* utf16, size_t length) - override { - return plain_.createPropNameIDFromUtf16(utf16, length); - } - PropNameID createPropNameIDFromSymbol(const Symbol& sym) override { - return plain_.createPropNameIDFromSymbol(sym); - } - std::string utf8(const PropNameID& id) override { - return plain_.utf8(id); - } - bool compare(const PropNameID& a, const PropNameID& b) override { - return plain_.compare(a, b); - } - - std::string symbolToString(const Symbol& sym) override { - return plain_.symbolToString(sym); - } - - BigInt createBigIntFromInt64(int64_t value) override { - return plain_.createBigIntFromInt64(value); - } - BigInt createBigIntFromUint64(uint64_t value) override { - return plain_.createBigIntFromUint64(value); - } - bool bigintIsInt64(const BigInt& b) override { - return plain_.bigintIsInt64(b); - } - bool bigintIsUint64(const BigInt& b) override { - return plain_.bigintIsUint64(b); - } - uint64_t truncate(const BigInt& b) override { - return plain_.truncate(b); - } - String bigintToString(const BigInt& bigint, int radix) override { - return plain_.bigintToString(bigint, radix); - } - - String createStringFromAscii(const char* str, size_t length) override { - return plain_.createStringFromAscii(str, length); - } - String createStringFromUtf8(const uint8_t* utf8, size_t length) override { - return plain_.createStringFromUtf8(utf8, length); - } - String createStringFromUtf16(const char16_t* utf16, size_t length) override { - return plain_.createStringFromUtf16(utf16, length); - } - std::string utf8(const String& s) override { - return plain_.utf8(s); - } - - std::u16string utf16(const String& str) override { - return plain_.utf16(str); - } - std::u16string utf16(const PropNameID& sym) override { - return plain_.utf16(sym); - } - - void getStringData( - const jsi::String& str, - void* ctx, - void ( - *cb)(void* ctx, bool ascii, const void* data, size_t num)) override { - plain_.getStringData(str, ctx, cb); - } - - void getPropNameIdData( - const jsi::PropNameID& sym, - void* ctx, - void ( - *cb)(void* ctx, bool ascii, const void* data, size_t num)) override { - plain_.getPropNameIdData(sym, ctx, cb); - } - - Object createObjectWithPrototype(const Value& prototype) override { - return plain_.createObjectWithPrototype(prototype); - } - - Object createObject() override { - return plain_.createObject(); - } - - Object createObject(std::shared_ptr ho) override { - return plain_.createObject( - std::make_shared(*this, std::move(ho))); - } - std::shared_ptr getHostObject(const jsi::Object& o) override { - std::shared_ptr dho = plain_.getHostObject(o); - return static_cast(*dho).plainHO_; - } - HostFunctionType& getHostFunction(const jsi::Function& f) override { - HostFunctionType& dhf = plain_.getHostFunction(f); - // This will fail if a cpp file including this header is not compiled - // with RTTI. - return dhf.target()->plainHF_; - } - - bool hasNativeState(const Object& o) override { - return plain_.hasNativeState(o); - } - std::shared_ptr getNativeState(const Object& o) override { - return plain_.getNativeState(o); - } - void setNativeState(const Object& o, std::shared_ptr state) - override { - plain_.setNativeState(o, state); - } - - void setExternalMemoryPressure(const Object& obj, size_t amt) override { - plain_.setExternalMemoryPressure(obj, amt); - } - - void setPrototypeOf(const Object& object, const Value& prototype) override { - plain_.setPrototypeOf(object, prototype); - } - - Value getPrototypeOf(const Object& object) override { - return plain_.getPrototypeOf(object); - } - - Value getProperty(const Object& o, const PropNameID& name) override { - return plain_.getProperty(o, name); - } - Value getProperty(const Object& o, const String& name) override { - return plain_.getProperty(o, name); - } - Value getProperty(const Object& o, const Value& name) override { - return plain_.getProperty(o, name); - } - bool hasProperty(const Object& o, const PropNameID& name) override { - return plain_.hasProperty(o, name); - } - bool hasProperty(const Object& o, const String& name) override { - return plain_.hasProperty(o, name); - } - bool hasProperty(const Object& o, const Value& name) override { - return plain_.hasProperty(o, name); - } - void setPropertyValue( - const Object& o, - const PropNameID& name, - const Value& value) override { - plain_.setPropertyValue(o, name, value); - } - void setPropertyValue(const Object& o, const String& name, const Value& value) - override { - plain_.setPropertyValue(o, name, value); - } - void setPropertyValue(const Object& o, const Value& name, const Value& value) - override { - plain_.setPropertyValue(o, name, value); - } - - void deleteProperty(const Object& object, const PropNameID& name) override { - plain_.deleteProperty(object, name); - } - - void deleteProperty(const Object& object, const String& name) override { - plain_.deleteProperty(object, name); - } - - void deleteProperty(const Object& object, const Value& name) override { - plain_.deleteProperty(object, name); - } - - bool isArray(const Object& o) const override { - return plain_.isArray(o); - } - bool isArrayBuffer(const Object& o) const override { - return plain_.isArrayBuffer(o); - } - bool isFunction(const Object& o) const override { - return plain_.isFunction(o); - } - bool isHostObject(const jsi::Object& o) const override { - return plain_.isHostObject(o); - } - bool isHostFunction(const jsi::Function& f) const override { - return plain_.isHostFunction(f); - } - Array getPropertyNames(const Object& o) override { - return plain_.getPropertyNames(o); - } - - WeakObject createWeakObject(const Object& o) override { - return plain_.createWeakObject(o); - } - Value lockWeakObject(const WeakObject& wo) override { - return plain_.lockWeakObject(wo); - } - - Array createArray(size_t length) override { - return plain_.createArray(length); - } - ArrayBuffer createArrayBuffer( - std::shared_ptr buffer) override { - return plain_.createArrayBuffer(std::move(buffer)); - } - size_t size(const Array& a) override { - return plain_.size(a); - } - size_t size(const ArrayBuffer& ab) override { - return plain_.size(ab); - } - uint8_t* data(const ArrayBuffer& ab) override { - return plain_.data(ab); - } - Value getValueAtIndex(const Array& a, size_t i) override { - return plain_.getValueAtIndex(a, i); - } - void setValueAtIndexImpl(const Array& a, size_t i, const Value& value) - override { - plain_.setValueAtIndexImpl(a, i, value); - } - - Function createFunctionFromHostFunction( - const PropNameID& name, - unsigned int paramCount, - HostFunctionType func) override { - return plain_.createFunctionFromHostFunction( - name, paramCount, DecoratedHostFunction(*this, std::move(func))); - } - Value call( - const Function& f, - const Value& jsThis, - const Value* args, - size_t count) override { - return plain_.call(f, jsThis, args, count); - } - Value callAsConstructor(const Function& f, const Value* args, size_t count) - override { - return plain_.callAsConstructor(f, args, count); - } - - void setRuntimeDataImpl( - const UUID& uuid, - const void* data, - void (*deleter)(const void* data)) override { - return plain_.setRuntimeDataImpl(uuid, data, deleter); - } - - const void* getRuntimeDataImpl(const UUID& uuid) override { - return plain_.getRuntimeDataImpl(uuid); - } - - // Private data for managing scopes. - Runtime::ScopeState* pushScope() override { - return plain_.pushScope(); - } - void popScope(Runtime::ScopeState* ss) override { - plain_.popScope(ss); - } - - bool strictEquals(const Symbol& a, const Symbol& b) const override { - return plain_.strictEquals(a, b); - } - bool strictEquals(const BigInt& a, const BigInt& b) const override { - return plain_.strictEquals(a, b); - } - bool strictEquals(const String& a, const String& b) const override { - return plain_.strictEquals(a, b); - } - bool strictEquals(const Object& a, const Object& b) const override { - return plain_.strictEquals(a, b); - } - - bool instanceOf(const Object& o, const Function& f) override { - return plain_.instanceOf(o, f); - } - - // jsi::Instrumentation methods - - std::string getRecordedGCStats() override { - return plain().instrumentation().getRecordedGCStats(); - } - - std::unordered_map getHeapInfo( - bool includeExpensive) override { - return plain().instrumentation().getHeapInfo(includeExpensive); - } - - void collectGarbage(std::string cause) override { - plain().instrumentation().collectGarbage(std::move(cause)); - } - - void startTrackingHeapObjectStackTraces( - std::function)> callback) override { - plain().instrumentation().startTrackingHeapObjectStackTraces( - std::move(callback)); - } - - void stopTrackingHeapObjectStackTraces() override { - plain().instrumentation().stopTrackingHeapObjectStackTraces(); - } - - void startHeapSampling(size_t samplingInterval) override { - plain().instrumentation().startHeapSampling(samplingInterval); - } - - void stopHeapSampling(std::ostream& os) override { - plain().instrumentation().stopHeapSampling(os); - } - - void createSnapshotToFile( - const std::string& path, - const HeapSnapshotOptions& options) override { - plain().instrumentation().createSnapshotToFile(path, options); - } - - void createSnapshotToStream( - std::ostream& os, - const HeapSnapshotOptions& options) override { - plain().instrumentation().createSnapshotToStream(os, options); - } - - std::string flushAndDisableBridgeTrafficTrace() override { - return const_cast(plain()) - .instrumentation() - .flushAndDisableBridgeTrafficTrace(); - } - - void writeBasicBlockProfileTraceToFile( - const std::string& fileName) const override { - const_cast(plain()) - .instrumentation() - .writeBasicBlockProfileTraceToFile(fileName); - } - - void dumpOpcodeStats(std::ostream& os) const override { - const_cast(plain()).instrumentation().dumpOpcodeStats(os); - } - - /// Dump external profiler symbols to the given file name. - void dumpProfilerSymbolsToFile(const std::string& fileName) const override { - const_cast(plain()).instrumentation().dumpProfilerSymbolsToFile( - fileName); - } - - private: - Plain& plain_; -}; - -namespace detail { - -// This metaprogramming allows the With type's methods to be -// optional. - -template -struct BeforeCaller { - static void before(T&) {} -}; - -template -struct AfterCaller { - static void after(T&) {} -}; - -// decltype((void)&...) is either SFINAE, or void. -// So, if SFINAE does not happen for T, then this specialization exists -// for BeforeCaller, and always applies. If not, only the -// default above exists, and that is used instead. -template -struct BeforeCaller { - static void before(T& t) { - t.before(); - } -}; - -template -struct AfterCaller { - static void after(T& t) { - t.after(); - } -}; - -// It's possible to use multiple decorators by nesting -// WithRuntimeDecorator<...>, but this specialization allows use of -// std::tuple of decorator classes instead. See testlib.cpp for an -// example. -template -struct BeforeCaller> { - static void before(std::tuple& tuple) { - all_before<0, T...>(tuple); - } - - private: - template - static void all_before(std::tuple& tuple) { - detail::BeforeCaller::before(std::get(tuple)); - all_before(tuple); - } - - template - static void all_before(std::tuple&) {} -}; - -template -struct AfterCaller> { - static void after(std::tuple& tuple) { - all_after<0, T...>(tuple); - } - - private: - template - static void all_after(std::tuple& tuple) { - all_after(tuple); - detail::AfterCaller::after(std::get(tuple)); - } - - template - static void all_after(std::tuple&) {} -}; - -} // namespace detail - -// A decorator which implements an around idiom. A With instance is -// RAII constructed before each call to the undecorated class; the -// ctor is passed a single argument of type WithArg&. Plain and Base -// are used as in the base class. -template -class WithRuntimeDecorator : public RuntimeDecorator { - public: - using RD = RuntimeDecorator; - - // The reference arguments to the ctor are stored, but not used by - // the ctor, and there is no ctor, so they can be passed members of - // the derived class. - WithRuntimeDecorator(Plain& plain, With& with) : RD(plain), with_(with) {} - - ICast* castInterface(const UUID& interfaceUUID) override { - Around around{with_}; - return RD::castInterface(interfaceUUID); - } - - Value evaluateJavaScript( - const std::shared_ptr& buffer, - const std::string& sourceURL) override { - Around around{with_}; - return RD::evaluateJavaScript(buffer, sourceURL); - } - std::shared_ptr prepareJavaScript( - const std::shared_ptr& buffer, - std::string sourceURL) override { - Around around{with_}; - return RD::prepareJavaScript(buffer, std::move(sourceURL)); - } - Value evaluatePreparedJavaScript( - const std::shared_ptr& js) override { - Around around{with_}; - return RD::evaluatePreparedJavaScript(js); - } - void queueMicrotask(const Function& callback) override { - Around around{with_}; - RD::queueMicrotask(callback); - } - bool drainMicrotasks(int maxMicrotasksHint) override { - Around around{with_}; - return RD::drainMicrotasks(maxMicrotasksHint); - } - Object global() override { - Around around{with_}; - return RD::global(); - } - std::string description() override { - Around around{with_}; - return RD::description(); - } - bool isInspectable() override { - Around around{with_}; - return RD::isInspectable(); - } - - // The jsi:: prefix is necessary because MSVC compiler complains C2247: - // Instrumentation is not accessible because RuntimeDecorator uses private - // to inherit from Instrumentation. - // TODO(T40821815) Consider removing this workaround when updating MSVC - jsi::Instrumentation& instrumentation() override { - Around around{with_}; - return RD::instrumentation(); - } - - protected: - Runtime::PointerValue* cloneSymbol(const Runtime::PointerValue* pv) override { - Around around{with_}; - return RD::cloneSymbol(pv); - } - Runtime::PointerValue* cloneBigInt(const Runtime::PointerValue* pv) override { - Around around{with_}; - return RD::cloneBigInt(pv); - } - Runtime::PointerValue* cloneString(const Runtime::PointerValue* pv) override { - Around around{with_}; - return RD::cloneString(pv); - } - Runtime::PointerValue* cloneObject(const Runtime::PointerValue* pv) override { - Around around{with_}; - return RD::cloneObject(pv); - } - Runtime::PointerValue* clonePropNameID( - const Runtime::PointerValue* pv) override { - Around around{with_}; - return RD::clonePropNameID(pv); - } - - PropNameID createPropNameIDFromAscii(const char* str, size_t length) - override { - Around around{with_}; - return RD::createPropNameIDFromAscii(str, length); - } - PropNameID createPropNameIDFromUtf8(const uint8_t* utf8, size_t length) - override { - Around around{with_}; - return RD::createPropNameIDFromUtf8(utf8, length); - } - PropNameID createPropNameIDFromUtf16(const char16_t* utf16, size_t length) - override { - Around around{with_}; - return RD::createPropNameIDFromUtf16(utf16, length); - } - PropNameID createPropNameIDFromString(const String& str) override { - Around around{with_}; - return RD::createPropNameIDFromString(str); - } - PropNameID createPropNameIDFromSymbol(const Symbol& sym) override { - Around around{with_}; - return RD::createPropNameIDFromSymbol(sym); - } - std::string utf8(const PropNameID& id) override { - Around around{with_}; - return RD::utf8(id); - } - bool compare(const PropNameID& a, const PropNameID& b) override { - Around around{with_}; - return RD::compare(a, b); - } - - std::string symbolToString(const Symbol& sym) override { - Around around{with_}; - return RD::symbolToString(sym); - } - - BigInt createBigIntFromInt64(int64_t i) override { - Around around{with_}; - return RD::createBigIntFromInt64(i); - } - BigInt createBigIntFromUint64(uint64_t i) override { - Around around{with_}; - return RD::createBigIntFromUint64(i); - } - bool bigintIsInt64(const BigInt& bi) override { - Around around{with_}; - return RD::bigintIsInt64(bi); - } - bool bigintIsUint64(const BigInt& bi) override { - Around around{with_}; - return RD::bigintIsUint64(bi); - } - uint64_t truncate(const BigInt& bi) override { - Around around{with_}; - return RD::truncate(bi); - } - String bigintToString(const BigInt& bi, int i) override { - Around around{with_}; - return RD::bigintToString(bi, i); - } - - String createStringFromAscii(const char* str, size_t length) override { - Around around{with_}; - return RD::createStringFromAscii(str, length); - } - String createStringFromUtf8(const uint8_t* utf8, size_t length) override { - Around around{with_}; - return RD::createStringFromUtf8(utf8, length); - } - String createStringFromUtf16(const char16_t* utf16, size_t length) override { - Around around{with_}; - return RD::createStringFromUtf16(utf16, length); - } - std::string utf8(const String& s) override { - Around around{with_}; - return RD::utf8(s); - } - - std::u16string utf16(const String& str) override { - Around around{with_}; - return RD::utf16(str); - } - std::u16string utf16(const PropNameID& sym) override { - Around around{with_}; - return RD::utf16(sym); - } - - void getStringData( - const jsi::String& str, - void* ctx, - void ( - *cb)(void* ctx, bool ascii, const void* data, size_t num)) override { - Around around{with_}; - RD::getStringData(str, ctx, cb); - } - - void getPropNameIdData( - const jsi::PropNameID& sym, - void* ctx, - void ( - *cb)(void* ctx, bool ascii, const void* data, size_t num)) override { - Around around{with_}; - RD::getPropNameIdData(sym, ctx, cb); - } - - Value createValueFromJsonUtf8(const uint8_t* json, size_t length) override { - Around around{with_}; - return RD::createValueFromJsonUtf8(json, length); - } - - Object createObjectWithPrototype(const Value& prototype) override { - Around around{with_}; - return RD::createObjectWithPrototype(prototype); - } - - Object createObject() override { - Around around{with_}; - return RD::createObject(); - } - Object createObject(std::shared_ptr ho) override { - Around around{with_}; - return RD::createObject(std::move(ho)); - } - std::shared_ptr getHostObject(const jsi::Object& o) override { - Around around{with_}; - return RD::getHostObject(o); - } - HostFunctionType& getHostFunction(const jsi::Function& f) override { - Around around{with_}; - return RD::getHostFunction(f); - } - - bool hasNativeState(const Object& o) override { - Around around{with_}; - return RD::hasNativeState(o); - } - std::shared_ptr getNativeState(const Object& o) override { - Around around{with_}; - return RD::getNativeState(o); - } - void setNativeState(const Object& o, std::shared_ptr state) - override { - Around around{with_}; - RD::setNativeState(o, state); - } - - void setPrototypeOf(const Object& object, const Value& prototype) override { - Around around{with_}; - RD::setPrototypeOf(object, prototype); - } - - Value getPrototypeOf(const Object& object) override { - Around around{with_}; - return RD::getPrototypeOf(object); - } - - Value getProperty(const Object& o, const PropNameID& name) override { - Around around{with_}; - return RD::getProperty(o, name); - } - Value getProperty(const Object& o, const String& name) override { - Around around{with_}; - return RD::getProperty(o, name); - } - Value getProperty(const Object& o, const Value& name) override { - Around around{with_}; - return RD::getProperty(o, name); - } - bool hasProperty(const Object& o, const PropNameID& name) override { - Around around{with_}; - return RD::hasProperty(o, name); - } - bool hasProperty(const Object& o, const String& name) override { - Around around{with_}; - return RD::hasProperty(o, name); - } - bool hasProperty(const Object& o, const Value& name) override { - Around around{with_}; - return RD::hasProperty(o, name); - } - void setPropertyValue( - const Object& o, - const PropNameID& name, - const Value& value) override { - Around around{with_}; - RD::setPropertyValue(o, name, value); - } - void setPropertyValue(const Object& o, const String& name, const Value& value) - override { - Around around{with_}; - RD::setPropertyValue(o, name, value); - } - void setPropertyValue(const Object& o, const Value& name, const Value& value) - override { - Around around{with_}; - RD::setPropertyValue(o, name, value); - } - - void deleteProperty(const Object& object, const PropNameID& name) override { - Around around{with_}; - RD::deleteProperty(object, name); - } - - void deleteProperty(const Object& object, const String& name) override { - Around around{with_}; - RD::deleteProperty(object, name); - } - - void deleteProperty(const Object& object, const Value& name) override { - Around around{with_}; - RD::deleteProperty(object, name); - } - - bool isArray(const Object& o) const override { - Around around{with_}; - return RD::isArray(o); - } - bool isArrayBuffer(const Object& o) const override { - Around around{with_}; - return RD::isArrayBuffer(o); - } - bool isFunction(const Object& o) const override { - Around around{with_}; - return RD::isFunction(o); - } - bool isHostObject(const jsi::Object& o) const override { - Around around{with_}; - return RD::isHostObject(o); - } - bool isHostFunction(const jsi::Function& f) const override { - Around around{with_}; - return RD::isHostFunction(f); - } - Array getPropertyNames(const Object& o) override { - Around around{with_}; - return RD::getPropertyNames(o); - } - - WeakObject createWeakObject(const Object& o) override { - Around around{with_}; - return RD::createWeakObject(o); - } - Value lockWeakObject(const WeakObject& wo) override { - Around around{with_}; - return RD::lockWeakObject(wo); - } - - Array createArray(size_t length) override { - Around around{with_}; - return RD::createArray(length); - } - ArrayBuffer createArrayBuffer( - std::shared_ptr buffer) override { - return RD::createArrayBuffer(std::move(buffer)); - } - size_t size(const Array& a) override { - Around around{with_}; - return RD::size(a); - } - size_t size(const ArrayBuffer& ab) override { - Around around{with_}; - return RD::size(ab); - } - uint8_t* data(const ArrayBuffer& ab) override { - Around around{with_}; - return RD::data(ab); - } - Value getValueAtIndex(const Array& a, size_t i) override { - Around around{with_}; - return RD::getValueAtIndex(a, i); - } - void setValueAtIndexImpl(const Array& a, size_t i, const Value& value) - override { - Around around{with_}; - RD::setValueAtIndexImpl(a, i, value); - } - - Function createFunctionFromHostFunction( - const PropNameID& name, - unsigned int paramCount, - HostFunctionType func) override { - Around around{with_}; - return RD::createFunctionFromHostFunction( - name, paramCount, std::move(func)); - } - Value call( - const Function& f, - const Value& jsThis, - const Value* args, - size_t count) override { - Around around{with_}; - return RD::call(f, jsThis, args, count); - } - Value callAsConstructor(const Function& f, const Value* args, size_t count) - override { - Around around{with_}; - return RD::callAsConstructor(f, args, count); - } - - // Private data for managing scopes. - Runtime::ScopeState* pushScope() override { - Around around{with_}; - return RD::pushScope(); - } - void popScope(Runtime::ScopeState* ss) override { - Around around{with_}; - RD::popScope(ss); - } - - bool strictEquals(const Symbol& a, const Symbol& b) const override { - Around around{with_}; - return RD::strictEquals(a, b); - } - bool strictEquals(const BigInt& a, const BigInt& b) const override { - Around around{with_}; - return RD::strictEquals(a, b); - } - - bool strictEquals(const String& a, const String& b) const override { - Around around{with_}; - return RD::strictEquals(a, b); - } - bool strictEquals(const Object& a, const Object& b) const override { - Around around{with_}; - return RD::strictEquals(a, b); - } - - bool instanceOf(const Object& o, const Function& f) override { - Around around{with_}; - return RD::instanceOf(o, f); - } - - void setExternalMemoryPressure(const jsi::Object& obj, size_t amount) - override { - Around around{with_}; - RD::setExternalMemoryPressure(obj, amount); - } - - void setRuntimeDataImpl( - const UUID& uuid, - const void* data, - void (*deleter)(const void* data)) override { - Around around{with_}; - RD::setRuntimeDataImpl(uuid, data, deleter); - } - - const void* getRuntimeDataImpl(const UUID& uuid) override { - Around around{with_}; - return RD::getRuntimeDataImpl(uuid); - } - - private: - // Wrap an RAII type around With& to guarantee after always happens. - struct Around { - Around(With& with) : with_(with) { - detail::BeforeCaller::before(with_); - } - ~Around() { - detail::AfterCaller::after(with_); - } - - With& with_; - }; - - With& with_; -}; - -} // namespace jsi -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/instrumentation.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/instrumentation.h deleted file mode 100644 index 4a88951f..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/instrumentation.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include -#include - -#include - -namespace facebook { -namespace jsi { - -/// Methods for starting and collecting instrumentation, an \c Instrumentation -/// instance is associated with a particular \c Runtime instance, which it -/// controls the instrumentation of. -/// None of these functions should return newly created jsi values, nor should -/// it modify the values of any jsi values in the heap (although GCs are fine). -class JSI_EXPORT Instrumentation { - public: - /// Additional options controlling what to include when capturing a heap - /// snapshot. - struct HeapSnapshotOptions { - bool captureNumericValue{false}; - }; - - virtual ~Instrumentation() = default; - - /// Returns GC statistics as a JSON-encoded string, with an object containing - /// "type" and "version" fields outermost. "type" is a string, unique to a - /// particular implementation of \c jsi::Instrumentation, and "version" is a - /// number to indicate any revision to that implementation and its output - /// format. - /// - /// \pre This call can only be made on the instrumentation instance of a - /// runtime initialised to collect GC statistics. - /// - /// \post All cumulative measurements mentioned in the output are accumulated - /// across the entire lifetime of the Runtime. - /// - /// \return the GC statistics collected so far, as a JSON-encoded string. - virtual std::string getRecordedGCStats() = 0; - - /// Request statistics about the current state of the runtime's heap. This - /// function can be called at any time, and should produce information that is - /// correct at the instant it is called (i.e, not stale). - /// - /// \return a map from a string key to a number associated with that - /// statistic. - virtual std::unordered_map getHeapInfo( - bool includeExpensive) = 0; - - /// Perform a full garbage collection. - /// \param cause The cause of this collection, as it should be reported in - /// logs. - virtual void collectGarbage(std::string cause) = 0; - - /// A HeapStatsUpdate is a tuple of the fragment index, the number of objects - /// in that fragment, and the number of bytes used by those objects. - /// A "fragment" is a view of all objects allocated within a time slice. - using HeapStatsUpdate = std::tuple; - - /// Start capturing JS stack-traces for all JS heap allocated objects. These - /// can be accessed via \c ::createSnapshotToFile(). - /// \param fragmentCallback If present, invoke this callback every so often - /// with the most recently seen object ID, and a list of fragments that have - /// been updated. This callback will be invoked on the same thread that the - /// runtime is using. - virtual void startTrackingHeapObjectStackTraces( - std::function stats)> fragmentCallback) = 0; - - /// Stop capture JS stack-traces for JS heap allocated objects. - virtual void stopTrackingHeapObjectStackTraces() = 0; - - /// Start a heap sampling profiler that will sample heap allocations, and the - /// stack trace they were allocated at. Reports a summary of which functions - /// allocated the most. - /// \param samplingInterval The number of bytes allocated to wait between - /// samples. This will be used as the expected value of a poisson - /// distribution. - virtual void startHeapSampling(size_t samplingInterval) = 0; - - /// Turns off the heap sampling profiler previously enabled via - /// \c startHeapSampling. Writes the output of the sampling heap profiler to - /// \p os. The output is a JSON formatted string. - virtual void stopHeapSampling(std::ostream& os) = 0; - - /// Captures the heap to a file - /// - /// \param path to save the heap capture. - /// \param options additional options for what to capture. - virtual void createSnapshotToFile( - const std::string& path, - const HeapSnapshotOptions& options = {false}) = 0; - - /// Captures the heap to an output stream - /// - /// \param os output stream to write to. - /// \param options additional options for what to capture. - virtual void createSnapshotToStream( - std::ostream& os, - const HeapSnapshotOptions& options = {false}) = 0; - - /// If the runtime has been created to trace to a temp file, flush - /// any unwritten parts of the trace of bridge traffic to the file, - /// and return the name of the file. Otherwise, return the empty string. - /// Tracing is disabled after this call. - virtual std::string flushAndDisableBridgeTrafficTrace() = 0; - - /// Write basic block profile trace to the given file name. - virtual void writeBasicBlockProfileTraceToFile( - const std::string& fileName) const = 0; - - /// Write the opcode stats to the given stream. - virtual void dumpOpcodeStats(std::ostream& os) const = 0; - - /// Dump external profiler symbols to the given file name. - virtual void dumpProfilerSymbolsToFile(const std::string& fileName) const = 0; -}; - -} // namespace jsi -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/jsi-inl.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/jsi-inl.h deleted file mode 100644 index 2f70a594..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/jsi-inl.h +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -namespace facebook { -namespace jsi { -namespace detail { - -inline Value toValue(Runtime&, std::nullptr_t) { - return Value::null(); -} -inline Value toValue(Runtime&, bool b) { - return Value(b); -} -inline Value toValue(Runtime&, double d) { - return Value(d); -} -inline Value toValue(Runtime&, float f) { - return Value(static_cast(f)); -} -inline Value toValue(Runtime&, int i) { - return Value(i); -} -inline Value toValue(Runtime& runtime, const char* str) { - return String::createFromAscii(runtime, str); -} -inline Value toValue(Runtime& runtime, const std::string& str) { - return String::createFromUtf8(runtime, str); -} -template -inline Value toValue(Runtime& runtime, const T& other) { - static_assert( - std::is_base_of::value, - "This type cannot be converted to Value"); - return Value(runtime, other); -} -inline Value toValue(Runtime& runtime, const Value& value) { - return Value(runtime, value); -} -inline Value&& toValue(Runtime&, Value&& value) { - return std::move(value); -} - -inline PropNameID toPropNameID(Runtime& runtime, const char* name) { - return PropNameID::forAscii(runtime, name); -} -inline PropNameID toPropNameID(Runtime& runtime, const std::string& name) { - return PropNameID::forUtf8(runtime, name); -} -inline PropNameID&& toPropNameID(Runtime&, PropNameID&& name) { - return std::move(name); -} - -/// Helper to throw while still compiling with exceptions turned off. -template -[[noreturn]] inline void throwOrDie(Args&&... args) { - std::rethrow_exception( - std::make_exception_ptr(E{std::forward(args)...})); -} - -} // namespace detail - -template -inline T Runtime::make(Runtime::PointerValue* pv) { - return T(pv); -} - -inline Runtime::PointerValue* Runtime::getPointerValue(jsi::Pointer& pointer) { - return pointer.ptr_; -} - -inline const Runtime::PointerValue* Runtime::getPointerValue( - const jsi::Pointer& pointer) { - return pointer.ptr_; -} - -inline const Runtime::PointerValue* Runtime::getPointerValue( - const jsi::Value& value) { - return value.data_.pointer.ptr_; -} - -inline void Runtime::setRuntimeData( - const UUID& uuid, - const std::shared_ptr& data) { - auto* dataPtr = new std::shared_ptr(data); - setRuntimeDataImpl(uuid, dataPtr, [](const void* data) { - delete (const std::shared_ptr*)data; - }); -} - -inline std::shared_ptr Runtime::getRuntimeData(const UUID& uuid) { - auto* data = (const std::shared_ptr*)getRuntimeDataImpl(uuid); - return data ? *data : nullptr; -} - -Value Object::getPrototype(Runtime& runtime) const { - return runtime.getPrototypeOf(*this); -} - -inline Value Object::getProperty(Runtime& runtime, const char* name) const { - return getProperty(runtime, String::createFromAscii(runtime, name)); -} - -inline Value Object::getProperty(Runtime& runtime, const String& name) const { - return runtime.getProperty(*this, name); -} - -inline Value Object::getProperty(Runtime& runtime, const PropNameID& name) - const { - return runtime.getProperty(*this, name); -} - -inline Value Object::getProperty(Runtime& runtime, const Value& name) const { - return runtime.getProperty(*this, name); -} - -inline bool Object::hasProperty(Runtime& runtime, const char* name) const { - return hasProperty(runtime, String::createFromAscii(runtime, name)); -} - -inline bool Object::hasProperty(Runtime& runtime, const String& name) const { - return runtime.hasProperty(*this, name); -} - -inline bool Object::hasProperty(Runtime& runtime, const PropNameID& name) - const { - return runtime.hasProperty(*this, name); -} - -inline bool Object::hasProperty(Runtime& runtime, const Value& name) const { - return runtime.hasProperty(*this, name); -} - -template -void Object::setProperty(Runtime& runtime, const char* name, T&& value) const { - setProperty( - runtime, String::createFromAscii(runtime, name), std::forward(value)); -} - -template -void Object::setProperty(Runtime& runtime, const String& name, T&& value) - const { - setPropertyValue( - runtime, name, detail::toValue(runtime, std::forward(value))); -} - -template -void Object::setProperty(Runtime& runtime, const PropNameID& name, T&& value) - const { - setPropertyValue( - runtime, name, detail::toValue(runtime, std::forward(value))); -} - -template -void Object::setProperty(Runtime& runtime, const Value& name, T&& value) const { - setPropertyValue( - runtime, name, detail::toValue(runtime, std::forward(value))); -} - -inline void Object::deleteProperty(Runtime& runtime, const char* name) const { - deleteProperty(runtime, String::createFromAscii(runtime, name)); -} - -inline void Object::deleteProperty(Runtime& runtime, const String& name) const { - runtime.deleteProperty(*this, name); -} - -inline void Object::deleteProperty(Runtime& runtime, const PropNameID& name) - const { - runtime.deleteProperty(*this, name); -} - -inline void Object::deleteProperty(Runtime& runtime, const Value& name) const { - runtime.deleteProperty(*this, name); -} - -inline Array Object::getArray(Runtime& runtime) const& { - assert(runtime.isArray(*this)); - (void)runtime; // when assert is disabled we need to mark this as used - return Array(runtime.cloneObject(ptr_)); -} - -inline Array Object::getArray(Runtime& runtime) && { - assert(runtime.isArray(*this)); - (void)runtime; // when assert is disabled we need to mark this as used - Runtime::PointerValue* value = ptr_; - ptr_ = nullptr; - return Array(value); -} - -inline ArrayBuffer Object::getArrayBuffer(Runtime& runtime) const& { - assert(runtime.isArrayBuffer(*this)); - (void)runtime; // when assert is disabled we need to mark this as used - return ArrayBuffer(runtime.cloneObject(ptr_)); -} - -inline ArrayBuffer Object::getArrayBuffer(Runtime& runtime) && { - assert(runtime.isArrayBuffer(*this)); - (void)runtime; // when assert is disabled we need to mark this as used - Runtime::PointerValue* value = ptr_; - ptr_ = nullptr; - return ArrayBuffer(value); -} - -inline Function Object::getFunction(Runtime& runtime) const& { - assert(runtime.isFunction(*this)); - return Function(runtime.cloneObject(ptr_)); -} - -inline Function Object::getFunction(Runtime& runtime) && { - assert(runtime.isFunction(*this)); - (void)runtime; // when assert is disabled we need to mark this as used - Runtime::PointerValue* value = ptr_; - ptr_ = nullptr; - return Function(value); -} - -template -inline bool Object::isHostObject(Runtime& runtime) const { - return runtime.isHostObject(*this) && - std::dynamic_pointer_cast(runtime.getHostObject(*this)); -} - -template <> -inline bool Object::isHostObject(Runtime& runtime) const { - return runtime.isHostObject(*this); -} - -template -inline std::shared_ptr Object::getHostObject(Runtime& runtime) const { - assert(isHostObject(runtime)); - return std::static_pointer_cast(runtime.getHostObject(*this)); -} - -template -inline std::shared_ptr Object::asHostObject(Runtime& runtime) const { - if (!isHostObject(runtime)) { - detail::throwOrDie( - "Object is not a HostObject of desired type"); - } - return std::static_pointer_cast(runtime.getHostObject(*this)); -} - -template <> -inline std::shared_ptr Object::getHostObject( - Runtime& runtime) const { - assert(runtime.isHostObject(*this)); - return runtime.getHostObject(*this); -} - -template -inline bool Object::hasNativeState(Runtime& runtime) const { - return runtime.hasNativeState(*this) && - std::dynamic_pointer_cast(runtime.getNativeState(*this)); -} - -template <> -inline bool Object::hasNativeState(Runtime& runtime) const { - return runtime.hasNativeState(*this); -} - -template -inline std::shared_ptr Object::getNativeState(Runtime& runtime) const { - assert(hasNativeState(runtime)); - return std::static_pointer_cast(runtime.getNativeState(*this)); -} - -inline void Object::setNativeState( - Runtime& runtime, - std::shared_ptr state) const { - runtime.setNativeState(*this, state); -} - -inline void Object::setExternalMemoryPressure(Runtime& runtime, size_t amt) - const { - runtime.setExternalMemoryPressure(*this, amt); -} - -inline Array Object::getPropertyNames(Runtime& runtime) const { - return runtime.getPropertyNames(*this); -} - -inline Value WeakObject::lock(Runtime& runtime) const { - return runtime.lockWeakObject(*this); -} - -template -void Array::setValueAtIndex(Runtime& runtime, size_t i, T&& value) const { - setValueAtIndexImpl( - runtime, i, detail::toValue(runtime, std::forward(value))); -} - -inline Value Array::getValueAtIndex(Runtime& runtime, size_t i) const { - return runtime.getValueAtIndex(*this, i); -} - -inline Function Function::createFromHostFunction( - Runtime& runtime, - const jsi::PropNameID& name, - unsigned int paramCount, - jsi::HostFunctionType func) { - return runtime.createFunctionFromHostFunction( - name, paramCount, std::move(func)); -} - -inline Value Function::call(Runtime& runtime, const Value* args, size_t count) - const { - return runtime.call(*this, Value::undefined(), args, count); -} - -inline Value Function::call(Runtime& runtime, std::initializer_list args) - const { - return call(runtime, args.begin(), args.size()); -} - -template -inline Value Function::call(Runtime& runtime, Args&&... args) const { - // A more awesome version of this would be able to create raw values - // which can be used directly without wrapping and unwrapping, but - // this will do for now. - return call(runtime, {detail::toValue(runtime, std::forward(args))...}); -} - -inline Value Function::callWithThis( - Runtime& runtime, - const Object& jsThis, - const Value* args, - size_t count) const { - return runtime.call(*this, Value(runtime, jsThis), args, count); -} - -inline Value Function::callWithThis( - Runtime& runtime, - const Object& jsThis, - std::initializer_list args) const { - return callWithThis(runtime, jsThis, args.begin(), args.size()); -} - -template -inline Value Function::callWithThis( - Runtime& runtime, - const Object& jsThis, - Args&&... args) const { - // A more awesome version of this would be able to create raw values - // which can be used directly without wrapping and unwrapping, but - // this will do for now. - return callWithThis( - runtime, jsThis, {detail::toValue(runtime, std::forward(args))...}); -} - -template -inline Array Array::createWithElements(Runtime& runtime, Args&&... args) { - return createWithElements( - runtime, {detail::toValue(runtime, std::forward(args))...}); -} - -template -inline std::vector PropNameID::names( - Runtime& runtime, - Args&&... args) { - return names({detail::toPropNameID(runtime, std::forward(args))...}); -} - -template -inline std::vector PropNameID::names( - PropNameID (&&propertyNames)[N]) { - std::vector result; - result.reserve(N); - for (auto& name : propertyNames) { - result.push_back(std::move(name)); - } - return result; -} - -inline Value Function::callAsConstructor( - Runtime& runtime, - const Value* args, - size_t count) const { - return runtime.callAsConstructor(*this, args, count); -} - -inline Value Function::callAsConstructor( - Runtime& runtime, - std::initializer_list args) const { - return callAsConstructor(runtime, args.begin(), args.size()); -} - -template -inline Value Function::callAsConstructor(Runtime& runtime, Args&&... args) - const { - return callAsConstructor( - runtime, {detail::toValue(runtime, std::forward(args))...}); -} - -String BigInt::toString(Runtime& runtime, int radix) const { - return runtime.bigintToString(*this, radix); -} - -} // namespace jsi -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/jsi.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/jsi.h deleted file mode 100644 index 08edcd2a..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/jsi.h +++ /dev/null @@ -1,1864 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#ifndef JSI_EXPORT -#ifdef _MSC_VER -#ifdef CREATE_SHARED_LIBRARY -#define JSI_EXPORT __declspec(dllexport) -#else -#define JSI_EXPORT -#endif // CREATE_SHARED_LIBRARY -#else // _MSC_VER -#define JSI_EXPORT __attribute__((visibility("default"))) -#endif // _MSC_VER -#endif // !defined(JSI_EXPORT) - -class FBJSRuntime; -namespace facebook { -namespace jsi { - -/// UUID version 1 implementation. This should be constructed with constant -/// arguments to identify fixed UUIDs. -class JSI_EXPORT UUID { - public: - // Construct from raw parts - constexpr UUID( - uint32_t timeLow, - uint16_t timeMid, - uint16_t timeHighAndVersion, - uint16_t variantAndClockSeq, - uint64_t node) - : high( - ((uint64_t)(timeLow) << 32) | ((uint64_t)(timeMid) << 16) | - ((uint64_t)(timeHighAndVersion))), - low(((uint64_t)(variantAndClockSeq) << 48) | node) {} - - // Default constructor (zero UUID) - constexpr UUID() : high(0), low(0) {} - - constexpr UUID(const UUID&) = default; - constexpr UUID& operator=(const UUID&) = default; - - constexpr bool operator==(const UUID& other) const { - return high == other.high && low == other.low; - } - constexpr bool operator!=(const UUID& other) const { - return !(*this == other); - } - - // Ordering (for std::map, sorting, etc.) - constexpr bool operator<(const UUID& other) const { - return (high < other.high) || (high == other.high && low < other.low); - } - - // Hash support for UUID (for unordered_map compatibility) - struct Hash { - std::size_t operator()(const UUID& uuid) const noexcept { - return std::hash{}(uuid.high) ^ - (std::hash{}(uuid.low) << 1); - } - }; - - // UUID format: 8-4-4-4-12 - std::string toString() const { - std::string buffer(36, ' '); - std::snprintf( - buffer.data(), - buffer.size() + 1, - "%08x-%04x-%04x-%04x-%012llx", - getTimeLow(), - getTimeMid(), - getTimeHighAndVersion(), - getVariantAndClockSeq(), - (unsigned long long)getNode()); - return buffer; - } - - constexpr uint32_t getTimeLow() const { - return (uint32_t)(high >> 32); - } - - constexpr uint16_t getTimeMid() const { - return (uint16_t)(high >> 16); - } - - constexpr uint16_t getTimeHighAndVersion() const { - return (uint16_t)high; - } - - constexpr uint16_t getVariantAndClockSeq() const { - return (uint16_t)(low >> 48); - } - - constexpr uint64_t getNode() const { - return low & 0xFFFFFFFFFFFF; - } - - private: - uint64_t high; - uint64_t low; -}; - -/// Base interface that all JSI interfaces inherit from. Users should not try to -/// manipulate this base type directly, and should use castInterface to get the -/// appropriate subtype. -struct JSI_EXPORT ICast { - /// If the current object can be cast into the interface specified by \p - /// interfaceUUID, return a pointer to the object. Otherwise, return a null - /// pointer. - /// The returned interface has the same lifetime as the underlying object. It - /// does not need to be released when not needed. - virtual ICast* castInterface(const UUID& interfaceUUID) = 0; - - protected: - /// Interfaces are not destructible, thus the destructor is intentionally - /// protected to prevent delete calls on the interface. - /// Additionally, the destructor is non-virtual to reduce the vtable - /// complexity from inheritance. - ~ICast() = default; -}; - -/// Base class for buffers of data or bytecode that need to be passed to the -/// runtime. The buffer is expected to be fully immutable, so the result of -/// size(), data(), and the contents of the pointer returned by data() must not -/// change after construction. -class JSI_EXPORT Buffer { - public: - virtual ~Buffer(); - virtual size_t size() const = 0; - virtual const uint8_t* data() const = 0; -}; - -class JSI_EXPORT StringBuffer : public Buffer { - public: - StringBuffer(std::string s) : s_(std::move(s)) {} - size_t size() const override { - return s_.size(); - } - const uint8_t* data() const override { - return reinterpret_cast(s_.data()); - } - - private: - std::string s_; -}; - -/// Base class for buffers of data that need to be passed to the runtime. The -/// result of size() and data() must not change after construction. However, the -/// region pointed to by data() may be modified by the user or the runtime. The -/// user must ensure that access to the contents of the buffer is properly -/// synchronised. -class JSI_EXPORT MutableBuffer { - public: - virtual ~MutableBuffer(); - virtual size_t size() const = 0; - virtual uint8_t* data() = 0; -}; - -/// PreparedJavaScript is a base class representing JavaScript which is in a -/// form optimized for execution, in a runtime-specific way. Construct one via -/// jsi::Runtime::prepareJavaScript(). -/// ** This is an experimental API that is subject to change. ** -class JSI_EXPORT PreparedJavaScript { - protected: - PreparedJavaScript() = default; - - public: - virtual ~PreparedJavaScript() = 0; -}; - -class Runtime; -class Pointer; -class PropNameID; -class Symbol; -class BigInt; -class String; -class Object; -class WeakObject; -class Array; -class ArrayBuffer; -class Function; -class Value; -class Instrumentation; -class Scope; -class JSIException; -class JSError; - -/// A function which has this type can be registered as a function -/// callable from JavaScript using Function::createFromHostFunction(). -/// When the function is called, args will point to the arguments, and -/// count will indicate how many arguments are passed. The function -/// can return a Value to the caller, or throw an exception. If a C++ -/// exception is thrown, a JS Error will be created and thrown into -/// JS; if the C++ exception extends std::exception, the Error's -/// message will be whatever what() returns. Note that it is undefined whether -/// HostFunctions may or may not be called in strict mode; that is `thisVal` -/// can be any value - it will not necessarily be coerced to an object or -/// or set to the global object. -using HostFunctionType = std::function< - Value(Runtime& rt, const Value& thisVal, const Value* args, size_t count)>; - -/// An object which implements this interface can be registered as an -/// Object with the JS runtime. -class JSI_EXPORT HostObject { - public: - // The C++ object's dtor will be called when the GC finalizes this - // object. (This may be as late as when the Runtime is shut down.) - // You have no control over which thread it is called on. This will - // be called from inside the GC, so it is unsafe to do any VM - // operations which require a Runtime&. Derived classes' dtors - // should also avoid doing anything expensive. Calling the dtor on - // a jsi object is explicitly ok. If you want to do JS operations, - // or any nontrivial work, you should add it to a work queue, and - // manage it externally. - virtual ~HostObject(); - - // When JS wants a property with a given name from the HostObject, - // it will call this method. If it throws an exception, the call - // will throw a JS \c Error object. By default this returns undefined. - // \return the value for the property. - virtual Value get(Runtime&, const PropNameID& name); - - // When JS wants to set a property with a given name on the HostObject, - // it will call this method. If it throws an exception, the call will - // throw a JS \c Error object. By default this throws a type error exception - // mimicking the behavior of a frozen object in strict mode. - virtual void set(Runtime&, const PropNameID& name, const Value& value); - - // When JS wants a list of property names for the HostObject, it will - // call this method. If it throws an exception, the call will throw a - // JS \c Error object. The default implementation returns empty vector. - virtual std::vector getPropertyNames(Runtime& rt); -}; - -/// Native state (and destructor) that can be attached to any JS object -/// using setNativeState. -class JSI_EXPORT NativeState { - public: - virtual ~NativeState(); -}; - -/// Represents a JS runtime. Movable, but not copyable. Note that -/// this object may not be thread-aware, but cannot be used safely from -/// multiple threads at once. The application is responsible for -/// ensuring that it is used safely. This could mean using the -/// Runtime from a single thread, using a mutex, doing all work on a -/// serial queue, etc. This restriction applies to the methods of -/// this class, and any method in the API which take a Runtime& as an -/// argument. Destructors (all but ~Scope), operators, or other methods -/// which do not take Runtime& as an argument are safe to call from any -/// thread, but it is still forbidden to make write operations on a single -/// instance of any class from more than one thread. In addition, to -/// make shutdown safe, destruction of objects associated with the Runtime -/// must be destroyed before the Runtime is destroyed, or from the -/// destructor of a managed HostObject or HostFunction. Informally, this -/// means that the main source of unsafe behavior is to hold a jsi object -/// in a non-Runtime-managed object, and not clean it up before the Runtime -/// is shut down. If your lifecycle is such that avoiding this is hard, -/// you will probably need to do use your own locks. -class JSI_EXPORT Runtime : public ICast { - public: - virtual ~Runtime(); - - ICast* castInterface(const UUID& interfaceUUID) override; - - /// Evaluates the given JavaScript \c buffer. \c sourceURL is used - /// to annotate the stack trace if there is an exception. The - /// contents may be utf8-encoded JS source code, or binary bytecode - /// whose format is specific to the implementation. If the input - /// format is unknown, or evaluation causes an error, a JSIException - /// will be thrown. - /// Note this function should ONLY be used when there isn't another means - /// through the JSI API. For example, it will be much slower to use this to - /// call a global function than using the JSI APIs to read the function - /// property from the global object and then calling it explicitly. - virtual Value evaluateJavaScript( - const std::shared_ptr& buffer, - const std::string& sourceURL) = 0; - - /// Prepares to evaluate the given JavaScript \c buffer by processing it into - /// a form optimized for execution. This may include pre-parsing, compiling, - /// etc. If the input is invalid (for example, cannot be parsed), a - /// JSIException will be thrown. The resulting object is tied to the - /// particular concrete type of Runtime from which it was created. It may be - /// used (via evaluatePreparedJavaScript) in any Runtime of the same concrete - /// type. - /// The PreparedJavaScript object may be passed to multiple VM instances, so - /// they can all share and benefit from the prepared script. - /// As with evaluateJavaScript(), using JavaScript code should be avoided - /// when the JSI API is sufficient. - virtual std::shared_ptr prepareJavaScript( - const std::shared_ptr& buffer, - std::string sourceURL) = 0; - - /// Evaluates a PreparedJavaScript. If evaluation causes an error, a - /// JSIException will be thrown. - /// As with evaluateJavaScript(), using JavaScript code should be avoided - /// when the JSI API is sufficient. - virtual Value evaluatePreparedJavaScript( - const std::shared_ptr& js) = 0; - - /// Queues a microtask in the JavaScript VM internal Microtask (a.k.a. Job in - /// ECMA262) queue, to be executed when the host drains microtasks in - /// its event loop implementation. - /// - /// \param callback a function to be executed as a microtask. - virtual void queueMicrotask(const jsi::Function& callback) = 0; - - /// Drain the JavaScript VM internal Microtask (a.k.a. Job in ECMA262) queue. - /// - /// \param maxMicrotasksHint a hint to tell an implementation that it should - /// make a best effort not execute more than the given number. It's default - /// to -1 for infinity (unbounded execution). - /// \return true if the queue is drained or false if there is more work to do. - /// - /// When there were exceptions thrown from the execution of microtasks, - /// implementations shall discard the exceptional jobs. An implementation may - /// \throw a \c JSError object to signal the hosts to handle. In that case, an - /// implementation may or may not suspend the draining. - /// - /// Hosts may call this function again to resume the draining if it was - /// suspended due to either exceptions or the \p maxMicrotasksHint bound. - /// E.g. a host may repetitively invoke this function until the queue is - /// drained to implement the "microtask checkpoint" defined in WHATWG HTML - /// event loop: https://html.spec.whatwg.org/C#perform-a-microtask-checkpoint. - /// - /// Note that error propagation is only a concern if a host needs to implement - /// `queueMicrotask`, a recent API that allows enqueueing arbitrary functions - /// (hence may throw) as microtasks. Exceptions from ECMA-262 Promise Jobs are - /// handled internally to VMs and are never propagated to hosts. - /// - /// This API offers some queue management to hosts at its best effort due to - /// different behaviors and limitations imposed by different VMs and APIs. By - /// the time this is written, An implementation may swallow exceptions (JSC), - /// may not pause (V8), and may not support bounded executions. - virtual bool drainMicrotasks(int maxMicrotasksHint = -1) = 0; - - /// \return the global object - virtual Object global() = 0; - - /// \return a short printable description of the instance. It should - /// at least include some human-readable indication of the runtime - /// implementation. This should only be used by logging, debugging, - /// and other developer-facing callers. - virtual std::string description() = 0; - - /// \return whether or not the underlying runtime supports debugging via the - /// Chrome remote debugging protocol. - /// - /// NOTE: the API for determining whether a runtime is debuggable and - /// registering a runtime with the debugger is still in flux, so please don't - /// use this API unless you know what you're doing. - virtual bool isInspectable() = 0; - - /// \return an interface to extract metrics from this \c Runtime. The default - /// implementation of this function returns an \c Instrumentation instance - /// which returns no metrics. - virtual Instrumentation& instrumentation(); - - /// Stores the pointer \p data with the \p uuid in the runtime. This can be - /// used to store some custom data within the runtime. When the runtime is - /// destroyed, or if an entry at an existing key is overwritten, the runtime - /// will release its ownership of the held object. - void setRuntimeData(const UUID& uuid, const std::shared_ptr& data); - - /// Returns the data associated with the \p uuid in the runtime. If there's no - /// data associated with the uuid, return a null pointer. - std::shared_ptr getRuntimeData(const UUID& uuid); - - protected: - friend class Pointer; - friend class PropNameID; - friend class Symbol; - friend class BigInt; - friend class String; - friend class Object; - friend class WeakObject; - friend class Array; - friend class ArrayBuffer; - friend class Function; - friend class Value; - friend class Scope; - friend class JSError; - - /// Stores the pointer \p data with the \p uuid in the runtime. This can be - /// used to store some custom data within the runtime. When the runtime is - /// destroyed, or if an entry at an existing key is overwritten, the runtime - /// will release its ownership by calling \p deleter. - virtual void setRuntimeDataImpl( - const UUID& uuid, - const void* data, - void (*deleter)(const void* data)); - - /// Returns the data associated with the \p uuid in the runtime. If there's no - /// data associated with the uuid, return a null pointer. - virtual const void* getRuntimeDataImpl(const UUID& uuid); - - // Potential optimization: avoid the cloneFoo() virtual dispatch, - // and instead just fix the number of fields, and copy them, since - // in practice they are trivially copyable. Sufficient use of - // rvalue arguments/methods would also reduce the number of clones. - - struct PointerValue { - virtual void invalidate() noexcept = 0; - - protected: - virtual ~PointerValue() = default; - }; - - virtual PointerValue* cloneSymbol(const Runtime::PointerValue* pv) = 0; - virtual PointerValue* cloneBigInt(const Runtime::PointerValue* pv) = 0; - virtual PointerValue* cloneString(const Runtime::PointerValue* pv) = 0; - virtual PointerValue* cloneObject(const Runtime::PointerValue* pv) = 0; - virtual PointerValue* clonePropNameID(const Runtime::PointerValue* pv) = 0; - - virtual PropNameID createPropNameIDFromAscii( - const char* str, - size_t length) = 0; - virtual PropNameID createPropNameIDFromUtf8( - const uint8_t* utf8, - size_t length) = 0; - virtual PropNameID createPropNameIDFromUtf16( - const char16_t* utf16, - size_t length); - virtual PropNameID createPropNameIDFromString(const String& str) = 0; - virtual PropNameID createPropNameIDFromSymbol(const Symbol& sym) = 0; - virtual std::string utf8(const PropNameID&) = 0; - virtual bool compare(const PropNameID&, const PropNameID&) = 0; - - virtual std::string symbolToString(const Symbol&) = 0; - - virtual BigInt createBigIntFromInt64(int64_t) = 0; - virtual BigInt createBigIntFromUint64(uint64_t) = 0; - virtual bool bigintIsInt64(const BigInt&) = 0; - virtual bool bigintIsUint64(const BigInt&) = 0; - virtual uint64_t truncate(const BigInt&) = 0; - virtual String bigintToString(const BigInt&, int) = 0; - - virtual String createStringFromAscii(const char* str, size_t length) = 0; - virtual String createStringFromUtf8(const uint8_t* utf8, size_t length) = 0; - virtual String createStringFromUtf16(const char16_t* utf16, size_t length); - virtual std::string utf8(const String&) = 0; - - // \return a \c Value created from a utf8-encoded JSON string. The default - // implementation creates a \c String and invokes JSON.parse. - virtual Value createValueFromJsonUtf8(const uint8_t* json, size_t length); - - virtual Object createObject() = 0; - virtual Object createObject(std::shared_ptr ho) = 0; - virtual std::shared_ptr getHostObject(const jsi::Object&) = 0; - virtual HostFunctionType& getHostFunction(const jsi::Function&) = 0; - - // Creates a new Object with the custom prototype - virtual Object createObjectWithPrototype(const Value& prototype); - - virtual bool hasNativeState(const jsi::Object&) = 0; - virtual std::shared_ptr getNativeState(const jsi::Object&) = 0; - virtual void setNativeState( - const jsi::Object&, - std::shared_ptr state) = 0; - - virtual void setPrototypeOf(const Object& object, const Value& prototype); - virtual Value getPrototypeOf(const Object& object); - - virtual Value getProperty(const Object&, const PropNameID& name) = 0; - virtual Value getProperty(const Object&, const String& name) = 0; - virtual Value getProperty(const Object&, const Value& name); - virtual bool hasProperty(const Object&, const PropNameID& name) = 0; - virtual bool hasProperty(const Object&, const String& name) = 0; - virtual bool hasProperty(const Object&, const Value& name); - virtual void setPropertyValue( - const Object&, - const PropNameID& name, - const Value& value) = 0; - virtual void - setPropertyValue(const Object&, const String& name, const Value& value) = 0; - virtual void - setPropertyValue(const Object&, const Value& name, const Value& value); - - virtual void deleteProperty(const Object&, const PropNameID& name); - virtual void deleteProperty(const Object&, const String& name); - virtual void deleteProperty(const Object&, const Value& name); - - virtual bool isArray(const Object&) const = 0; - virtual bool isArrayBuffer(const Object&) const = 0; - virtual bool isFunction(const Object&) const = 0; - virtual bool isHostObject(const jsi::Object&) const = 0; - virtual bool isHostFunction(const jsi::Function&) const = 0; - virtual Array getPropertyNames(const Object&) = 0; - - virtual WeakObject createWeakObject(const Object&) = 0; - virtual Value lockWeakObject(const WeakObject&) = 0; - - virtual Array createArray(size_t length) = 0; - virtual ArrayBuffer createArrayBuffer( - std::shared_ptr buffer) = 0; - virtual size_t size(const Array&) = 0; - virtual size_t size(const ArrayBuffer&) = 0; - virtual uint8_t* data(const ArrayBuffer&) = 0; - virtual Value getValueAtIndex(const Array&, size_t i) = 0; - virtual void - setValueAtIndexImpl(const Array&, size_t i, const Value& value) = 0; - - virtual Function createFunctionFromHostFunction( - const PropNameID& name, - unsigned int paramCount, - HostFunctionType func) = 0; - virtual Value call( - const Function&, - const Value& jsThis, - const Value* args, - size_t count) = 0; - virtual Value - callAsConstructor(const Function&, const Value* args, size_t count) = 0; - - // Private data for managing scopes. - struct ScopeState; - virtual ScopeState* pushScope(); - virtual void popScope(ScopeState*); - - virtual bool strictEquals(const Symbol& a, const Symbol& b) const = 0; - virtual bool strictEquals(const BigInt& a, const BigInt& b) const = 0; - virtual bool strictEquals(const String& a, const String& b) const = 0; - virtual bool strictEquals(const Object& a, const Object& b) const = 0; - - virtual bool instanceOf(const Object& o, const Function& f) = 0; - - /// See Object::setExternalMemoryPressure. - virtual void setExternalMemoryPressure( - const jsi::Object& obj, - size_t amount) = 0; - - virtual std::u16string utf16(const String& str); - virtual std::u16string utf16(const PropNameID& sym); - - /// Invokes the provided callback \p cb with the String content in \p str. - /// The callback must take in three arguments: bool ascii, const void* data, - /// and size_t num, respectively. \p ascii indicates whether the \p data - /// passed to the callback should be interpreted as a pointer to a sequence of - /// \p num ASCII characters or UTF16 characters. Depending on the internal - /// representation of the string, the function may invoke the callback - /// multiple times, with a different format on each invocation. The callback - /// must not access runtime functionality, as any operation on the runtime may - /// invalidate the data pointers. - virtual void getStringData( - const jsi::String& str, - void* ctx, - void (*cb)(void* ctx, bool ascii, const void* data, size_t num)); - - /// Invokes the provided callback \p cb with the PropNameID content in \p sym. - /// The callback must take in three arguments: bool ascii, const void* data, - /// and size_t num, respectively. \p ascii indicates whether the \p data - /// passed to the callback should be interpreted as a pointer to a sequence of - /// \p num ASCII characters or UTF16 characters. Depending on the internal - /// representation of the string, the function may invoke the callback - /// multiple times, with a different format on each invocation. The callback - /// must not access runtime functionality, as any operation on the runtime may - /// invalidate the data pointers. - virtual void getPropNameIdData( - const jsi::PropNameID& sym, - void* ctx, - void (*cb)(void* ctx, bool ascii, const void* data, size_t num)); - - // These exist so derived classes can access the private parts of - // Value, Symbol, String, and Object, which are all friends of Runtime. - template - static T make(PointerValue* pv); - static PointerValue* getPointerValue(Pointer& pointer); - static const PointerValue* getPointerValue(const Pointer& pointer); - static const PointerValue* getPointerValue(const Value& value); - - friend class ::FBJSRuntime; - template - friend class RuntimeDecorator; -}; - -// Base class for pointer-storing types. -class JSI_EXPORT Pointer { - protected: - explicit Pointer(Pointer&& other) noexcept : ptr_(other.ptr_) { - other.ptr_ = nullptr; - } - - ~Pointer() { - if (ptr_) { - ptr_->invalidate(); - } - } - - Pointer& operator=(Pointer&& other) noexcept; - - friend class Runtime; - friend class Value; - - explicit Pointer(Runtime::PointerValue* ptr) : ptr_(ptr) {} - - typename Runtime::PointerValue* ptr_; -}; - -/// Represents something that can be a JS property key. Movable, not copyable. -class JSI_EXPORT PropNameID : public Pointer { - public: - using Pointer::Pointer; - - PropNameID(Runtime& runtime, const PropNameID& other) - : Pointer(runtime.clonePropNameID(other.ptr_)) {} - - PropNameID(PropNameID&& other) = default; - PropNameID& operator=(PropNameID&& other) = default; - - /// Create a JS property name id from ascii values. The data is - /// copied. - static PropNameID forAscii(Runtime& runtime, const char* str, size_t length) { - return runtime.createPropNameIDFromAscii(str, length); - } - - /// Create a property name id from a nul-terminated C ascii name. The data is - /// copied. - static PropNameID forAscii(Runtime& runtime, const char* str) { - return forAscii(runtime, str, strlen(str)); - } - - /// Create a PropNameID from a C++ string. The string is copied. - static PropNameID forAscii(Runtime& runtime, const std::string& str) { - return forAscii(runtime, str.c_str(), str.size()); - } - - /// Create a PropNameID from utf8 values. The data is copied. - /// Results are undefined if \p utf8 contains invalid code points. - static PropNameID - forUtf8(Runtime& runtime, const uint8_t* utf8, size_t length) { - return runtime.createPropNameIDFromUtf8(utf8, length); - } - - /// Create a PropNameID from utf8-encoded octets stored in a - /// std::string. The string data is transformed and copied. - /// Results are undefined if \p utf8 contains invalid code points. - static PropNameID forUtf8(Runtime& runtime, const std::string& utf8) { - return runtime.createPropNameIDFromUtf8( - reinterpret_cast(utf8.data()), utf8.size()); - } - - /// Given a series of UTF-16 encoded code units, create a PropNameId. The - /// input may contain unpaired surrogates, which will be interpreted as a code - /// point of the same value. - static PropNameID - forUtf16(Runtime& runtime, const char16_t* utf16, size_t length) { - return runtime.createPropNameIDFromUtf16(utf16, length); - } - - /// Given a series of UTF-16 encoded code units stored inside std::u16string, - /// create a PropNameId. The input may contain unpaired surrogates, which - /// will be interpreted as a code point of the same value. - static PropNameID forUtf16(Runtime& runtime, const std::u16string& str) { - return runtime.createPropNameIDFromUtf16(str.data(), str.size()); - } - - /// Create a PropNameID from a JS string. - static PropNameID forString(Runtime& runtime, const jsi::String& str) { - return runtime.createPropNameIDFromString(str); - } - - /// Create a PropNameID from a JS symbol. - static PropNameID forSymbol(Runtime& runtime, const jsi::Symbol& sym) { - return runtime.createPropNameIDFromSymbol(sym); - } - - // Creates a vector of PropNameIDs constructed from given arguments. - template - static std::vector names(Runtime& runtime, Args&&... args); - - // Creates a vector of given PropNameIDs. - template - static std::vector names(PropNameID (&&propertyNames)[N]); - - /// Copies the data in a PropNameID as utf8 into a C++ string. - std::string utf8(Runtime& runtime) const { - return runtime.utf8(*this); - } - - /// Copies the data in a PropNameID as utf16 into a C++ string. - std::u16string utf16(Runtime& runtime) const { - return runtime.utf16(*this); - } - - /// Invokes the user provided callback to process the content in PropNameId. - /// The callback must take in three arguments: bool ascii, const void* data, - /// and size_t num, respectively. \p ascii indicates whether the \p data - /// passed to the callback should be interpreted as a pointer to a sequence of - /// \p num ASCII characters or UTF16 characters. The function may invoke the - /// callback multiple times, with a different format on each invocation. The - /// callback must not access runtime functionality, as any operation on the - /// runtime may invalidate the data pointers. - template - void getPropNameIdData(Runtime& runtime, CB& cb) const { - runtime.getPropNameIdData( - *this, &cb, [](void* ctx, bool ascii, const void* data, size_t num) { - (*((CB*)ctx))(ascii, data, num); - }); - } - - static bool compare( - Runtime& runtime, - const jsi::PropNameID& a, - const jsi::PropNameID& b) { - return runtime.compare(a, b); - } - - friend class Runtime; - friend class Value; -}; - -/// Represents a JS Symbol (es6). Movable, not copyable. -/// TODO T40778724: this is a limited implementation sufficient for -/// the debugger not to crash when a Symbol is a property in an Object -/// or element in an array. Complete support for creating will come -/// later. -class JSI_EXPORT Symbol : public Pointer { - public: - using Pointer::Pointer; - - Symbol(Symbol&& other) = default; - Symbol& operator=(Symbol&& other) = default; - - /// \return whether a and b refer to the same symbol. - static bool strictEquals(Runtime& runtime, const Symbol& a, const Symbol& b) { - return runtime.strictEquals(a, b); - } - - /// Converts a Symbol into a C++ string as JS .toString would. The output - /// will look like \c Symbol(description) . - std::string toString(Runtime& runtime) const { - return runtime.symbolToString(*this); - } - - friend class Runtime; - friend class Value; -}; - -/// Represents a JS BigInt. Movable, not copyable. -class JSI_EXPORT BigInt : public Pointer { - public: - using Pointer::Pointer; - - BigInt(BigInt&& other) = default; - BigInt& operator=(BigInt&& other) = default; - - /// Create a BigInt representing the signed 64-bit \p value. - static BigInt fromInt64(Runtime& runtime, int64_t value) { - return runtime.createBigIntFromInt64(value); - } - - /// Create a BigInt representing the unsigned 64-bit \p value. - static BigInt fromUint64(Runtime& runtime, uint64_t value) { - return runtime.createBigIntFromUint64(value); - } - - /// \return whether a === b. - static bool strictEquals(Runtime& runtime, const BigInt& a, const BigInt& b) { - return runtime.strictEquals(a, b); - } - - /// \returns This bigint truncated to a signed 64-bit integer. - int64_t getInt64(Runtime& runtime) const { - return runtime.truncate(*this); - } - - /// \returns Whether this bigint can be losslessly converted to int64_t. - bool isInt64(Runtime& runtime) const { - return runtime.bigintIsInt64(*this); - } - - /// \returns This bigint truncated to a signed 64-bit integer. Throws a - /// JSIException if the truncation is lossy. - int64_t asInt64(Runtime& runtime) const; - - /// \returns This bigint truncated to an unsigned 64-bit integer. - uint64_t getUint64(Runtime& runtime) const { - return runtime.truncate(*this); - } - - /// \returns Whether this bigint can be losslessly converted to uint64_t. - bool isUint64(Runtime& runtime) const { - return runtime.bigintIsUint64(*this); - } - - /// \returns This bigint truncated to an unsigned 64-bit integer. Throws a - /// JSIException if the truncation is lossy. - uint64_t asUint64(Runtime& runtime) const; - - /// \returns this BigInt converted to a String in base \p radix. Throws a - /// JSIException if radix is not in the [2, 36] range. - inline String toString(Runtime& runtime, int radix = 10) const; - - friend class Runtime; - friend class Value; -}; - -/// Represents a JS String. Movable, not copyable. -class JSI_EXPORT String : public Pointer { - public: - using Pointer::Pointer; - - String(String&& other) = default; - String& operator=(String&& other) = default; - - /// Create a JS string from ascii values. The string data is - /// copied. - static String - createFromAscii(Runtime& runtime, const char* str, size_t length) { - return runtime.createStringFromAscii(str, length); - } - - /// Create a JS string from a nul-terminated C ascii string. The - /// string data is copied. - static String createFromAscii(Runtime& runtime, const char* str) { - return createFromAscii(runtime, str, strlen(str)); - } - - /// Create a JS string from a C++ string. The string data is - /// copied. - static String createFromAscii(Runtime& runtime, const std::string& str) { - return createFromAscii(runtime, str.c_str(), str.size()); - } - - /// Create a JS string from utf8-encoded octets. The string data is - /// transformed and copied. Results are undefined if \p utf8 contains invalid - /// code points. - static String - createFromUtf8(Runtime& runtime, const uint8_t* utf8, size_t length) { - return runtime.createStringFromUtf8(utf8, length); - } - - /// Create a JS string from utf8-encoded octets stored in a - /// std::string. The string data is transformed and copied. Results are - /// undefined if \p utf8 contains invalid code points. - static String createFromUtf8(Runtime& runtime, const std::string& utf8) { - return runtime.createStringFromUtf8( - reinterpret_cast(utf8.data()), utf8.length()); - } - - /// Given a series of UTF-16 encoded code units, create a JS String. The input - /// may contain unpaired surrogates, which will be interpreted as a code point - /// of the same value. - static String - createFromUtf16(Runtime& runtime, const char16_t* utf16, size_t length) { - return runtime.createStringFromUtf16(utf16, length); - } - - /// Given a series of UTF-16 encoded code units stored inside std::u16string, - /// create a JS String. The input may contain unpaired surrogates, which will - /// be interpreted as a code point of the same value. - static String createFromUtf16(Runtime& runtime, const std::u16string& utf16) { - return runtime.createStringFromUtf16(utf16.data(), utf16.length()); - } - - /// \return whether a and b contain the same characters. - static bool strictEquals(Runtime& runtime, const String& a, const String& b) { - return runtime.strictEquals(a, b); - } - - /// Copies the data in a JS string as utf8 into a C++ string. - std::string utf8(Runtime& runtime) const { - return runtime.utf8(*this); - } - - /// Copies the data in a JS string as utf16 into a C++ string. - std::u16string utf16(Runtime& runtime) const { - return runtime.utf16(*this); - } - - /// Invokes the user provided callback to process content in String. The - /// callback must take in three arguments: bool ascii, const void* data, and - /// size_t num, respectively. \p ascii indicates whether the \p data passed to - /// the callback should be interpreted as a pointer to a sequence of \p num - /// ASCII characters or UTF16 characters. The function may invoke the callback - /// multiple times, with a different format on each invocation. The callback - /// must not access runtime functionality, as any operation on the runtime may - /// invalidate the data pointers. - template - void getStringData(Runtime& runtime, CB& cb) const { - runtime.getStringData( - *this, &cb, [](void* ctx, bool ascii, const void* data, size_t num) { - (*((CB*)ctx))(ascii, data, num); - }); - } - - friend class Runtime; - friend class Value; -}; - -class Array; -class Function; - -/// Represents a JS Object. Movable, not copyable. -class JSI_EXPORT Object : public Pointer { - public: - using Pointer::Pointer; - - Object(Object&& other) = default; - Object& operator=(Object&& other) = default; - - /// Creates a new Object instance, like '{}' in JS. - explicit Object(Runtime& runtime) : Object(runtime.createObject()) {} - - static Object createFromHostObject( - Runtime& runtime, - std::shared_ptr ho) { - return runtime.createObject(ho); - } - - /// Creates a new Object with the custom prototype - static Object create(Runtime& runtime, const Value& prototype) { - return runtime.createObjectWithPrototype(prototype); - } - - /// \return whether this and \c obj are the same JSObject or not. - static bool strictEquals(Runtime& runtime, const Object& a, const Object& b) { - return runtime.strictEquals(a, b); - } - - /// \return the result of `this instanceOf ctor` in JS. - bool instanceOf(Runtime& rt, const Function& ctor) const { - return rt.instanceOf(*this, ctor); - } - - /// Sets \p prototype as the prototype of the object. The prototype must be - /// either an Object or null. If the prototype was not set successfully, this - /// method will throw. - void setPrototype(Runtime& runtime, const Value& prototype) const { - return runtime.setPrototypeOf(*this, prototype); - } - - /// \return the prototype of the object - inline Value getPrototype(Runtime& runtime) const; - - /// \return the property of the object with the given ascii name. - /// If the name isn't a property on the object, returns the - /// undefined value. - Value getProperty(Runtime& runtime, const char* name) const; - - /// \return the property of the object with the String name. - /// If the name isn't a property on the object, returns the - /// undefined value. - Value getProperty(Runtime& runtime, const String& name) const; - - /// \return the property of the object with the given JS PropNameID - /// name. If the name isn't a property on the object, returns the - /// undefined value. - Value getProperty(Runtime& runtime, const PropNameID& name) const; - - /// \return the Property of the object with the given JS Value name. If the - /// name isn't a property on the object, returns the undefined value.This - /// attempts to convert the JS Value to convert to a property key. If the - /// conversion fails, this method may throw. - Value getProperty(Runtime& runtime, const Value& name) const; - - /// \return true if and only if the object has a property with the - /// given ascii name. - bool hasProperty(Runtime& runtime, const char* name) const; - - /// \return true if and only if the object has a property with the - /// given String name. - bool hasProperty(Runtime& runtime, const String& name) const; - - /// \return true if and only if the object has a property with the - /// given PropNameID name. - bool hasProperty(Runtime& runtime, const PropNameID& name) const; - - /// \return true if and only if the object has a property with the given - /// JS Value name. This attempts to convert the JS Value to convert to a - /// property key. If the conversion fails, this method may throw. - bool hasProperty(Runtime& runtime, const Value& name) const; - - /// Sets the property value from a Value or anything which can be - /// used to make one: nullptr_t, bool, double, int, const char*, - /// String, or Object. - template - void setProperty(Runtime& runtime, const char* name, T&& value) const; - - /// Sets the property value from a Value or anything which can be - /// used to make one: nullptr_t, bool, double, int, const char*, - /// String, or Object. - template - void setProperty(Runtime& runtime, const String& name, T&& value) const; - - /// Sets the property value from a Value or anything which can be - /// used to make one: nullptr_t, bool, double, int, const char*, - /// String, or Object. - template - void setProperty(Runtime& runtime, const PropNameID& name, T&& value) const; - - /// Sets the property value from a Value or anything which can be - /// used to make one: nullptr_t, bool, double, int, const char*, - /// String, or Object. This takes a JS Value as the property name, and - /// attempts to convert to a property key. If the conversion fails, this - /// method may throw. - template - void setProperty(Runtime& runtime, const Value& name, T&& value) const; - - /// Delete the property with the given ascii name. Throws if the deletion - /// failed. - void deleteProperty(Runtime& runtime, const char* name) const; - - /// Delete the property with the given String name. Throws if the deletion - /// failed. - void deleteProperty(Runtime& runtime, const String& name) const; - - /// Delete the property with the given PropNameID name. Throws if the deletion - /// failed. - void deleteProperty(Runtime& runtime, const PropNameID& name) const; - - /// Delete the property with the given Value name. Throws if the deletion - /// failed. - void deleteProperty(Runtime& runtime, const Value& name) const; - - /// \return true iff JS \c Array.isArray() would return \c true. If - /// so, then \c getArray() will succeed. - bool isArray(Runtime& runtime) const { - return runtime.isArray(*this); - } - - /// \return true iff the Object is an ArrayBuffer. If so, then \c - /// getArrayBuffer() will succeed. - bool isArrayBuffer(Runtime& runtime) const { - return runtime.isArrayBuffer(*this); - } - - /// \return true iff the Object is callable. If so, then \c - /// getFunction will succeed. - bool isFunction(Runtime& runtime) const { - return runtime.isFunction(*this); - } - - /// \return true iff the Object was initialized with \c createFromHostObject - /// and the HostObject passed is of type \c T. If returns \c true then - /// \c getHostObject will succeed. - template - bool isHostObject(Runtime& runtime) const; - - /// \return an Array instance which refers to the same underlying - /// object. If \c isArray() would return false, this will assert. - Array getArray(Runtime& runtime) const&; - - /// \return an Array instance which refers to the same underlying - /// object. If \c isArray() would return false, this will assert. - Array getArray(Runtime& runtime) &&; - - /// \return an Array instance which refers to the same underlying - /// object. If \c isArray() would return false, this will throw - /// JSIException. - Array asArray(Runtime& runtime) const&; - - /// \return an Array instance which refers to the same underlying - /// object. If \c isArray() would return false, this will throw - /// JSIException. - Array asArray(Runtime& runtime) &&; - - /// \return an ArrayBuffer instance which refers to the same underlying - /// object. If \c isArrayBuffer() would return false, this will assert. - ArrayBuffer getArrayBuffer(Runtime& runtime) const&; - - /// \return an ArrayBuffer instance which refers to the same underlying - /// object. If \c isArrayBuffer() would return false, this will assert. - ArrayBuffer getArrayBuffer(Runtime& runtime) &&; - - /// \return a Function instance which refers to the same underlying - /// object. If \c isFunction() would return false, this will assert. - Function getFunction(Runtime& runtime) const&; - - /// \return a Function instance which refers to the same underlying - /// object. If \c isFunction() would return false, this will assert. - Function getFunction(Runtime& runtime) &&; - - /// \return a Function instance which refers to the same underlying - /// object. If \c isFunction() would return false, this will throw - /// JSIException. - Function asFunction(Runtime& runtime) const&; - - /// \return a Function instance which refers to the same underlying - /// object. If \c isFunction() would return false, this will throw - /// JSIException. - Function asFunction(Runtime& runtime) &&; - - /// \return a shared_ptr which refers to the same underlying - /// \c HostObject that was used to create this object. If \c isHostObject - /// is false, this will assert. Note that this does a type check and will - /// assert if the underlying HostObject isn't of type \c T - template - std::shared_ptr getHostObject(Runtime& runtime) const; - - /// \return a shared_ptr which refers to the same underlying - /// \c HostObject that was used to create this object. If \c isHostObject - /// is false, this will throw. - template - std::shared_ptr asHostObject(Runtime& runtime) const; - - /// \return whether this object has native state of type T previously set by - /// \c setNativeState. - template - bool hasNativeState(Runtime& runtime) const; - - /// \return a shared_ptr to the state previously set by \c setNativeState. - /// If \c hasNativeState is false, this will assert. Note that this does a - /// type check and will assert if the native state isn't of type \c T - template - std::shared_ptr getNativeState(Runtime& runtime) const; - - /// Set the internal native state property of this object, overwriting any old - /// value. Creates a new shared_ptr to the object managed by \p state, which - /// will live until the value at this property becomes unreachable. - /// - /// Throws a type error if this object is a proxy or host object. - void setNativeState(Runtime& runtime, std::shared_ptr state) - const; - - /// \return same as \c getProperty(name).asObject(), except with - /// a better exception message. - Object getPropertyAsObject(Runtime& runtime, const char* name) const; - - /// \return similar to \c - /// getProperty(name).getObject().getFunction(), except it will - /// throw JSIException instead of asserting if the property is - /// not an object, or the object is not callable. - Function getPropertyAsFunction(Runtime& runtime, const char* name) const; - - /// \return an Array consisting of all enumerable property names in - /// the object and its prototype chain. All values in the return - /// will be isString(). (This is probably not optimal, but it - /// works. I only need it in one place.) - Array getPropertyNames(Runtime& runtime) const; - - /// Inform the runtime that there is additional memory associated with a given - /// JavaScript object that is not visible to the GC. This can be used if an - /// object is known to retain some native memory, and may be used to guide - /// decisions about when to run garbage collection. - /// This method may be invoked multiple times on an object, and subsequent - /// calls will overwrite any previously set value. Once the object is garbage - /// collected, the associated external memory will be considered freed and may - /// no longer factor into GC decisions. - void setExternalMemoryPressure(Runtime& runtime, size_t amt) const; - - protected: - void setPropertyValue( - Runtime& runtime, - const String& name, - const Value& value) const { - return runtime.setPropertyValue(*this, name, value); - } - - void setPropertyValue( - Runtime& runtime, - const PropNameID& name, - const Value& value) const { - return runtime.setPropertyValue(*this, name, value); - } - - void setPropertyValue(Runtime& runtime, const Value& name, const Value& value) - const { - return runtime.setPropertyValue(*this, name, value); - } - - friend class Runtime; - friend class Value; -}; - -/// Represents a weak reference to a JS Object. If the only reference -/// to an Object are these, the object is eligible for GC. Method -/// names are inspired by C++ weak_ptr. Movable, not copyable. -class JSI_EXPORT WeakObject : public Pointer { - public: - using Pointer::Pointer; - - WeakObject(WeakObject&& other) = default; - WeakObject& operator=(WeakObject&& other) = default; - - /// Create a WeakObject from an Object. - WeakObject(Runtime& runtime, const Object& o) - : WeakObject(runtime.createWeakObject(o)) {} - - /// \return a Value representing the underlying Object if it is still valid; - /// otherwise returns \c undefined. Note that this method has nothing to do - /// with threads or concurrency. The name is based on std::weak_ptr::lock() - /// which serves a similar purpose. - Value lock(Runtime& runtime) const; - - friend class Runtime; -}; - -/// Represents a JS Object which can be efficiently used as an array -/// with integral indices. -class JSI_EXPORT Array : public Object { - public: - Array(Array&&) = default; - /// Creates a new Array instance, with \c length undefined elements. - Array(Runtime& runtime, size_t length) : Array(runtime.createArray(length)) {} - - Array& operator=(Array&&) = default; - - /// \return the size of the Array, according to its length property. - /// (C++ naming convention) - size_t size(Runtime& runtime) const { - return runtime.size(*this); - } - - /// \return the size of the Array, according to its length property. - /// (JS naming convention) - size_t length(Runtime& runtime) const { - return size(runtime); - } - - /// \return the property of the array at index \c i. If there is no - /// such property, returns the undefined value. If \c i is out of - /// range [ 0..\c length ] throws a JSIException. - Value getValueAtIndex(Runtime& runtime, size_t i) const; - - /// Sets the property of the array at index \c i. The argument - /// value behaves as with Object::setProperty(). If \c i is out of - /// range [ 0..\c length ] throws a JSIException. - template - void setValueAtIndex(Runtime& runtime, size_t i, T&& value) const; - - /// There is no current API for changing the size of an array once - /// created. We'll probably need that eventually. - - /// Creates a new Array instance from provided values - template - static Array createWithElements(Runtime&, Args&&... args); - - /// Creates a new Array instance from initializer list. - static Array createWithElements( - Runtime& runtime, - std::initializer_list elements); - - private: - friend class Object; - friend class Value; - friend class Runtime; - - void setValueAtIndexImpl(Runtime& runtime, size_t i, const Value& value) - const { - return runtime.setValueAtIndexImpl(*this, i, value); - } - - Array(Runtime::PointerValue* value) : Object(value) {} -}; - -/// Represents a JSArrayBuffer -class JSI_EXPORT ArrayBuffer : public Object { - public: - ArrayBuffer(ArrayBuffer&&) = default; - ArrayBuffer& operator=(ArrayBuffer&&) = default; - - ArrayBuffer(Runtime& runtime, std::shared_ptr buffer) - : ArrayBuffer(runtime.createArrayBuffer(std::move(buffer))) {} - - /// \return the size of the ArrayBuffer storage. This is not affected by - /// overriding the byteLength property. - /// (C++ naming convention) - size_t size(Runtime& runtime) const { - return runtime.size(*this); - } - - size_t length(Runtime& runtime) const { - return runtime.size(*this); - } - - uint8_t* data(Runtime& runtime) const { - return runtime.data(*this); - } - - private: - friend class Object; - friend class Value; - friend class Runtime; - - ArrayBuffer(Runtime::PointerValue* value) : Object(value) {} -}; - -/// Represents a JS Object which is guaranteed to be Callable. -class JSI_EXPORT Function : public Object { - public: - Function(Function&&) = default; - Function& operator=(Function&&) = default; - - /// Create a function which, when invoked, calls C++ code. If the - /// function throws an exception, a JS Error will be created and - /// thrown. - /// \param name the name property for the function. - /// \param paramCount the length property for the function, which - /// may not be the number of arguments the function is passed. - /// \note The std::function's dtor will be called when the GC finalizes this - /// function. As with HostObject, this may be as late as when the Runtime is - /// shut down, and may occur on an arbitrary thread. If the function contains - /// any captured values, you are responsible for ensuring that their - /// destructors are safe to call on any thread. - static Function createFromHostFunction( - Runtime& runtime, - const jsi::PropNameID& name, - unsigned int paramCount, - jsi::HostFunctionType func); - - /// Calls the function with \c count \c args. The \c this value of the JS - /// function will not be set by the C++ caller, similar to calling - /// Function.prototype.apply(undefined, args) in JS. - /// \b Note: as with Function.prototype.apply, \c this may not always be - /// \c undefined in the function itself. If the function is non-strict, - /// \c this will be set to the global object. - Value call(Runtime& runtime, const Value* args, size_t count) const; - - /// Calls the function with a \c std::initializer_list of Value - /// arguments. The \c this value of the JS function will not be set by the - /// C++ caller, similar to calling Function.prototype.apply(undefined, args) - /// in JS. - /// \b Note: as with Function.prototype.apply, \c this may not always be - /// \c undefined in the function itself. If the function is non-strict, - /// \c this will be set to the global object. - Value call(Runtime& runtime, std::initializer_list args) const; - - /// Calls the function with any number of arguments similarly to - /// Object::setProperty(). The \c this value of the JS function will not be - /// set by the C++ caller, similar to calling - /// Function.prototype.call(undefined, ...args) in JS. - /// \b Note: as with Function.prototype.call, \c this may not always be - /// \c undefined in the function itself. If the function is non-strict, - /// \c this will be set to the global object. - template - Value call(Runtime& runtime, Args&&... args) const; - - /// Calls the function with \c count \c args and \c jsThis value passed - /// as the \c this value. - Value callWithThis( - Runtime& Runtime, - const Object& jsThis, - const Value* args, - size_t count) const; - - /// Calls the function with a \c std::initializer_list of Value - /// arguments and \c jsThis passed as the \c this value. - Value callWithThis( - Runtime& runtime, - const Object& jsThis, - std::initializer_list args) const; - - /// Calls the function with any number of arguments similarly to - /// Object::setProperty(), and with \c jsThis passed as the \c this value. - template - Value callWithThis(Runtime& runtime, const Object& jsThis, Args&&... args) - const; - - /// Calls the function as a constructor with \c count \c args. Equivalent - /// to calling `new Func` where `Func` is the js function reqresented by - /// this. - Value callAsConstructor(Runtime& runtime, const Value* args, size_t count) - const; - - /// Same as above `callAsConstructor`, except use an initializer_list to - /// supply the arguments. - Value callAsConstructor(Runtime& runtime, std::initializer_list args) - const; - - /// Same as above `callAsConstructor`, but automatically converts/wraps - /// any argument with a jsi Value. - template - Value callAsConstructor(Runtime& runtime, Args&&... args) const; - - /// Returns whether this was created with Function::createFromHostFunction. - /// If true then you can use getHostFunction to get the underlying - /// HostFunctionType. - bool isHostFunction(Runtime& runtime) const { - return runtime.isHostFunction(*this); - } - - /// Returns the underlying HostFunctionType iff isHostFunction returns true - /// and asserts otherwise. You can use this to use std::function<>::target - /// to get the object that was passed to create the HostFunctionType. - /// - /// Note: The reference returned is borrowed from the JS object underlying - /// \c this, and thus only lasts as long as the object underlying - /// \c this does. - HostFunctionType& getHostFunction(Runtime& runtime) const { - assert(isHostFunction(runtime)); - return runtime.getHostFunction(*this); - } - - private: - friend class Object; - friend class Value; - friend class Runtime; - - Function(Runtime::PointerValue* value) : Object(value) {} -}; - -/// Represents any JS Value (undefined, null, boolean, number, symbol, -/// string, or object). Movable, or explicitly copyable (has no copy -/// ctor). -class JSI_EXPORT Value { - public: - /// Default ctor creates an \c undefined JS value. - Value() noexcept : Value(UndefinedKind) {} - - /// Creates a \c null JS value. - /* implicit */ Value(std::nullptr_t) : kind_(NullKind) {} - - /// Creates a boolean JS value. - /* implicit */ Value(bool b) : Value(BooleanKind) { - data_.boolean = b; - } - - /// Creates a number JS value. - /* implicit */ Value(double d) : Value(NumberKind) { - data_.number = d; - } - - /// Creates a number JS value. - /* implicit */ Value(int i) : Value(NumberKind) { - data_.number = i; - } - - /// Moves a Symbol, String, or Object rvalue into a new JS value. - template < - typename T, - typename = std::enable_if_t< - std::is_base_of::value || - std::is_base_of::value || - std::is_base_of::value || - std::is_base_of::value>> - /* implicit */ Value(T&& other) : Value(kindOf(other)) { - new (&data_.pointer) T(std::move(other)); - } - - /// Value("foo") will treat foo as a bool. This makes doing that a - /// compile error. - template - Value(const char*) { - static_assert( - !std::is_same::value, - "Value cannot be constructed directly from const char*"); - } - - Value(Value&& other) noexcept; - - /// Copies a Symbol lvalue into a new JS value. - Value(Runtime& runtime, const Symbol& sym) : Value(SymbolKind) { - new (&data_.pointer) Symbol(runtime.cloneSymbol(sym.ptr_)); - } - - /// Copies a BigInt lvalue into a new JS value. - Value(Runtime& runtime, const BigInt& bigint) : Value(BigIntKind) { - new (&data_.pointer) BigInt(runtime.cloneBigInt(bigint.ptr_)); - } - - /// Copies a String lvalue into a new JS value. - Value(Runtime& runtime, const String& str) : Value(StringKind) { - new (&data_.pointer) String(runtime.cloneString(str.ptr_)); - } - - /// Copies a Object lvalue into a new JS value. - Value(Runtime& runtime, const Object& obj) : Value(ObjectKind) { - new (&data_.pointer) Object(runtime.cloneObject(obj.ptr_)); - } - - /// Creates a JS value from another Value lvalue. - Value(Runtime& runtime, const Value& value); - - /// Value(rt, "foo") will treat foo as a bool. This makes doing - /// that a compile error. - template - Value(Runtime&, const char*) { - static_assert( - !std::is_same::value, - "Value cannot be constructed directly from const char*"); - } - - ~Value(); - // \return the undefined \c Value. - static Value undefined() { - return Value(); - } - - // \return the null \c Value. - static Value null() { - return Value(nullptr); - } - - // \return a \c Value created from a utf8-encoded JSON string. - static Value - createFromJsonUtf8(Runtime& runtime, const uint8_t* json, size_t length) { - return runtime.createValueFromJsonUtf8(json, length); - } - - /// \return according to the Strict Equality Comparison algorithm, see: - /// https://262.ecma-international.org/11.0/#sec-strict-equality-comparison - static bool strictEquals(Runtime& runtime, const Value& a, const Value& b); - - Value& operator=(Value&& other) noexcept { - this->~Value(); - new (this) Value(std::move(other)); - return *this; - } - - bool isUndefined() const { - return kind_ == UndefinedKind; - } - - bool isNull() const { - return kind_ == NullKind; - } - - bool isBool() const { - return kind_ == BooleanKind; - } - - bool isNumber() const { - return kind_ == NumberKind; - } - - bool isString() const { - return kind_ == StringKind; - } - - bool isBigInt() const { - return kind_ == BigIntKind; - } - - bool isSymbol() const { - return kind_ == SymbolKind; - } - - bool isObject() const { - return kind_ == ObjectKind; - } - - /// \return the boolean value, or asserts if not a boolean. - bool getBool() const { - assert(isBool()); - return data_.boolean; - } - - /// \return the boolean value, or throws JSIException if not a - /// boolean. - bool asBool() const; - - /// \return the number value, or asserts if not a number. - double getNumber() const { - assert(isNumber()); - return data_.number; - } - - /// \return the number value, or throws JSIException if not a - /// number. - double asNumber() const; - - /// \return the Symbol value, or asserts if not a symbol. - Symbol getSymbol(Runtime& runtime) const& { - assert(isSymbol()); - return Symbol(runtime.cloneSymbol(data_.pointer.ptr_)); - } - - /// \return the Symbol value, or asserts if not a symbol. - /// Can be used on rvalue references to avoid cloning more symbols. - Symbol getSymbol(Runtime&) && { - assert(isSymbol()); - auto ptr = data_.pointer.ptr_; - data_.pointer.ptr_ = nullptr; - return static_cast(ptr); - } - - /// \return the Symbol value, or throws JSIException if not a - /// symbol - Symbol asSymbol(Runtime& runtime) const&; - Symbol asSymbol(Runtime& runtime) &&; - - /// \return the BigInt value, or asserts if not a bigint. - BigInt getBigInt(Runtime& runtime) const& { - assert(isBigInt()); - return BigInt(runtime.cloneBigInt(data_.pointer.ptr_)); - } - - /// \return the BigInt value, or asserts if not a bigint. - /// Can be used on rvalue references to avoid cloning more bigints. - BigInt getBigInt(Runtime&) && { - assert(isBigInt()); - auto ptr = data_.pointer.ptr_; - data_.pointer.ptr_ = nullptr; - return static_cast(ptr); - } - - /// \return the BigInt value, or throws JSIException if not a - /// bigint - BigInt asBigInt(Runtime& runtime) const&; - BigInt asBigInt(Runtime& runtime) &&; - - /// \return the String value, or asserts if not a string. - String getString(Runtime& runtime) const& { - assert(isString()); - return String(runtime.cloneString(data_.pointer.ptr_)); - } - - /// \return the String value, or asserts if not a string. - /// Can be used on rvalue references to avoid cloning more strings. - String getString(Runtime&) && { - assert(isString()); - auto ptr = data_.pointer.ptr_; - data_.pointer.ptr_ = nullptr; - return static_cast(ptr); - } - - /// \return the String value, or throws JSIException if not a - /// string. - String asString(Runtime& runtime) const&; - String asString(Runtime& runtime) &&; - - /// \return the Object value, or asserts if not an object. - Object getObject(Runtime& runtime) const& { - assert(isObject()); - return Object(runtime.cloneObject(data_.pointer.ptr_)); - } - - /// \return the Object value, or asserts if not an object. - /// Can be used on rvalue references to avoid cloning more objects. - Object getObject(Runtime&) && { - assert(isObject()); - auto ptr = data_.pointer.ptr_; - data_.pointer.ptr_ = nullptr; - return static_cast(ptr); - } - - /// \return the Object value, or throws JSIException if not an - /// object. - Object asObject(Runtime& runtime) const&; - Object asObject(Runtime& runtime) &&; - - // \return a String like JS .toString() would do. - String toString(Runtime& runtime) const; - - private: - friend class Runtime; - - enum ValueKind { - UndefinedKind, - NullKind, - BooleanKind, - NumberKind, - SymbolKind, - BigIntKind, - StringKind, - ObjectKind, - PointerKind = SymbolKind, - }; - - union Data { - // Value's ctor and dtor will manage the lifecycle of the contained Data. - Data() { - static_assert( - sizeof(Data) == sizeof(uint64_t), - "Value data should fit in a 64-bit register"); - } - ~Data() {} - - // scalars - bool boolean; - double number; - // pointers - Pointer pointer; // Symbol, String, Object, Array, Function - }; - - Value(ValueKind kind) : kind_(kind) {} - - constexpr static ValueKind kindOf(const Symbol&) { - return SymbolKind; - } - constexpr static ValueKind kindOf(const BigInt&) { - return BigIntKind; - } - constexpr static ValueKind kindOf(const String&) { - return StringKind; - } - constexpr static ValueKind kindOf(const Object&) { - return ObjectKind; - } - - ValueKind kind_; - Data data_; - - // In the future: Value becomes NaN-boxed. See T40538354. -}; - -/// Not movable and not copyable RAII marker advising the underlying -/// JavaScript VM to track resources allocated since creation until -/// destruction so that they can be recycled eagerly when the Scope -/// goes out of scope instead of floating in the air until the next -/// garbage collection or any other delayed release occurs. -/// -/// This API should be treated only as advice, implementations can -/// choose to ignore the fact that Scopes are created or destroyed. -/// -/// This class is an exception to the rule allowing destructors to be -/// called without proper synchronization (see Runtime documentation). -/// The whole point of this class is to enable all sorts of clean ups -/// when the destructor is called and this proper synchronization is -/// required at that time. -/// -/// Instances of this class are intended to be created as automatic stack -/// variables in which case destructor calls don't require any additional -/// locking, provided that the lock (if any) is managed with RAII helpers. -class JSI_EXPORT Scope { - public: - explicit Scope(Runtime& rt) : rt_(rt), prv_(rt.pushScope()) {} - ~Scope() { - rt_.popScope(prv_); - } - - Scope(const Scope&) = delete; - Scope(Scope&&) = delete; - - Scope& operator=(const Scope&) = delete; - Scope& operator=(Scope&&) = delete; - - template - static auto callInNewScope(Runtime& rt, F f) -> decltype(f()) { - Scope s(rt); - return f(); - } - - private: - Runtime& rt_; - Runtime::ScopeState* prv_; -}; - -/// Base class for jsi exceptions -class JSI_EXPORT JSIException : public std::exception { - protected: - JSIException() {} - JSIException(std::string what) : what_(std::move(what)) {} - - public: - JSIException(const JSIException&) = default; - - virtual const char* what() const noexcept override { - return what_.c_str(); - } - - virtual ~JSIException() override; - - protected: - std::string what_; -}; - -/// This exception will be thrown by API functions on errors not related to -/// JavaScript execution. -class JSI_EXPORT JSINativeException : public JSIException { - public: - JSINativeException(std::string what) : JSIException(std::move(what)) {} - - JSINativeException(const JSINativeException&) = default; - - virtual ~JSINativeException(); -}; - -/// This exception will be thrown by API functions whenever a JS -/// operation causes an exception as described by the spec, or as -/// otherwise described. -class JSI_EXPORT JSError : public JSIException { - public: - /// Creates a JSError referring to provided \c value - JSError(Runtime& r, Value&& value); - - /// Creates a JSError referring to new \c Error instance capturing current - /// JavaScript stack. The error message property is set to given \c message. - JSError(Runtime& rt, std::string message); - - /// Creates a JSError referring to new \c Error instance capturing current - /// JavaScript stack. The error message property is set to given \c message. - JSError(Runtime& rt, const char* message) - : JSError(rt, std::string(message)) {} - - /// Creates a JSError referring to a JavaScript Object having message and - /// stack properties set to provided values. - JSError(Runtime& rt, std::string message, std::string stack); - - /// Creates a JSError referring to provided value and what string - /// set to provided message. This argument order is a bit weird, - /// but necessary to avoid ambiguity with the above. - JSError(std::string what, Runtime& rt, Value&& value); - - /// Creates a JSError referring to the provided value, message and stack. This - /// constructor does not take a Runtime parameter, and therefore cannot result - /// in recursively invoking the JSError constructor. - JSError(Value&& value, std::string message, std::string stack); - - JSError(const JSError&) = default; - - virtual ~JSError(); - - const std::string& getStack() const { - return stack_; - } - - const std::string& getMessage() const { - return message_; - } - - const jsi::Value& value() const { - assert(value_); - return *value_; - } - - private: - // This initializes the value_ member and does some other - // validation, so it must be called by every branch through the - // constructors. - void setValue(Runtime& rt, Value&& value); - - // This needs to be on the heap, because throw requires the object - // be copyable, and Value is not. - std::shared_ptr value_; - std::string message_; - std::string stack_; -}; - -/// Helper function to cast the object pointed to by \p ptr into an interface -/// specified by \c U. If cast is successful, return a pointer to the object -/// as a raw pointer of \c U. Otherwise, return nullptr. -/// The returned interface same lifetime as the object referenced by \p ptr. -template -U* castInterface(T* ptr) { - if (ptr) { - return static_cast(ptr->castInterface(U::uuid)); - } - return nullptr; -} - -/// Helper function to cast the object managed by the shared_ptr \p ptr into an -/// interface specified by \c U. If the cast is successful, return a shared_ptr -/// of type \c U to the object. Otherwise, return an empty pointer. -/// The returned shared_ptr shares ownership of the object with \p ptr. -template -std::shared_ptr dynamicInterfaceCast(T&& ptr) { - auto* p = ptr->castInterface(U::uuid); - U* res = static_cast(p); - if (res) { - return std::shared_ptr(std::forward(ptr), res); - } - return nullptr; -} - -} // namespace jsi -} // namespace facebook - -#include diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/jsilib.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/jsilib.h deleted file mode 100644 index c94de89f..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/jsilib.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -namespace facebook { -namespace jsi { - -class FileBuffer : public Buffer { - public: - FileBuffer(const std::string& path); - ~FileBuffer() override; - - size_t size() const override { - return size_; - } - - const uint8_t* data() const override { - return data_; - } - - private: - size_t size_; - uint8_t* data_; -}; - -// A trivial implementation of PreparedJavaScript that simply stores the source -// buffer and URL. -class SourceJavaScriptPreparation final : public jsi::PreparedJavaScript, - public jsi::Buffer { - std::shared_ptr buf_; - std::string sourceURL_; - - public: - SourceJavaScriptPreparation( - std::shared_ptr buf, - std::string sourceURL) - : buf_(std::move(buf)), sourceURL_(std::move(sourceURL)) {} - - const std::string& sourceURL() const { - return sourceURL_; - } - - size_t size() const override { - return buf_->size(); - } - const uint8_t* data() const override { - return buf_->data(); - } -}; - -} // namespace jsi -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/test/testlib.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/test/testlib.h deleted file mode 100644 index b56d41b8..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/test/testlib.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include - -#include -#include - -namespace facebook { -namespace jsi { - -class Runtime; - -using RuntimeFactory = std::function()>; - -std::vector runtimeGenerators(); - -class JSITestBase : public ::testing::TestWithParam { - public: - JSITestBase() : factory(GetParam()), runtime(factory()), rt(*runtime) {} - - Value eval(const char* code) { - return rt.global().getPropertyAsFunction(rt, "eval").call(rt, code); - } - - Function function(const std::string& code) { - return eval(("(" + code + ")").c_str()).getObject(rt).getFunction(rt); - } - - bool checkValue(const Value& value, const std::string& jsValue) { - return function("function(value) { return value == " + jsValue + "; }") - .call(rt, std::move(value)) - .getBool(); - } - - RuntimeFactory factory; - std::shared_ptr runtime; - Runtime& rt; -}; -} // namespace jsi -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/threadsafe.h b/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/threadsafe.h deleted file mode 100644 index cb10a335..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/include_shermes/jsi/threadsafe.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -#include -#include - -namespace facebook { -namespace jsi { - -class ThreadSafeRuntime : public Runtime { - public: - virtual void lock() const = 0; - virtual void unlock() const = 0; - virtual Runtime& getUnsafeRuntime() = 0; -}; - -namespace detail { - -template -struct WithLock { - L lock; - WithLock(R& r) : lock(r) {} - void before() { - lock.lock(); - } - void after() { - lock.unlock(); - } -}; - -// The actual implementation of a given ThreadSafeRuntime. It's parameterized -// by: -// -// - R: The actual Runtime type that this wraps -// - L: A lock type that has three members: -// - L(R& r) // ctor -// - void lock() -// - void unlock() -template -class ThreadSafeRuntimeImpl final - : public WithRuntimeDecorator, R, ThreadSafeRuntime> { - public: - template - ThreadSafeRuntimeImpl(Args&&... args) - : WithRuntimeDecorator, R, ThreadSafeRuntime>( - unsafe_, - lock_), - unsafe_(std::forward(args)...), - lock_(unsafe_) {} - - R& getUnsafeRuntime() override { - return WithRuntimeDecorator, R, ThreadSafeRuntime>::plain(); - } - - void lock() const override { - lock_.before(); - } - - void unlock() const override { - lock_.after(); - } - - private: - R unsafe_; - mutable WithLock lock_; -}; - -} // namespace detail - -} // namespace jsi -} // namespace facebook diff --git a/test-app/runtime/src/main/cpp/napi/hermes/js_runtime.h b/test-app/runtime/src/main/cpp/napi/hermes/js_runtime.h deleted file mode 100644 index 71bad7bd..00000000 --- a/test-app/runtime/src/main/cpp/napi/hermes/js_runtime.h +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#ifndef SRC_JS_RUNTIME_API_H_ -#define SRC_JS_RUNTIME_API_H_ - -#include "js_native_api.h" - -// -// Node-API extensions required for JavaScript engine hosting. -// -// It is a very early version of the APIs which we consider to be experimental. -// These APIs are not stable yet and are subject to change while we continue -// their development. After some time we will stabilize the APIs and make them -// "officially stable". -// - -#define JSR_API NAPI_EXTERN napi_status NAPI_CDECL - -EXTERN_C_START - -typedef struct jsr_runtime_s* jsr_runtime; -typedef struct jsr_config_s* jsr_config; -typedef struct jsr_prepared_script_s* jsr_prepared_script; -typedef struct jsr_napi_env_scope_s* jsr_napi_env_scope; - -typedef void(NAPI_CDECL* jsr_data_delete_cb)(void* data, void* deleter_data); - -//============================================================================= -// jsr_runtime -//============================================================================= - -JSR_API jsr_create_runtime(jsr_config config, jsr_runtime* runtime); -JSR_API jsr_delete_runtime(jsr_runtime runtime); -JSR_API jsr_runtime_get_node_api_env(jsr_runtime runtime, napi_env* env); - -//============================================================================= -// jsr_config -//============================================================================= - -JSR_API jsr_create_config(jsr_config* config); -JSR_API jsr_delete_config(jsr_config config); - -JSR_API jsr_config_enable_inspector(jsr_config config, bool value); -JSR_API jsr_config_set_inspector_runtime_name(jsr_config config, - const char* name); -JSR_API jsr_config_set_inspector_port(jsr_config config, uint16_t port); -JSR_API jsr_config_set_inspector_break_on_start(jsr_config config, bool value); - -JSR_API jsr_config_enable_gc_api(jsr_config config, bool value); - -//============================================================================= -// jsr_config task runner -//============================================================================= - -// A callback to run task -typedef void(NAPI_CDECL* jsr_task_run_cb)(void* task_data); - -// A callback to post task to the task runner -typedef void(NAPI_CDECL* jsr_task_runner_post_task_cb)( -void* task_runner_data, -void* task_data, - jsr_task_run_cb task_run_cb, -jsr_data_delete_cb task_data_delete_cb, -void* deleter_data); - -JSR_API jsr_config_set_task_runner( - jsr_config config, - void* task_runner_data, - jsr_task_runner_post_task_cb task_runner_post_task_cb, - jsr_data_delete_cb task_runner_data_delete_cb, - void* deleter_data); - -//============================================================================= -// jsr_config script cache -//============================================================================= - -typedef void(NAPI_CDECL* jsr_script_cache_load_cb)( -void* script_cache_data, -const char* source_url, - uint64_t source_hash, -const char* runtime_name, - uint64_t runtime_version, -const char* cache_tag, -const uint8_t** buffer, - size_t* buffer_size, -jsr_data_delete_cb* buffer_delete_cb, -void** deleter_data); - -typedef void(NAPI_CDECL* jsr_script_cache_store_cb)( -void* script_cache_data, -const char* source_url, - uint64_t source_hash, -const char* runtime_name, - uint64_t runtime_version, -const char* cache_tag, -const uint8_t* buffer, - size_t buffer_size, -jsr_data_delete_cb buffer_delete_cb, -void* deleter_data); - -JSR_API jsr_config_set_script_cache( - jsr_config config, - void* script_cache_data, - jsr_script_cache_load_cb script_cache_load_cb, - jsr_script_cache_store_cb script_cache_store_cb, - jsr_data_delete_cb script_cache_data_delete_cb, - void* deleter_data); - -//============================================================================= -// napi_env scope -//============================================================================= - -// Opens the napi_env scope in the current thread. -// Calling Node-API functions without the opened scope may cause a failure. -// The scope must be closed by the jsr_close_napi_env_scope call. -JSR_API jsr_open_napi_env_scope(napi_env env, jsr_napi_env_scope* scope); - -// Closes the napi_env scope in the current thread. It must match to the -// jsr_open_napi_env_scope call. -JSR_API jsr_close_napi_env_scope(napi_env env, jsr_napi_env_scope scope); - -//============================================================================= -// Additional functions to implement JSI -//============================================================================= - -// To implement JSI description() -JSR_API jsr_get_description(napi_env env, const char** result); - -// To implement JSI drainMicrotasks() -JSR_API -jsr_drain_microtasks(napi_env env, int32_t max_count_hint, bool* result); - -// To implement JSI isInspectable() -JSR_API jsr_is_inspectable(napi_env env, bool* result); - -//============================================================================= -// Script preparing and running. -// -// Script is usually converted to byte code, or in other words - prepared - for -// execution. Then, we can run the prepared script. -//============================================================================= - -// Run script with source URL. -JSR_API jsr_run_script(napi_env env, - napi_value source, - const char* source_url, - napi_value* result); - -// Prepare the script for running. -JSR_API jsr_create_prepared_script(napi_env env, - const uint8_t* script_data, - size_t script_length, - jsr_data_delete_cb script_delete_cb, - void* deleter_data, - const char* source_url, - jsr_prepared_script* result); - -// Delete the prepared script. -JSR_API jsr_delete_prepared_script(napi_env env, - jsr_prepared_script prepared_script); - -// Run the prepared script. -JSR_API jsr_prepared_script_run(napi_env env, - jsr_prepared_script prepared_script, - napi_value* result); - -//============================================================================= -// Functions to support unit tests. -//============================================================================= - -// Provides a hint to run garbage collection. -// It is typically used for unit tests. -// It requires enabling GC by calling jsr_config_enable_gc_api. -JSR_API jsr_collect_garbage(napi_env env); - -// Checks if the environment has an unhandled promise rejection. -JSR_API jsr_has_unhandled_promise_rejection(napi_env env, bool* result); - -// Gets and clears the last unhandled promise rejection. -JSR_API jsr_get_and_clear_last_unhandled_promise_rejection(napi_env env, - napi_value* result); - -EXTERN_C_END - -#endif // !SRC_JS_RUNTIME_API_H_ diff --git a/test-app/runtime/src/main/cpp/napi/hermes/jsr.cpp b/test-app/runtime/src/main/cpp/napi/hermes/jsr.cpp index ac10bb05..d29a1dfd 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/jsr.cpp +++ b/test-app/runtime/src/main/cpp/napi/hermes/jsr.cpp @@ -1,40 +1,27 @@ #include "jsr.h" -#include "js_runtime.h" #include "File.h" -using namespace facebook::jsi; std::unordered_map JSR::env_to_jsr_cache; -typedef struct napi_runtime__ { +typedef struct jsr_ns_runtime__ { JSR *hermes; -} napi_runtime__; - - -#ifdef __SHERMES__ -class TaskRunner : public ::hermes::node_api::TaskRunner { -public: - void post(std::unique_ptr<::hermes::node_api::Task> task) noexcept override { - printf("%s", "HERMES NAPI CALLBACK POSTED"); - } -}; -#endif +} jsr_ns_runtime__; JSR::JSR() { - #ifdef __SHERMES__ - hermes::vm::RuntimeConfig config = - hermes::vm::RuntimeConfig::Builder().withMicrotaskQueue(true).withES6BlockScoping(true).withEnableAsyncGenerators(true).build(); - #else - hermes::vm::RuntimeConfig config = - hermes::vm::RuntimeConfig::Builder().withMicrotaskQueue(true).build(); - #endif - + hermes::vm::RuntimeConfig config = + hermes::vm::RuntimeConfig::Builder() + .withMicrotaskQueue(true) + .withES6BlockScoping(true) + .withEnableAsyncGenerators(true) + .build(); + threadSafeRuntime = facebook::hermes::makeThreadSafeHermesRuntime(config); rt = (facebook::hermes::HermesRuntime *) &threadSafeRuntime->getUnsafeRuntime(); } -napi_status js_create_runtime(napi_runtime *runtime) { +napi_status js_create_runtime(jsr_ns_runtime *runtime) { if (runtime == nullptr) return napi_invalid_arg; - *runtime = new napi_runtime__(); + *runtime = new jsr_ns_runtime__(); (*runtime)->hermes = new JSR(); return napi_ok; @@ -60,13 +47,18 @@ napi_status js_unlock_env(napi_env env) { return napi_ok; } -napi_status js_create_napi_env(napi_env *env, napi_runtime runtime) { +napi_status js_create_napi_env(napi_env *env, jsr_ns_runtime runtime) { if (env == nullptr) return napi_invalid_arg; - #ifdef __SHERMES__ - *env = ::hermes::node_api::createNodeApiEnv(runtime->hermes->rt->getVMRuntimeUnsafe(), std::make_shared(), [](napi_env env, napi_value value) {}, 8); - #else - runtime->hermes->rt->createNapiEnv(env); - #endif + + // Extract the underlying hermes::vm::Runtime from the JSI HermesRuntime via + // the IHermes interface, then create the Node-API env on top of it. This is + // the same path Hermes' own tools (repl, test-runner, napi-runner) use and + // relies only on symbols exported by libhermesvm.so. + void *vmRuntime = + facebook::jsi::castInterface(runtime->hermes->rt) + ->getVMRuntimeUnsafe(); + *env = hermes_napi_create_env(vmRuntime); + JSR::env_to_jsr_cache.insert(std::make_pair(*env, runtime->hermes)); return napi_ok; } @@ -76,11 +68,13 @@ napi_status js_set_runtime_flags(const char *flags) { } napi_status js_free_napi_env(napi_env env) { + // The env is owned by the hermes::vm::Runtime and is torn down when the + // Runtime is destroyed (see js_free_runtime); we only drop our cache entry. JSR::env_to_jsr_cache.erase(env); return napi_ok; } -napi_status js_free_runtime(napi_runtime runtime) { +napi_status js_free_runtime(jsr_ns_runtime runtime) { if (runtime == nullptr) return napi_invalid_arg; runtime->hermes->threadSafeRuntime.reset(); runtime->hermes->rt = nullptr; @@ -95,25 +89,39 @@ napi_status js_execute_script(napi_env env, napi_value script, const char *file, napi_value *result) { - #ifdef __SHERMES__ - return napi_run_script_source(env, script, file, result);; - #else - return jsr_run_script(env, script, file, result); - #endif + // Pull the UTF-8 source out of the napi string value and compile+run it via + // the Hermes NAPI entry point so we can attach the source URL for stack + // traces. + size_t len = 0; + napi_status status = napi_get_value_string_utf8(env, script, nullptr, 0, &len); + if (status != napi_ok) return status; + + uint8_t *source = new uint8_t[len + 1]; + status = napi_get_value_string_utf8(env, script, reinterpret_cast(source), + len + 1, &len); + if (status != napi_ok) { + delete[] source; + return status; + } + + hermes_run_script_flags flags{}; + flags.struct_size = sizeof(flags); + // Pass size = len + 1 so the trailing '\0' lets Hermes run the source + // zero-copy. Hermes takes ownership of the buffer and frees it via the + // finalizer below. + return hermes_run_script( + env, source, len + 1, + [](const uint8_t *data, size_t, void *) { delete[] const_cast(data); }, + nullptr, file, &flags, result); } napi_status js_execute_pending_jobs(napi_env env) { - #ifdef __SHERMES__ auto itFound = JSR::env_to_jsr_cache.find(env); if (itFound == JSR::env_to_jsr_cache.end()) { return napi_invalid_arg; } itFound->second->rt->drainMicrotasks(); return napi_ok; - #else - bool result; - return jsr_drain_microtasks(env, 0, &result); - #endif } napi_status js_get_engine_ptr(napi_env env, int64_t *engine_ptr) { @@ -133,16 +141,22 @@ napi_status js_cache_script(napi_env env, const char *source, const char *file) napi_status js_run_cached_script(napi_env env, const char *file, napi_value script, void *cache, napi_value *result) { int length = 0; + // tns::File::ReadBinary allocates with new uint8_t[length]. auto data = tns::File::ReadBinary(file, length); if (!data) { return napi_cannot_run_js; } - return napi_run_bytecode(env, data, length, file, result); + hermes_bytecode_flags flags{}; + flags.struct_size = sizeof(flags); + // Hermes takes ownership of the buffer and frees it via the finalizer. + return hermes_run_bytecode( + env, static_cast(data), static_cast(length), + [](const uint8_t *d, size_t, void *) { delete[] const_cast(d); }, + nullptr, file, &flags, result); } napi_status js_get_runtime_version(napi_env env, napi_value *version) { napi_create_string_utf8(env, "Hermes", NAPI_AUTO_LENGTH, version); return napi_ok; } - diff --git a/test-app/runtime/src/main/cpp/napi/hermes/jsr.h b/test-app/runtime/src/main/cpp/napi/hermes/jsr.h index 62d39124..0d89ebe8 100644 --- a/test-app/runtime/src/main/cpp/napi/hermes/jsr.h +++ b/test-app/runtime/src/main/cpp/napi/hermes/jsr.h @@ -5,14 +5,22 @@ #ifndef TEST_APP_JSR_H #define TEST_APP_JSR_H -#include "hermes/hermes.h" -#ifdef __SHERMES__ -#include "hermes/hermes_node_api.h" -#else -#include "hermes/hermes_api.h" -#endif +#include +#include +#include +// hermes.h transitively provides everything we need on the runtime side: +// - facebook::hermes::makeThreadSafeHermesRuntime / HermesRuntime +// - facebook::hermes::IHermes (via ) +// - facebook::jsi::castInterface (via ) +// - hermes::vm::RuntimeConfig (via ) +#include "hermes/hermes.h" #include "jsi/threadsafe.h" + +// Node-API surface exported by libhermesvm.so: hermes_napi_create_env, +// hermes_run_script, hermes_run_bytecode plus the standard napi_* functions. +#include "napi/hermes_napi.h" + #include "jsr_common.h" class JSR { diff --git a/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/APICallbackFunction.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/APICallbackFunction.h new file mode 100644 index 00000000..05ee1410 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/APICallbackFunction.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2013-2020 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef APICallbackFunction_h +#define APICallbackFunction_h + +#include "APICast.h" +#include "Error.h" +#include "JSCallbackConstructor.h" +#include "JSLock.h" +#include + +namespace JSC { + +struct APICallbackFunction { + template static EncodedJSValue callImpl(JSGlobalObject*, CallFrame*); + template static EncodedJSValue constructImpl(JSGlobalObject*, CallFrame*); +}; + +template +EncodedJSValue APICallbackFunction::callImpl(JSGlobalObject* globalObject, CallFrame* callFrame) +{ + VM& vm = getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); + JSContextRef execRef = toRef(globalObject); + JSObjectRef functionRef = toRef(callFrame->jsCallee()); + JSObjectRef thisObjRef = toRef(jsCast(callFrame->thisValue().toThis(globalObject, ECMAMode::sloppy()))); + + int argumentCount = static_cast(callFrame->argumentCount()); + Vector arguments(argumentCount, [&](size_t i) { + return toRef(globalObject, callFrame->uncheckedArgument(i)); + }); + + JSValueRef exception = nullptr; + JSValueRef result; + { + JSLock::DropAllLocks dropAllLocks(globalObject); + result = jsCast(toJS(functionRef))->functionCallback()(execRef, functionRef, thisObjRef, argumentCount, arguments.span().data(), &exception); + } + if (exception) { + throwException(globalObject, scope, toJS(globalObject, exception)); + return JSValue::encode(jsUndefined()); + } + + // result must be a valid JSValue. + if (!result) + return JSValue::encode(jsUndefined()); + + return JSValue::encode(toJS(globalObject, result)); +} + +template +EncodedJSValue APICallbackFunction::constructImpl(JSGlobalObject* globalObject, CallFrame* callFrame) +{ + VM& vm = getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue callee = callFrame->jsCallee(); + T* constructor = jsCast(callFrame->jsCallee()); + JSContextRef ctx = toRef(globalObject); + JSObjectRef constructorRef = toRef(constructor); + + JSObjectCallAsConstructorCallback callback = constructor->constructCallback(); + if (callback) { + JSValue prototype; + JSValue newTarget = callFrame->newTarget(); + // If we are doing a derived class construction get the .prototype property off the new target first so we behave closer to normal JS. + if (newTarget != constructor) { + prototype = newTarget.get(globalObject, vm.propertyNames->prototype); + RETURN_IF_EXCEPTION(scope, { }); + } + + size_t argumentCount = callFrame->argumentCount(); + Vector arguments(argumentCount, [&](size_t i) { + return toRef(globalObject, callFrame->uncheckedArgument(i)); + }); + + JSValueRef exception = nullptr; + JSObjectRef result; + { + JSLock::DropAllLocks dropAllLocks(globalObject); + result = callback(ctx, constructorRef, argumentCount, arguments.span().data(), &exception); + } + + if (exception) { + throwException(globalObject, scope, toJS(globalObject, exception)); + return JSValue::encode(jsUndefined()); + } + // result must be a valid JSValue. + if (!result) + return throwVMTypeError(globalObject, scope); + + JSObject* newObject = toJS(result); + // This won't trigger proxy traps on newObject's prototype handler but that's probably desirable here anyway. + if (newTarget != constructor && newObject->getPrototypeDirect() == constructor->get(globalObject, vm.propertyNames->prototype)) { + RETURN_IF_EXCEPTION(scope, { }); + newObject->setPrototype(vm, globalObject, prototype); + RETURN_IF_EXCEPTION(scope, { }); + } + + return JSValue::encode(newObject); + } + + return JSValue::encode(toJS(JSObjectMake(ctx, jsCast(callee)->classRef(), nullptr))); +} + +} // namespace JSC + +#endif // APICallbackFunction_h diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/APICast.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/APICast.h similarity index 59% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/APICast.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/APICast.h index b2f3888b..69bea2f9 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/APICast.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/APICast.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2019 Apple Inc. All rights reserved. + * Copyright (C) 2006-2022 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,17 +23,22 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef APICast_h -#define APICast_h +#pragma once +#include + +WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN + +#include "HeapCellInlines.h" +#include "Integrity.h" #include "JSAPIValueWrapper.h" #include "JSCJSValue.h" #include "JSCJSValueInlines.h" -#include "JSGlobalObject.h" -#include "HeapCellInlines.h" + +WTF_ALLOW_UNSAFE_BUFFER_USAGE_END namespace JSC { - class ExecState; + class CallFrame; class PropertyNameArray; class VM; class JSObject; @@ -49,26 +54,26 @@ typedef struct OpaqueJSValue* JSObjectRef; /* Opaque typing convenience methods */ -inline JSC::ExecState* toJS(JSContextRef c) +inline JSC::JSGlobalObject* toJS(JSContextRef context) { - ASSERT(c); - return reinterpret_cast(const_cast(c)); + ASSERT(context); + return JSC::Integrity::audit(reinterpret_cast(const_cast(context))); } -inline JSC::ExecState* toJS(JSGlobalContextRef c) +inline JSC::JSGlobalObject* toJS(JSGlobalContextRef context) { - ASSERT(c); - return reinterpret_cast(c); + ASSERT(context); + return JSC::Integrity::audit(reinterpret_cast(context)); } inline JSC::JSGlobalObject* toJSGlobalObject(JSGlobalContextRef context) { - return toJS(context)->lexicalGlobalObject(); + return toJS(context); } -inline JSC::JSValue toJS(JSC::ExecState* exec, JSValueRef v) +inline JSC::JSValue toJS(JSC::JSGlobalObject* globalObject, JSValueRef v) { - ASSERT_UNUSED(exec, exec); + ASSERT_UNUSED(globalObject, globalObject); #if !CPU(ADDRESS64) JSC::JSCell* jsCell = reinterpret_cast(const_cast(v)); if (!jsCell) @@ -79,42 +84,53 @@ inline JSC::JSValue toJS(JSC::ExecState* exec, JSValueRef v) else result = jsCell; #else - JSC::JSValue result = bitwise_cast(v); + JSC::JSValue result = std::bit_cast(v); #endif if (!result) return JSC::jsNull(); - if (result.isCell()) - RELEASE_ASSERT(result.asCell()->methodTable(exec->vm())); + if (result.isCell()) { + JSC::Integrity::audit(result.asCell()); + RELEASE_ASSERT(result.asCell()->methodTable()); + } return result; } -inline JSC::JSValue toJSForGC(JSC::ExecState* exec, JSValueRef v) +#if CPU(ADDRESS64) +inline JSC::JSValue toJS(JSValueRef value) +{ + return JSC::Integrity::audit(std::bit_cast(value)); +} +#endif + +inline JSC::JSValue toJSForGC(JSC::JSGlobalObject* globalObject, JSValueRef v) { - ASSERT_UNUSED(exec, exec); + ASSERT_UNUSED(globalObject, globalObject); #if !CPU(ADDRESS64) JSC::JSCell* jsCell = reinterpret_cast(const_cast(v)); if (!jsCell) return JSC::JSValue(); JSC::JSValue result = jsCell; #else - JSC::JSValue result = bitwise_cast(v); + JSC::JSValue result = std::bit_cast(v); #endif - if (result && result.isCell()) - RELEASE_ASSERT(result.asCell()->methodTable(exec->vm())); + if (result && result.isCell()) { + JSC::Integrity::audit(result.asCell()); + RELEASE_ASSERT(result.asCell()->methodTable()); + } return result; } // Used in JSObjectGetPrivate as that may be called during finalization inline JSC::JSObject* uncheckedToJS(JSObjectRef o) { - return reinterpret_cast(o); + return JSC::Integrity::audit(reinterpret_cast(o)); } inline JSC::JSObject* toJS(JSObjectRef o) { JSC::JSObject* object = uncheckedToJS(o); if (object) - RELEASE_ASSERT(object->methodTable(object->vm())); + RELEASE_ASSERT(object->methodTable()); return object; } @@ -125,7 +141,7 @@ inline JSC::PropertyNameArray* toJS(JSPropertyNameAccumulatorRef a) inline JSC::VM* toJS(JSContextGroupRef g) { - return reinterpret_cast(const_cast(g)); + return JSC::Integrity::audit(reinterpret_cast(const_cast(g))); } inline JSValueRef toRef(JSC::VM& vm, JSC::JSValue v) @@ -139,34 +155,40 @@ inline JSValueRef toRef(JSC::VM& vm, JSC::JSValue v) return reinterpret_cast(v.asCell()); #else UNUSED_PARAM(vm); - return bitwise_cast(v); + return std::bit_cast(JSC::Integrity::audit(v)); #endif } -inline JSValueRef toRef(JSC::ExecState* exec, JSC::JSValue v) +inline JSValueRef toRef(JSC::JSGlobalObject* globalObject, JSC::JSValue v) { - return toRef(exec->vm(), v); + return toRef(getVM(globalObject), v); } +#if CPU(ADDRESS64) +inline JSValueRef toRefWithoutGlobalObject(JSC::JSValue v) +{ + return std::bit_cast(JSC::Integrity::audit(v)); +} +#endif + inline JSObjectRef toRef(JSC::JSObject* o) { - return reinterpret_cast(o); + return reinterpret_cast(JSC::Integrity::audit(o)); } inline JSObjectRef toRef(const JSC::JSObject* o) { - return reinterpret_cast(const_cast(o)); + return reinterpret_cast(JSC::Integrity::audit(const_cast(o))); } -inline JSContextRef toRef(JSC::ExecState* e) +inline JSContextRef toRef(JSC::JSGlobalObject* globalObject) { - return reinterpret_cast(e); + return reinterpret_cast(JSC::Integrity::audit(globalObject)); } -inline JSGlobalContextRef toGlobalRef(JSC::ExecState* e) +inline JSGlobalContextRef toGlobalRef(JSC::JSGlobalObject* globalObject) { - ASSERT(e == e->lexicalGlobalObject()->globalExec()); - return reinterpret_cast(e); + return reinterpret_cast(JSC::Integrity::audit(globalObject)); } inline JSPropertyNameAccumulatorRef toRef(JSC::PropertyNameArray* l) @@ -176,7 +198,5 @@ inline JSPropertyNameAccumulatorRef toRef(JSC::PropertyNameArray* l) inline JSContextGroupRef toRef(JSC::VM* g) { - return reinterpret_cast(g); + return reinterpret_cast(JSC::Integrity::audit(g)); } - -#endif // APICast_h diff --git a/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/APIIntegrityPrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/APIIntegrityPrivate.h new file mode 100644 index 00000000..38e7e3f4 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/APIIntegrityPrivate.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSIntegrityPrivate_h +#define JSIntegrityPrivate_h + +#include "JSContextRef.h" +#include "JSObjectRef.h" +#include "JSValueRef.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@function +@abstract Audits the integrity of the JSContextRef. +@param ctx The JSContext you want to audit. +@result JSContextRef that was passed in. +@discussion This function will crash if the audit detects any errors. + */ +JS_EXPORT JSContextRef jsAuditJSContextRef(JSContextRef ctx) JSC_API_AVAILABLE(macos(13.0), ios(16.1)); + +/*! +@function +@abstract Audits the integrity of the JSGlobalContextRef. +@param ctx The JSGlobalContextRef you want to audit. +@result JSGlobalContextRef that was passed in. +@discussion This function will crash if the audit detects any errors. + */ +JS_EXPORT JSGlobalContextRef jsAuditJSGlobalContextRef(JSGlobalContextRef ctx) JSC_API_AVAILABLE(macos(13.0), ios(16.1)); + +/*! +@function +@abstract Audits the integrity of the JSObjectRef. +@param obj The JSObjectRef you want to audit. +@result JSObjectRef that was passed in. +@discussion This function will crash if the audit detects any errors. + */ +JS_EXPORT JSObjectRef jsAuditJSObjectRef(JSObjectRef obj) JSC_API_AVAILABLE(macos(13.0), ios(16.1)); + +/*! +@function +@abstract Audits the integrity of the JSValueRef. +@param value The JSValueRef you want to audit. +@result JSValueRef that was passed in. +@discussion This function will crash if the audit detects any errors. + */ +JS_EXPORT JSValueRef jsAuditJSValueRef(JSValueRef value) JSC_API_AVAILABLE(macos(13.0), ios(16.1)); + +#ifdef __cplusplus +} +#endif + +#endif /* JSIntegrityPrivate_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/APIUtils.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/APIUtils.h similarity index 74% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/APIUtils.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/APIUtils.h index 7a5e8ba8..4d0233b2 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/APIUtils.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/APIUtils.h @@ -37,28 +37,30 @@ enum class ExceptionStatus { DidNotThrow }; -inline ExceptionStatus handleExceptionIfNeeded(JSC::CatchScope& scope, JSC::ExecState* exec, JSValueRef* returnedExceptionRef) +inline ExceptionStatus handleExceptionIfNeeded(JSC::CatchScope& scope, JSContextRef ctx, JSValueRef* returnedExceptionRef) { - if (UNLIKELY(scope.exception())) { + JSC::JSGlobalObject* globalObject = toJS(ctx); + if (scope.exception()) [[unlikely]] { JSC::Exception* exception = scope.exception(); if (returnedExceptionRef) - *returnedExceptionRef = toRef(exec, exception->value()); + *returnedExceptionRef = toRef(globalObject, exception->value()); scope.clearException(); #if ENABLE(REMOTE_INSPECTOR) - scope.vm().vmEntryGlobalObject(exec)->inspectorController().reportAPIException(exec, exception); + globalObject->inspectorController().reportAPIException(globalObject, exception); #endif return ExceptionStatus::DidThrow; } return ExceptionStatus::DidNotThrow; } -inline void setException(JSC::ExecState* exec, JSValueRef* returnedExceptionRef, JSC::JSValue exception) +inline void setException(JSContextRef ctx, JSValueRef* returnedExceptionRef, JSC::JSValue exception) { + JSC::JSGlobalObject* globalObject = toJS(ctx); if (returnedExceptionRef) - *returnedExceptionRef = toRef(exec, exception); + *returnedExceptionRef = toRef(globalObject, exception); #if ENABLE(REMOTE_INSPECTOR) - JSC::VM& vm = exec->vm(); - vm.vmEntryGlobalObject(exec)->inspectorController().reportAPIException(exec, JSC::Exception::create(vm, exception)); + JSC::VM& vm = getVM(globalObject); + globalObject->inspectorController().reportAPIException(globalObject, JSC::Exception::create(vm, exception)); #endif } diff --git a/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/ExtraSymbolsForTAPI.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/ExtraSymbolsForTAPI.h new file mode 100644 index 00000000..88e1dabe --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/ExtraSymbolsForTAPI.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "JSContextRef.h" +#include + +// MARK: JavaScriptCore + +extern "C" JS_EXPORT void JSSynchronousGarbageCollectForDebugging(JSContextRef); +extern "C" JS_EXPORT void JSSynchronousEdenCollectForDebugging(JSContextRef); + +// MARK: WTF + +namespace WTF { +// Can be removed when https://commits.webkit.org/256555@main is sufficiently +// old that all supported versions of Safari have the change. +WTF_EXPORT_PRIVATE unsigned weakRandomUint32(); +} diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSAPIGlobalObject.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSAPIGlobalObject.h similarity index 56% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSAPIGlobalObject.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSAPIGlobalObject.h index 339e5e27..cdda1fad 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSAPIGlobalObject.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSAPIGlobalObject.h @@ -1,5 +1,5 @@ -/* - * Copyright (C) 2019 Apple Inc. All rights reserved. +/** + * Copyright (C) 2019-2023 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,39 +31,35 @@ OBJC_CLASS JSScript; namespace JSC { -class JSAPIGlobalObject : public JSGlobalObject { +class JSAPIGlobalObject final : public JSGlobalObject { public: using Base = JSGlobalObject; DECLARE_EXPORT_INFO; - static const GlobalObjectMethodTable s_globalObjectMethodTable; - static JSAPIGlobalObject* create(VM& vm, Structure* structure) + static constexpr DestructionMode needsDestruction = NeedsDestruction; + template + static GCClient::IsoSubspace* subspaceFor(VM& vm) { - auto* object = new (NotNull, allocateCell(vm.heap)) JSAPIGlobalObject(vm, structure); - object->finishCreation(vm); - return object; + return vm.apiGlobalObjectSpace(); } - static Structure* createStructure(VM& vm, JSValue prototype) - { - auto* result = Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info()); - result->setTransitionWatchpointIsLikelyToBeFired(true); - return result; - } + static JSAPIGlobalObject* create(VM&, Structure*); + static Structure* createStructure(VM&, JSValue prototype); - static JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, ExecState*, JSModuleLoader*, JSString* moduleNameValue, JSValue parameters, const SourceOrigin&); - static Identifier moduleLoaderResolve(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue); - static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue); - static JSObject* moduleLoaderCreateImportMetaProperties(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSModuleRecord*, JSValue); - static JSValue moduleLoaderEvaluate(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue); + static void reportUncaughtExceptionAtEventLoop(JSGlobalObject*, Exception*); JSValue loadAndEvaluateJSScriptModule(const JSLockHolder&, JSScript *); private: - JSAPIGlobalObject(VM& vm, Structure* structure) - : Base(vm, structure, &s_globalObjectMethodTable) - { } + static const GlobalObjectMethodTable* globalObjectMethodTable(); + JSAPIGlobalObject(VM&, Structure*); + + static JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, JSModuleLoader*, JSString* moduleNameValue, JSValue parameters, const SourceOrigin&); + static Identifier moduleLoaderResolve(JSGlobalObject*, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue); + static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, JSModuleLoader*, JSValue, JSValue, JSValue); + static JSObject* moduleLoaderCreateImportMetaProperties(JSGlobalObject*, JSModuleLoader*, JSValue, JSModuleRecord*, JSValue); + static JSValue moduleLoaderEvaluate(JSGlobalObject*, JSModuleLoader*, JSValue, JSValue, JSValue, JSValue, JSValue); }; } diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSAPIValueWrapper.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSAPIValueWrapper.h similarity index 67% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSAPIValueWrapper.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSAPIValueWrapper.h index aa26082f..b0ce82c3 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSAPIValueWrapper.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSAPIValueWrapper.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003-2019 Apple Inc. All rights reserved. + * Copyright (C) 2003-2022 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -30,41 +30,40 @@ namespace JSC { class JSAPIValueWrapper final : public JSCell { - friend JSValue jsAPIValueWrapper(ExecState*, JSValue); + friend JSValue jsAPIValueWrapper(JSGlobalObject*, JSValue); public: - typedef JSCell Base; - static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; + using Base = JSCell; + static constexpr unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; - JSValue value() const { return m_value.get(); } - - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) + template + static GCClient::IsoSubspace* subspaceFor(VM& vm) { - return Structure::create(vm, globalObject, prototype, TypeInfo(APIValueWrapperType, OverridesGetPropertyNames), info()); + return vm.apiValueWrapperSpace(); } + JSValue value() const { return m_value.get(); } + + static Structure* createStructure(VM&, JSGlobalObject*, JSValue); + DECLARE_EXPORT_INFO; static JSAPIValueWrapper* create(VM& vm, JSValue value) { - JSAPIValueWrapper* wrapper = new (NotNull, allocateCell(vm.heap)) JSAPIValueWrapper(vm); - wrapper->finishCreation(vm, value); - return wrapper; - } - -protected: - void finishCreation(VM& vm, JSValue value) - { - Base::finishCreation(vm); - m_value.set(vm, this, value); + JSAPIValueWrapper* wrapper = new (NotNull, allocateCell(vm)) JSAPIValueWrapper(vm, value); + wrapper->finishCreation(vm); ASSERT(!value.isCell()); + return wrapper; } private: - JSAPIValueWrapper(VM& vm) + JSAPIValueWrapper(VM& vm, JSValue value) : JSCell(vm, vm.apiWrapperStructure.get()) + , m_value(value, WriteBarrierEarlyInit) { } + DECLARE_DEFAULT_FINISH_CREATION; + WriteBarrier m_value; }; diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSAPIWrapperObject.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSAPIWrapperObject.h similarity index 85% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSAPIWrapperObject.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSAPIWrapperObject.h index dd874dc6..947eff22 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSAPIWrapperObject.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSAPIWrapperObject.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2019 Apple Inc. All rights reserved. + * Copyright (C) 2013-2021 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,12 +33,15 @@ namespace JSC { -class JSAPIWrapperObject : public JSDestructibleObject { +class JSAPIWrapperObject : public JSNonFinalObject { public: - typedef JSDestructibleObject Base; + using Base = JSNonFinalObject; + + template + static void subspaceFor(VM&) { RELEASE_ASSERT_NOT_REACHED(); } void finishCreation(VM&); - static void visitChildren(JSCell*, JSC::SlotVisitor&); + DECLARE_VISIT_CHILDREN_WITH_MODIFIER(JS_EXPORT_PRIVATE); void* wrappedObject() { return m_wrappedObject; } void setWrappedObject(void*); diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSBase.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSBase.h similarity index 88% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSBase.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSBase.h index 01c1b286..2eaed1ff 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSBase.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSBase.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Inc. All rights reserved. + * Copyright (C) 2006 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -145,11 +145,41 @@ JS_EXPORT void JSGarbageCollect(JSContextRef ctx); /* Enable the Objective-C API for platforms with a modern runtime. NOTE: This is duplicated in VM.h. */ #if !defined(JSC_OBJC_API_ENABLED) -#if (defined(__clang__) && defined(__APPLE__) && ((defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && !defined(__i386__)) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE))) +#if (defined(__clang__) && defined(__APPLE__) && (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE))) #define JSC_OBJC_API_ENABLED 1 #else #define JSC_OBJC_API_ENABLED 0 #endif #endif +#if JSC_OBJC_API_ENABLED +#define JSC_CF_ENUM(enumName, ...) \ + typedef CF_ENUM(uint32_t, enumName) { \ + __VA_ARGS__ \ + } +#else +#define JSC_CF_ENUM(enumName, ...) \ + typedef enum { \ + __VA_ARGS__ \ + } enumName +#endif + +#if JSC_OBJC_API_ENABLED +#define JSC_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") +#define JSC_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") +#else +#define JSC_ASSUME_NONNULL_BEGIN +#define JSC_ASSUME_NONNULL_END +#endif + +#if JSC_OBJC_API_ENABLED +#define JSC_NULL_UNSPECIFIED _Null_unspecified +#define JSC_NULLABLE _Nullable +#define JSC_NONNULL _Nonnull +#else +#define JSC_NULL_UNSPECIFIED +#define JSC_NULLABLE +#define JSC_NONNULL +#endif + #endif /* JSBase_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSBaseInternal.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSBaseInternal.h similarity index 84% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSBaseInternal.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSBaseInternal.h index a274af96..d4559a50 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSBaseInternal.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSBaseInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 Apple Inc. All rights reserved. + * Copyright (C) 2019 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,13 +25,13 @@ #pragma once -#include -#include +#include "JSBase.h" +#include "WebKitAvailability.h" namespace JSC { +class CallFrame; class JSLockHolder; -class ExecState; class SourceCode; } -extern "C" JSValueRef JSEvaluateScriptInternal(const JSC::JSLockHolder&, JSC::ExecState*, JSContextRef, JSObjectRef thisObject, const JSC::SourceCode&, JSValueRef* exception); +extern "C" JSValueRef JSEvaluateScriptInternal(const JSC::JSLockHolder&, JSContextRef, JSObjectRef thisObject, const JSC::SourceCode&, JSValueRef* exception); diff --git a/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSBasePrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSBasePrivate.h new file mode 100644 index 00000000..64f0b72a --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSBasePrivate.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSBasePrivate_h +#define JSBasePrivate_h + +#include "JSBase.h" +#include "WebKitAvailability.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@function +@abstract Reports an object's non-GC memory payload to the garbage collector. +@param ctx The execution context to use. +@param size The payload's size, in bytes. +@discussion Use this function to notify the garbage collector that a GC object +owns a large non-GC memory region. Calling this function will encourage the +garbage collector to collect soon, hoping to reclaim that large non-GC memory +region. +*/ +JS_EXPORT void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) JSC_API_AVAILABLE(macos(10.6), ios(7.0)); + +JS_EXPORT void JSDisableGCTimer(void); + +#if !defined(__APPLE__) && !defined(WIN32) && !defined(_WIN32) +/*! +@function JSConfigureSignalForGC +@abstract Configure signals for GC in non-Apple and non-Windows platforms. +@param signal The signal number to use. +@result true if the signal is successfully configured, otherwise false. +@discussion Call this function before any of JSC initialization starts. Otherwise, it fails. +*/ +JS_EXPORT bool JSConfigureSignalForGC(int signal); +#endif + +/*! +@function +@abstract Produces an object with various statistics about current memory usage. +@param ctx The execution context to use. +@result An object containing GC heap status data. +@discussion Specifically, the result object has the following integer-valued fields: + heapSize: current size of heap + heapCapacity: current capacity of heap + extraMemorySize: amount of non-GC memory referenced by GC objects (included in heap size / capacity) + objectCount: current count of GC objects + protectedObjectCount: current count of protected GC objects + globalObjectCount: current count of global GC objects + protectedGlobalObjectCount: current count of protected global GC objects + objectTypeCounts: object with GC object types as keys and their current counts as values +*/ +JS_EXPORT JSObjectRef JSGetMemoryUsageStatistics(JSContextRef ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* JSBasePrivate_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCTestRunnerUtils.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCTestRunnerUtils.h similarity index 95% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCTestRunnerUtils.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCTestRunnerUtils.h index c52da524..01c2a80e 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCTestRunnerUtils.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCTestRunnerUtils.h @@ -26,8 +26,8 @@ #ifndef JSCTestRunnerUtils_h #define JSCTestRunnerUtils_h -#include -#include +#include "JSContextRef.h" +#include "JSValueRef.h" namespace JSC { diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCallbackConstructor.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCallbackConstructor.h similarity index 66% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCallbackConstructor.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCallbackConstructor.h index 3c31e07f..b6eb7238 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCallbackConstructor.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCallbackConstructor.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006-2022 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,20 +26,30 @@ #ifndef JSCallbackConstructor_h #define JSCallbackConstructor_h -#include "JSDestructibleObject.h" +#include "JSObject.h" #include "JSObjectRef.h" namespace JSC { -class JSCallbackConstructor final : public JSDestructibleObject { +#define JSCALLBACK_CONSTRUCTOR_METHOD(method) \ + WTF_VTBL_FUNCPTR_PTRAUTH_STR("JSCallbackConstructor." #method) method + +class JSCallbackConstructor final : public JSNonFinalObject { public: - typedef JSDestructibleObject Base; - static const unsigned StructureFlags = Base::StructureFlags | ImplementsHasInstance | ImplementsDefaultHasInstance; + using Base = JSNonFinalObject; + static constexpr unsigned StructureFlags = Base::StructureFlags | ImplementsHasInstance | ImplementsDefaultHasInstance; + static constexpr DestructionMode needsDestruction = NeedsDestruction; + + template + static GCClient::IsoSubspace* subspaceFor(VM& vm) + { + return vm.callbackConstructorSpace(); + } - static JSCallbackConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSClassRef classRef, JSObjectCallAsConstructorCallback callback) + static JSCallbackConstructor* create(JSGlobalObject* globalObject, Structure* structure, JSClassRef classRef, JSObjectCallAsConstructorCallback callback) { - VM& vm = exec->vm(); - JSCallbackConstructor* constructor = new (NotNull, allocateCell(vm.heap)) JSCallbackConstructor(globalObject, structure, classRef, callback); + VM& vm = getVM(globalObject); + JSCallbackConstructor* constructor = new (NotNull, allocateCell(vm)) JSCallbackConstructor(globalObject, structure, classRef, callback); constructor->finishCreation(globalObject, classRef); return constructor; } @@ -50,26 +60,27 @@ class JSCallbackConstructor final : public JSDestructibleObject { JSObjectCallAsConstructorCallback callback() const { return m_callback; } DECLARE_INFO; - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(ObjectType, StructureFlags), info()); } -protected: +private: JSCallbackConstructor(JSGlobalObject*, Structure*, JSClassRef, JSObjectCallAsConstructorCallback); void finishCreation(JSGlobalObject*, JSClassRef); -private: friend struct APICallbackFunction; - static ConstructType getConstructData(JSCell*, ConstructData&); + static CallData getConstructData(JSCell*); JSObjectCallAsConstructorCallback constructCallback() { return m_callback; } JSClassRef m_class; - JSObjectCallAsConstructorCallback m_callback; + JSObjectCallAsConstructorCallback JSCALLBACK_CONSTRUCTOR_METHOD(m_callback); }; +#undef JSCALLBACK_CONSTRUCTOR_METHOD + } // namespace JSC #endif // JSCallbackConstructor_h diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCallbackFunction.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCallbackFunction.h similarity index 87% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCallbackFunction.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCallbackFunction.h index f9e4f963..4c59e260 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCallbackFunction.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCallbackFunction.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2019 Apple Inc. All rights reserved. + * Copyright (C) 2006-2022 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,13 +31,16 @@ namespace JSC { +#define JSCALLBACK_FUNCTION_METHOD(method) \ + WTF_VTBL_FUNCPTR_PTRAUTH_STR("JSCallbackFunction." #method) method + class JSCallbackFunction final : public InternalFunction { friend struct APICallbackFunction; public: typedef InternalFunction Base; template - static IsoSubspace* subspaceFor(VM& vm) + static GCClient::IsoSubspace* subspaceFor(VM& vm) { return vm.callbackFunctionSpace(); } @@ -59,9 +62,11 @@ class JSCallbackFunction final : public InternalFunction { JSObjectCallAsFunctionCallback functionCallback() { return m_callback; } - JSObjectCallAsFunctionCallback m_callback { nullptr }; + JSObjectCallAsFunctionCallback JSCALLBACK_FUNCTION_METHOD(m_callback) { nullptr }; }; +#undef JSCALLBACK_FUNCTION_METHOD + } // namespace JSC #endif // JSCallbackFunction_h diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCallbackObject.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCallbackObject.h similarity index 55% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCallbackObject.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCallbackObject.h index d0e62528..8baf1e71 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCallbackObject.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCallbackObject.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2019 Apple Inc. All rights reserved. + * Copyright (C) 2006-2022 Apple Inc. All rights reserved. * Copyright (C) 2007 Eric Seidel * * Redistribution and use in source and binary forms, with or without @@ -27,14 +27,21 @@ #ifndef JSCallbackObject_h #define JSCallbackObject_h +#if JSC_OBJC_API_ENABLED || defined(JSC_GLIB_API_ENABLED) +#include "JSAPIWrapperObject.h" +#endif +#if defined(JSC_GLIB_API_ENABLED) +#include "JSAPIWrapperGlobalObject.h" +#endif #include "JSObjectRef.h" #include "JSValueRef.h" #include "JSObject.h" +#include namespace JSC { struct JSCallbackObjectData { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(JSCallbackObjectData); public: JSCallbackObjectData(void* privateData, JSClassRef jsClass) : privateData(privateData) @@ -69,7 +76,10 @@ struct JSCallbackObjectData { m_privateProperties->deletePrivateProperty(propertyName); } - void visitChildren(SlotVisitor& visitor) + DECLARE_VISIT_CHILDREN; + + template + void visitChildren(Visitor& visitor) { JSPrivatePropertyMap* properties = m_privateProperties.get(); if (!properties) @@ -80,7 +90,7 @@ struct JSCallbackObjectData { void* privateData; JSClassRef jsClass; struct JSPrivatePropertyMap { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(JSPrivatePropertyMap); public: JSValue getPrivateProperty(const Identifier& propertyName) const { @@ -92,20 +102,21 @@ struct JSCallbackObjectData { void setPrivateProperty(VM& vm, JSCell* owner, const Identifier& propertyName, JSValue value) { - LockHolder locker(m_lock); + Locker locker { m_lock }; WriteBarrier empty; m_propertyMap.add(propertyName.impl(), empty).iterator->value.set(vm, owner, value); } void deletePrivateProperty(const Identifier& propertyName) { - LockHolder locker(m_lock); + Locker locker { m_lock }; m_propertyMap.remove(propertyName.impl()); } - void visitChildren(SlotVisitor& visitor) + template + void visitChildren(Visitor& visitor) { - LockHolder locker(m_lock); + Locker locker { m_lock }; for (auto& pair : m_propertyMap) { if (pair.value) visitor.append(pair.value); @@ -113,7 +124,7 @@ struct JSCallbackObjectData { } private: - typedef HashMap, WriteBarrier, IdentifierRepHash> PrivatePropertyMap; + typedef UncheckedKeyHashMap, WriteBarrier, IdentifierRepHash> PrivatePropertyMap; PrivatePropertyMap m_propertyMap; Lock m_lock; }; @@ -123,43 +134,39 @@ struct JSCallbackObjectData { template class JSCallbackObject final : public Parent { -protected: - JSCallbackObject(ExecState*, Structure*, JSClassRef, void* data); - JSCallbackObject(VM&, JSClassRef, Structure*); - - void finishCreation(ExecState*); - void finishCreation(VM&); - public: - typedef Parent Base; - static const unsigned StructureFlags = Base::StructureFlags | ProhibitsPropertyCaching | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | ImplementsHasInstance | OverridesGetPropertyNames | OverridesGetCallData; + using Base = Parent; + static constexpr unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetOwnSpecialPropertyNames | OverridesGetCallData | OverridesPut | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | ImplementsHasInstance | ProhibitsPropertyCaching | GetOwnPropertySlotMayBeWrongAboutDontEnum; static_assert(!(StructureFlags & ImplementsDefaultHasInstance), "using customHasInstance"); ~JSCallbackObject(); - static JSCallbackObject* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSClassRef classRef, void* data) + static JSCallbackObject* create(JSGlobalObject* globalObject, Structure* structure, JSClassRef classRef, void* data) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); ASSERT_UNUSED(globalObject, !structure->globalObject() || structure->globalObject() == globalObject); - JSCallbackObject* callbackObject = new (NotNull, allocateCell(vm.heap)) JSCallbackObject(exec, structure, classRef, data); - callbackObject->finishCreation(exec); + JSCallbackObject* callbackObject = new (NotNull, allocateCell(vm)) JSCallbackObject(globalObject, structure, classRef, data); + callbackObject->finishCreation(globalObject); return callbackObject; } static JSCallbackObject* create(VM&, JSClassRef, Structure*); - static const bool needsDestruction; + static const DestructionMode needsDestruction; static void destroy(JSCell* cell) { static_cast(cell)->JSCallbackObject::~JSCallbackObject(); } + template + static GCClient::IsoSubspace* subspaceFor(VM& vm) + { + return subspaceForImpl(vm, mode); + } + void setPrivate(void* data); void* getPrivate(); - // FIXME: We should fix the warnings for extern-template in JSObject template classes: https://bugs.webkit.org/show_bug.cgi?id=161979 - IGNORE_CLANG_WARNINGS_BEGIN("undefined-var-template") DECLARE_INFO; - IGNORE_CLANG_WARNINGS_END JSClassRef classRef() const { return m_callbackObjectData->jsClass; } bool inherits(JSClassRef) const; @@ -183,52 +190,81 @@ class JSCallbackObject final : public Parent { using Parent::methodTable; + static EncodedJSValue callImpl(JSGlobalObject*, CallFrame*); + static EncodedJSValue constructImpl(JSGlobalObject*, CallFrame*); + static EncodedJSValue staticFunctionGetterImpl(JSGlobalObject*, EncodedJSValue, PropertyName); + static EncodedJSValue callbackGetterImpl(JSGlobalObject*, EncodedJSValue, PropertyName); + + DECLARE_VISIT_CHILDREN; + private: - static String className(const JSObject*, VM&); - static String toStringName(const JSObject*, ExecState*); + JSCallbackObject(JSGlobalObject*, Structure*, JSClassRef, void* data); + JSCallbackObject(VM&, JSClassRef, Structure*); - static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); + void finishCreation(JSGlobalObject*); + void finishCreation(VM&); - static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); - static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&); - - static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); - static bool putByIndex(JSCell*, ExecState*, unsigned, JSValue, bool shouldThrow); + static GCClient::IsoSubspace* subspaceForImpl(VM&, SubspaceAccess); + static EncodedJSValue JSC_HOST_CALL_ATTRIBUTES customToPrimitive(JSGlobalObject*, CallFrame*); - static bool deleteProperty(JSCell*, ExecState*, PropertyName); - static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned); + static bool getOwnPropertySlot(JSObject*, JSGlobalObject*, PropertyName, PropertySlot&); + static bool getOwnPropertySlotByIndex(JSObject*, JSGlobalObject*, unsigned propertyName, PropertySlot&); + + static bool put(JSCell*, JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&); + static bool putByIndex(JSCell*, JSGlobalObject*, unsigned, JSValue, bool shouldThrow); - static bool customHasInstance(JSObject*, ExecState*, JSValue); + static bool deleteProperty(JSCell*, JSGlobalObject*, PropertyName, DeletePropertySlot&); + static bool deletePropertyByIndex(JSCell*, JSGlobalObject*, unsigned); - static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + static bool customHasInstance(JSObject*, JSGlobalObject*, JSValue); - static ConstructType getConstructData(JSCell*, ConstructData&); - static CallType getCallData(JSCell*, CallData&); + static void getOwnSpecialPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, DontEnumPropertiesMode); - static void visitChildren(JSCell* cell, SlotVisitor& visitor) - { - JSCallbackObject* thisObject = jsCast(cell); - ASSERT_GC_OBJECT_INHERITS((static_cast(thisObject)), JSCallbackObject::info()); - Parent::visitChildren(thisObject, visitor); - thisObject->m_callbackObjectData->visitChildren(visitor); - } + static CallData getConstructData(JSCell*); + static CallData getCallData(JSCell*); - void init(ExecState*); + void init(JSGlobalObject*); static JSCallbackObject* asCallbackObject(JSValue); static JSCallbackObject* asCallbackObject(EncodedJSValue); + + using RawNativeFunction = EncodedJSValue(JSC_HOST_CALL_ATTRIBUTES*)(JSGlobalObject*, CallFrame*); + + static RawNativeFunction getCallFunction(); + static RawNativeFunction getConstructFunction(); + + static GetValueFunc getStaticFunctionGetter(); + static GetValueFunc getCallbackGetter(); - static EncodedJSValue JSC_HOST_CALL call(ExecState*); - static EncodedJSValue JSC_HOST_CALL construct(ExecState*); - - JSValue getStaticValue(ExecState*, PropertyName); - static EncodedJSValue staticFunctionGetter(ExecState*, EncodedJSValue, PropertyName); - static EncodedJSValue callbackGetter(ExecState*, EncodedJSValue, PropertyName); + JSValue getStaticValue(JSGlobalObject*, PropertyName); std::unique_ptr m_callbackObjectData; const ClassInfo* m_classInfo { nullptr }; }; +template +template +void JSCallbackObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + JSCallbackObject* thisObject = jsCast(cell); + ASSERT_GC_OBJECT_INHERITS((static_cast(thisObject)), JSCallbackObject::info()); + Parent::visitChildren(thisObject, visitor); + thisObject->m_callbackObjectData->visitChildren(visitor); +} + +// JSCallbackObject::info()'s forward definition triggers an undefined template var warning +// without these declarations in the same translation unit. +template<> const ClassInfo JSCallbackObject::s_info; +template<> const ClassInfo JSCallbackObject::s_info; + +#if defined(JSC_GLIB_API_ENABLED) +template<> const ClassInfo JSCallbackObject::s_info; +#endif + +#if JSC_OBJC_API_ENABLED || defined(JSC_GLIB_API_ENABLED) +template<> const ClassInfo JSCallbackObject::s_info; +#endif + } // namespace JSC // include the actual template class implementation diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCallbackObjectFunctions.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCallbackObjectFunctions.h similarity index 56% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCallbackObjectFunctions.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCallbackObjectFunctions.h index c7236339..cc6e75f1 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSCallbackObjectFunctions.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSCallbackObjectFunctions.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2019 Apple Inc. All rights reserved. + * Copyright (C) 2006-2020 Apple Inc. All rights reserved. * Copyright (C) 2007 Eric Seidel * * Redistribution and use in source and binary forms, with or without @@ -24,13 +24,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#pragma once + #include "APICast.h" #include "Error.h" #include "ExceptionHelpers.h" #include "JSCallbackFunction.h" #include "JSClassRef.h" #include "JSFunction.h" -#include "JSGlobalObject.h" #include "JSLock.h" #include "JSObjectRef.h" #include "JSString.h" @@ -43,7 +44,7 @@ namespace JSC { template inline JSCallbackObject* JSCallbackObject::asCallbackObject(JSValue value) { - ASSERT(asObject(value)->inherits(value.getObject()->vm(), info())); + ASSERT(asObject(value)->inherits(info())); return jsCast(asObject(value)); } @@ -51,13 +52,13 @@ template inline JSCallbackObject* JSCallbackObject::asCallbackObject(EncodedJSValue encodedValue) { JSValue value = JSValue::decode(encodedValue); - ASSERT(asObject(value)->inherits(value.getObject()->vm(), info())); + ASSERT(asObject(value)->inherits(info())); return jsCast(asObject(value)); } template -JSCallbackObject::JSCallbackObject(ExecState* exec, Structure* structure, JSClassRef jsClass, void* data) - : Parent(exec->vm(), structure) +JSCallbackObject::JSCallbackObject(JSGlobalObject* globalObject, Structure* structure, JSClassRef jsClass, void* data) + : Parent(getVM(globalObject), structure) , m_callbackObjectData(makeUnique(data, jsClass)) { } @@ -88,217 +89,235 @@ JSCallbackObject::~JSCallbackObject() } template -void JSCallbackObject::finishCreation(ExecState* exec) +void JSCallbackObject::finishCreation(JSGlobalObject* globalObject) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); Base::finishCreation(vm); - ASSERT(Parent::inherits(vm, info())); - init(exec); + ASSERT(Parent::inherits(info())); + init(globalObject); } // This is just for Global object, so we can assume that Base::finishCreation is JSGlobalObject::finishCreation. template void JSCallbackObject::finishCreation(VM& vm) { - ASSERT(Parent::inherits(vm, info())); + ASSERT(Parent::inherits(info())); ASSERT(Parent::isGlobalObject()); Base::finishCreation(vm); - init(jsCast(this)->globalExec()); + init(jsCast(this)); } template -void JSCallbackObject::init(ExecState* exec) +void JSCallbackObject::init(JSGlobalObject* globalObject) { - ASSERT(exec); + ASSERT(globalObject); + VM& vm = getVM(globalObject); + bool hasConvertToType = false; Vector initRoutines; JSClassRef jsClass = classRef(); do { + if (jsClass->convertToType) + hasConvertToType = true; if (JSObjectInitializeCallback initialize = jsClass->initialize) initRoutines.append(initialize); } while ((jsClass = jsClass->parentClass)); + + if (hasConvertToType) { + this->putDirect(vm, vm.propertyNames->toPrimitiveSymbol, + JSFunction::create(vm, globalObject, 1, "[Symbol.toPrimitive]"_s, customToPrimitive, ImplementationVisibility::Public), + static_cast(PropertyAttribute::DontEnum)); + } // initialize from base to derived for (int i = static_cast(initRoutines.size()) - 1; i >= 0; i--) { - JSLock::DropAllLocks dropAllLocks(exec); + // JSLock::DropAllLocks dropAllLocks(globalObject); JSObjectInitializeCallback initialize = initRoutines[i]; - initialize(toRef(exec), toRef(this)); + initialize(toRef(globalObject), toRef(jsCast(this))); } m_classInfo = this->classInfo(); } template -String JSCallbackObject::className(const JSObject* object, VM& vm) -{ - const JSCallbackObject* thisObject = jsCast(object); - String thisClassName = thisObject->classRef()->className(); - if (!thisClassName.isEmpty()) - return thisClassName; - - return Parent::className(object, vm); -} - -template -String JSCallbackObject::toStringName(const JSObject* object, ExecState* exec) +bool JSCallbackObject::getOwnPropertySlot(JSObject* object, JSGlobalObject* globalObject, PropertyName propertyName, PropertySlot& slot) { - VM& vm = exec->vm(); - const ClassInfo* info = object->classInfo(vm); - ASSERT(info); - return info->methodTable.className(object, vm); -} - -template -bool JSCallbackObject::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSCallbackObject* thisObject = jsCast(object); - JSContextRef ctx = toRef(exec); - JSObjectRef thisRef = toRef(thisObject); + JSContextRef ctx = toRef(globalObject); + JSObjectRef thisRef = toRef(jsCast(thisObject)); RefPtr propertyNameRef; if (StringImpl* name = propertyName.uid()) { + unsigned attributes = PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum; for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { // optional optimization to bypass getProperty in cases when we only need to know if the property exists if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) { if (!propertyNameRef) propertyNameRef = OpaqueJSString::tryCreate(name); - JSLock::DropAllLocks dropAllLocks(exec); + // JSLock::DropAllLocks dropAllLocks(globalObject); if (hasProperty(ctx, thisRef, propertyNameRef.get())) { - slot.setCustom(thisObject, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, callbackGetter); + slot.setCustom(thisObject, attributes, getCallbackGetter()); return true; } } else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) { if (!propertyNameRef) propertyNameRef = OpaqueJSString::tryCreate(name); - JSValueRef exception = 0; + JSValueRef exception = nullptr; JSValueRef value; - { - JSLock::DropAllLocks dropAllLocks(exec); + // { + // JSLock::DropAllLocks dropAllLocks(globalObject); value = getProperty(ctx, thisRef, propertyNameRef.get(), &exception); - } + // } if (exception) { - throwException(exec, scope, toJS(exec, exception)); - slot.setValue(thisObject, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, jsUndefined()); + throwException(globalObject, scope, toJS(globalObject, exception)); + slot.setValue(thisObject, attributes, jsUndefined()); return true; } if (value) { - slot.setValue(thisObject, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, toJS(exec, value)); + slot.setValue(thisObject, attributes, toJS(globalObject, value)); return true; } } - if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) { + if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(globalObject)) { if (staticValues->contains(name)) { - JSValue value = thisObject->getStaticValue(exec, propertyName); + JSValue value = thisObject->getStaticValue(globalObject, propertyName); + RETURN_IF_EXCEPTION(scope, false); if (value) { - slot.setValue(thisObject, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, value); + slot.setValue(thisObject, attributes, value); return true; } } } - if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) { + if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(globalObject)) { if (staticFunctions->contains(name)) { - slot.setCustom(thisObject, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum, staticFunctionGetter); + slot.setCustom(thisObject, attributes, getStaticFunctionGetter()); return true; } } } } - return Parent::getOwnPropertySlot(thisObject, exec, propertyName, slot); + bool found = Parent::getOwnPropertySlot(thisObject, globalObject, propertyName, slot); + RETURN_IF_EXCEPTION(scope, false); + if (found) + return true; + + if (propertyName.uid() == vm.propertyNames->toStringTagSymbol.impl()) { + String className = thisObject->classRef()->className(); + if (className.isEmpty()) + className = thisObject->className(); + slot.setValue(thisObject, static_cast(PropertyAttribute::DontEnum), jsString(vm, WTFMove(className))); + return true; + } + + return false; } template -bool JSCallbackObject::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned propertyName, PropertySlot& slot) +bool JSCallbackObject::getOwnPropertySlotByIndex(JSObject* object, JSGlobalObject* globalObject, unsigned propertyName, PropertySlot& slot) { - VM& vm = exec->vm(); - return object->methodTable(vm)->getOwnPropertySlot(object, exec, Identifier::from(vm, propertyName), slot); + VM& vm = getVM(globalObject); + return object->methodTable()->getOwnPropertySlot(object, globalObject, Identifier::from(vm, propertyName), slot); } template -JSValue JSCallbackObject::defaultValue(const JSObject* object, ExecState* exec, PreferredPrimitiveType hint) +EncodedJSValue JSCallbackObject::customToPrimitive(JSGlobalObject* globalObject, CallFrame* callFrame) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); - const JSCallbackObject* thisObject = jsCast(object); - JSContextRef ctx = toRef(exec); - JSObjectRef thisRef = toRef(thisObject); + JSCallbackObject* thisObject = jsDynamicCast(callFrame->thisValue()); + if (!thisObject) + return throwVMTypeError(globalObject, scope, "JSCallbackObject[Symbol.toPrimitive] method called on incompatible |this| value."_s); + PreferredPrimitiveType hint = toPreferredPrimitiveType(globalObject, callFrame->argument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + JSContextRef ctx = toRef(globalObject); + JSObjectRef thisRef = toRef(jsCast(thisObject)); ::JSType jsHint = hint == PreferString ? kJSTypeString : kJSTypeNumber; for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) { - JSValueRef exception = 0; + JSValueRef exception = nullptr; JSValueRef result = convertToType(ctx, thisRef, jsHint, &exception); - if (exception) { - throwException(exec, scope, toJS(exec, exception)); - return jsUndefined(); + if (exception) + return throwVMError(globalObject, scope, toJS(globalObject, exception)); + if (result) { + JSValue jsResult = toJS(globalObject, result); + if (jsResult.isObject()) [[unlikely]] + return JSValue::encode(asObject(jsResult)->ordinaryToPrimitive(globalObject, hint)); + return JSValue::encode(jsResult); } - if (result) - return toJS(exec, result); } } - return Parent::defaultValue(object, exec, hint); + RELEASE_AND_RETURN(scope, JSValue::encode(thisObject->ordinaryToPrimitive(globalObject, hint))); } template -bool JSCallbackObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) +bool JSCallbackObject::put(JSCell* cell, JSGlobalObject* globalObject, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSCallbackObject* thisObject = jsCast(cell); - JSContextRef ctx = toRef(exec); - JSObjectRef thisRef = toRef(thisObject); + JSContextRef ctx = toRef(globalObject); + JSObjectRef thisRef = toRef(jsCast(thisObject)); RefPtr propertyNameRef; - JSValueRef valueRef = toRef(exec, value); + JSValueRef valueRef = toRef(globalObject, value); + + if (isThisValueAltered(slot, thisObject)) [[unlikely]] + RELEASE_AND_RETURN(scope, Parent::put(thisObject, globalObject, propertyName, value, slot)); if (StringImpl* name = propertyName.uid()) { for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) { if (!propertyNameRef) propertyNameRef = OpaqueJSString::tryCreate(name); - JSValueRef exception = 0; + JSValueRef exception = nullptr; bool result; - { - JSLock::DropAllLocks dropAllLocks(exec); + // { + // JSLock::DropAllLocks dropAllLocks(globalObject); result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception); - } + // } if (exception) - throwException(exec, scope, toJS(exec, exception)); + throwException(globalObject, scope, toJS(globalObject, exception)); if (result || exception) return result; } - if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) { + if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(globalObject)) { if (StaticValueEntry* entry = staticValues->get(name)) { if (entry->attributes & kJSPropertyAttributeReadOnly) return false; if (JSObjectSetPropertyCallback setProperty = entry->setProperty) { - JSValueRef exception = 0; + JSValueRef exception = nullptr; bool result; - { - JSLock::DropAllLocks dropAllLocks(exec); + // { + // JSLock::DropAllLocks dropAllLocks(globalObject); result = setProperty(ctx, thisRef, entry->propertyNameRef.get(), valueRef, &exception); - } + // } if (exception) - throwException(exec, scope, toJS(exec, exception)); + throwException(globalObject, scope, toJS(globalObject, exception)); if (result || exception) return result; } } } - if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) { + if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(globalObject)) { if (StaticFunctionEntry* entry = staticFunctions->get(name)) { - PropertySlot getSlot(thisObject, PropertySlot::InternalMethodType::VMInquiry); - if (Parent::getOwnPropertySlot(thisObject, exec, propertyName, getSlot)) - return Parent::put(thisObject, exec, propertyName, value, slot); + PropertySlot getSlot(thisObject, PropertySlot::InternalMethodType::VMInquiry, &vm); + bool found = Parent::getOwnPropertySlot(thisObject, globalObject, propertyName, getSlot); + RETURN_IF_EXCEPTION(scope, false); + getSlot.disallowVMEntry.reset(); + if (found) + RELEASE_AND_RETURN(scope, Parent::put(thisObject, globalObject, propertyName, value, slot)); if (entry->attributes & kJSPropertyAttributeReadOnly) return false; return thisObject->JSCallbackObject::putDirect(vm, propertyName, value); // put as override property @@ -307,58 +326,58 @@ bool JSCallbackObject::put(JSCell* cell, ExecState* exec, PropertyName p } } - return Parent::put(thisObject, exec, propertyName, value, slot); + RELEASE_AND_RETURN(scope, Parent::put(thisObject, globalObject, propertyName, value, slot)); } template -bool JSCallbackObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyIndex, JSValue value, bool shouldThrow) +bool JSCallbackObject::putByIndex(JSCell* cell, JSGlobalObject* globalObject, unsigned propertyIndex, JSValue value, bool shouldThrow) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSCallbackObject* thisObject = jsCast(cell); - JSContextRef ctx = toRef(exec); - JSObjectRef thisRef = toRef(thisObject); + JSContextRef ctx = toRef(globalObject); + JSObjectRef thisRef = toRef(jsCast(thisObject)); RefPtr propertyNameRef; - JSValueRef valueRef = toRef(exec, value); + JSValueRef valueRef = toRef(globalObject, value); Identifier propertyName = Identifier::from(vm, propertyIndex); for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) { if (!propertyNameRef) propertyNameRef = OpaqueJSString::tryCreate(propertyName.impl()); - JSValueRef exception = 0; + JSValueRef exception = nullptr; bool result; - { - JSLock::DropAllLocks dropAllLocks(exec); + // { + // JSLock::DropAllLocks dropAllLocks(globalObject); result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception); - } + // } if (exception) - throwException(exec, scope, toJS(exec, exception)); + throwException(globalObject, scope, toJS(globalObject, exception)); if (result || exception) return result; } - if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) { + if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(globalObject)) { if (StaticValueEntry* entry = staticValues->get(propertyName.impl())) { if (entry->attributes & kJSPropertyAttributeReadOnly) return false; if (JSObjectSetPropertyCallback setProperty = entry->setProperty) { - JSValueRef exception = 0; + JSValueRef exception = nullptr; bool result; - { - JSLock::DropAllLocks dropAllLocks(exec); + // { + // JSLock::DropAllLocks dropAllLocks(globalObject); result = setProperty(ctx, thisRef, entry->propertyNameRef.get(), valueRef, &exception); - } + // } if (exception) - throwException(exec, scope, toJS(exec, exception)); + throwException(globalObject, scope, toJS(globalObject, exception)); if (result || exception) return result; } } } - if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) { + if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(globalObject)) { if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) { if (entry->attributes & kJSPropertyAttributeReadOnly) return false; @@ -367,18 +386,18 @@ bool JSCallbackObject::putByIndex(JSCell* cell, ExecState* exec, unsigne } } - return Parent::putByIndex(thisObject, exec, propertyIndex, value, shouldThrow); + RELEASE_AND_RETURN(scope, Parent::putByIndex(thisObject, globalObject, propertyIndex, value, shouldThrow)); } template -bool JSCallbackObject::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) +bool JSCallbackObject::deleteProperty(JSCell* cell, JSGlobalObject* globalObject, PropertyName propertyName, DeletePropertySlot& slot) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSCallbackObject* thisObject = jsCast(cell); - JSContextRef ctx = toRef(exec); - JSObjectRef thisRef = toRef(thisObject); + JSContextRef ctx = toRef(globalObject); + JSObjectRef thisRef = toRef(jsCast(thisObject)); RefPtr propertyNameRef; if (StringImpl* name = propertyName.uid()) { @@ -386,19 +405,19 @@ bool JSCallbackObject::deleteProperty(JSCell* cell, ExecState* exec, Pro if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) { if (!propertyNameRef) propertyNameRef = OpaqueJSString::tryCreate(name); - JSValueRef exception = 0; + JSValueRef exception = nullptr; bool result; - { - JSLock::DropAllLocks dropAllLocks(exec); + // { + // JSLock::DropAllLocks dropAllLocks(globalObject); result = deleteProperty(ctx, thisRef, propertyNameRef.get(), &exception); - } + // } if (exception) - throwException(exec, scope, toJS(exec, exception)); + throwException(globalObject, scope, toJS(globalObject, exception)); if (result || exception) return true; } - if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) { + if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(globalObject)) { if (StaticValueEntry* entry = staticValues->get(name)) { if (entry->attributes & kJSPropertyAttributeDontDelete) return false; @@ -406,7 +425,7 @@ bool JSCallbackObject::deleteProperty(JSCell* cell, ExecState* exec, Pro } } - if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) { + if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(globalObject)) { if (StaticFunctionEntry* entry = staticFunctions->get(name)) { if (entry->attributes & kJSPropertyAttributeDontDelete) return false; @@ -416,55 +435,63 @@ bool JSCallbackObject::deleteProperty(JSCell* cell, ExecState* exec, Pro } } - return Parent::deleteProperty(thisObject, exec, propertyName); + static_assert(std::is_final_v>, "Ensure no derived classes have custom deletePropertyByIndex implementation"); + if (std::optional index = parseIndex(propertyName)) + RELEASE_AND_RETURN(scope, Parent::deletePropertyByIndex(thisObject, globalObject, index.value())); + RELEASE_AND_RETURN(scope, Parent::deleteProperty(thisObject, globalObject, propertyName, slot)); } template -bool JSCallbackObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName) +bool JSCallbackObject::deletePropertyByIndex(JSCell* cell, JSGlobalObject* globalObject, unsigned propertyName) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); JSCallbackObject* thisObject = jsCast(cell); - return thisObject->methodTable(vm)->deleteProperty(thisObject, exec, Identifier::from(vm, propertyName)); + return JSCell::deleteProperty(thisObject, globalObject, Identifier::from(vm, propertyName)); } template -ConstructType JSCallbackObject::getConstructData(JSCell* cell, ConstructData& constructData) +CallData JSCallbackObject::getConstructData(JSCell* cell) { + CallData constructData; JSCallbackObject* thisObject = jsCast(cell); for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { if (jsClass->callAsConstructor) { - constructData.native.function = construct; - return ConstructType::Host; + constructData.type = CallData::Type::Native; + constructData.native.function = getConstructFunction(); + constructData.native.isBoundFunction = false; + constructData.native.isWasm = false; + break; } } - return ConstructType::None; + return constructData; } template -EncodedJSValue JSCallbackObject::construct(ExecState* exec) +EncodedJSValue JSCallbackObject::constructImpl(JSGlobalObject* globalObject, CallFrame* callFrame) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); - JSObject* constructor = exec->jsCallee(); - JSContextRef execRef = toRef(exec); + JSObject* constructor = callFrame->jsCallee(); + JSContextRef execRef = toRef(globalObject); JSObjectRef constructorRef = toRef(constructor); for (JSClassRef jsClass = jsCast*>(constructor)->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectCallAsConstructorCallback callAsConstructor = jsClass->callAsConstructor) { - size_t argumentCount = exec->argumentCount(); - Vector arguments; - arguments.reserveInitialCapacity(argumentCount); - for (size_t i = 0; i < argumentCount; ++i) - arguments.uncheckedAppend(toRef(exec, exec->uncheckedArgument(i))); - JSValueRef exception = 0; + size_t argumentCount = callFrame->argumentCount(); + Vector arguments(argumentCount, [&](size_t i) { + return toRef(globalObject, callFrame->uncheckedArgument(i)); + }); + JSValueRef exception = nullptr; JSObject* result; { - JSLock::DropAllLocks dropAllLocks(exec); - result = toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.data(), &exception)); + JSLock::DropAllLocks dropAllLocks(globalObject); + result = toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.span().data(), &exception)); + } + if (exception) { + throwException(globalObject, scope, toJS(globalObject, exception)); + return JSValue::encode(jsUndefined()); } - if (exception) - throwException(exec, scope, toJS(exec, exception)); return JSValue::encode(result); } } @@ -474,26 +501,24 @@ EncodedJSValue JSCallbackObject::construct(ExecState* exec) } template -bool JSCallbackObject::customHasInstance(JSObject* object, ExecState* exec, JSValue value) +bool JSCallbackObject::customHasInstance(JSObject* object, JSGlobalObject* globalObject, JSValue value) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSCallbackObject* thisObject = jsCast(object); - JSContextRef execRef = toRef(exec); - JSObjectRef thisRef = toRef(thisObject); + JSContextRef execRef = toRef(globalObject); + JSObjectRef thisRef = toRef(jsCast(thisObject)); for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectHasInstanceCallback hasInstance = jsClass->hasInstance) { - JSValueRef valueRef = toRef(exec, value); - JSValueRef exception = 0; + JSValueRef valueRef = toRef(globalObject, value); + JSValueRef exception = nullptr; bool result; - { - JSLock::DropAllLocks dropAllLocks(exec); - result = hasInstance(execRef, thisRef, valueRef, &exception); - } + // https://www.mail-archive.com/webkit-dev@lists.webkit.org/msg28769.html + result = hasInstance(execRef, thisRef, valueRef, &exception); if (exception) - throwException(exec, scope, toJS(exec, exception)); + throwException(globalObject, scope, toJS(globalObject, exception)); return result; } } @@ -501,43 +526,49 @@ bool JSCallbackObject::customHasInstance(JSObject* object, ExecState* ex } template -CallType JSCallbackObject::getCallData(JSCell* cell, CallData& callData) +CallData JSCallbackObject::getCallData(JSCell* cell) { + CallData callData; JSCallbackObject* thisObject = jsCast(cell); for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { if (jsClass->callAsFunction) { - callData.native.function = call; - return CallType::Host; + callData.type = CallData::Type::Native; + callData.native.function = getCallFunction(); + callData.native.isBoundFunction = false; + callData.native.isWasm = false; + break; } } - return CallType::None; + return callData; } template -EncodedJSValue JSCallbackObject::call(ExecState* exec) +EncodedJSValue JSCallbackObject::callImpl(JSGlobalObject* globalObject, CallFrame* callFrame) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); - JSContextRef execRef = toRef(exec); - JSObjectRef functionRef = toRef(exec->jsCallee()); - JSObjectRef thisObjRef = toRef(jsCast(exec->thisValue().toThis(exec, NotStrictMode))); + JSContextRef execRef = toRef(globalObject); + JSObjectRef functionRef = toRef(callFrame->jsCallee()); + JSObjectRef thisObjRef = toRef(jsCast(callFrame->thisValue().toThis(globalObject, ECMAMode::sloppy()))); for (JSClassRef jsClass = jsCast*>(toJS(functionRef))->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) { - size_t argumentCount = exec->argumentCount(); - Vector arguments; - arguments.reserveInitialCapacity(argumentCount); - for (size_t i = 0; i < argumentCount; ++i) - arguments.uncheckedAppend(toRef(exec, exec->uncheckedArgument(i))); - JSValueRef exception = 0; + size_t argumentCount = callFrame->argumentCount(); + Vector arguments(argumentCount, [&](size_t i) { + return toRef(globalObject, callFrame->uncheckedArgument(i)); + }); + + JSValueRef exception = nullptr; JSValue result; { - JSLock::DropAllLocks dropAllLocks(exec); - result = toJS(exec, callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception)); + JSLock::DropAllLocks dropAllLocks(globalObject); + result = toJS(globalObject, callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.span().data(), &exception)); + } + if (exception) { + throwException(globalObject, scope, toJS(globalObject, exception)); + return JSValue::encode(jsUndefined()); } - if (exception) - throwException(exec, scope, toJS(exec, exception)); return JSValue::encode(result); } } @@ -547,47 +578,45 @@ EncodedJSValue JSCallbackObject::call(ExecState* exec) } template -void JSCallbackObject::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +void JSCallbackObject::getOwnSpecialPropertyNames(JSObject* object, JSGlobalObject* globalObject, PropertyNameArray& propertyNames, DontEnumPropertiesMode mode) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); JSCallbackObject* thisObject = jsCast(object); - JSContextRef execRef = toRef(exec); - JSObjectRef thisRef = toRef(thisObject); + JSContextRef execRef = toRef(globalObject); + JSObjectRef thisRef = toRef(jsCast(thisObject)); for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames) { - JSLock::DropAllLocks dropAllLocks(exec); + JSLock::DropAllLocks dropAllLocks(globalObject); getPropertyNames(execRef, thisRef, toRef(&propertyNames)); } - if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) { + if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(globalObject)) { typedef OpaqueJSClassStaticValuesTable::const_iterator iterator; iterator end = staticValues->end(); for (iterator it = staticValues->begin(); it != end; ++it) { StringImpl* name = it->key.get(); StaticValueEntry* entry = it->value.get(); - if (entry->getProperty && (!(entry->attributes & kJSPropertyAttributeDontEnum) || mode.includeDontEnumProperties())) { + if (entry->getProperty && (mode == DontEnumPropertiesMode::Include || !(entry->attributes & kJSPropertyAttributeDontEnum))) { ASSERT(!name->isSymbol()); propertyNames.add(Identifier::fromString(vm, String(name))); } } } - if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) { + if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(globalObject)) { typedef OpaqueJSClassStaticFunctionsTable::const_iterator iterator; iterator end = staticFunctions->end(); for (iterator it = staticFunctions->begin(); it != end; ++it) { StringImpl* name = it->key.get(); StaticFunctionEntry* entry = it->value.get(); - if (!(entry->attributes & kJSPropertyAttributeDontEnum) || mode.includeDontEnumProperties()) { + if (mode == DontEnumPropertiesMode::Include || !(entry->attributes & kJSPropertyAttributeDontEnum)) { ASSERT(!name->isSymbol()); propertyNames.add(Identifier::fromString(vm, String(name))); } } } } - - Parent::getOwnNonIndexPropertyNames(thisObject, exec, propertyNames, mode); } template @@ -613,30 +642,30 @@ bool JSCallbackObject::inherits(JSClassRef c) const } template -JSValue JSCallbackObject::getStaticValue(ExecState* exec, PropertyName propertyName) +JSValue JSCallbackObject::getStaticValue(JSGlobalObject* globalObject, PropertyName propertyName) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); - JSObjectRef thisRef = toRef(this); + JSObjectRef thisRef = toRef(jsCast(this)); if (StringImpl* name = propertyName.uid()) { for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) { - if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) { + if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(globalObject)) { if (StaticValueEntry* entry = staticValues->get(name)) { if (JSObjectGetPropertyCallback getProperty = entry->getProperty) { - JSValueRef exception = 0; + JSValueRef exception = nullptr; JSValueRef value; - { - JSLock::DropAllLocks dropAllLocks(exec); - value = getProperty(toRef(exec), thisRef, entry->propertyNameRef.get(), &exception); - } + // { + // JSLock::DropAllLocks dropAllLocks(globalObject); + value = getProperty(toRef(globalObject), thisRef, entry->propertyNameRef.get(), &exception); + // } if (exception) { - throwException(exec, scope, toJS(exec, exception)); + throwException(globalObject, scope, toJS(globalObject, exception)); return jsUndefined(); } if (value) - return toJS(exec, value); + return toJS(globalObject, value); } } } @@ -647,24 +676,27 @@ JSValue JSCallbackObject::getStaticValue(ExecState* exec, PropertyName p } template -EncodedJSValue JSCallbackObject::staticFunctionGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName propertyName) +EncodedJSValue JSCallbackObject::staticFunctionGetterImpl(JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName propertyName) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSCallbackObject* thisObj = asCallbackObject(thisValue); // Check for cached or override property. - PropertySlot slot2(thisObj, PropertySlot::InternalMethodType::VMInquiry); - if (Parent::getOwnPropertySlot(thisObj, exec, propertyName, slot2)) - return JSValue::encode(slot2.getValue(exec, propertyName)); + PropertySlot slot2(thisObj, PropertySlot::InternalMethodType::VMInquiry, &vm); + bool found = Parent::getOwnPropertySlot(thisObj, globalObject, propertyName, slot2); + RETURN_IF_EXCEPTION(scope, { }); + slot2.disallowVMEntry.reset(); + if (found) + return JSValue::encode(slot2.getValue(globalObject, propertyName)); if (StringImpl* name = propertyName.uid()) { for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass) { - if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) { + if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(globalObject)) { if (StaticFunctionEntry* entry = staticFunctions->get(name)) { if (JSObjectCallAsFunctionCallback callAsFunction = entry->callAsFunction) { - JSObject* o = JSCallbackFunction::create(vm, thisObj->globalObject(vm), callAsFunction, name); + JSObject* o = JSCallbackFunction::create(vm, thisObj->globalObject(), callAsFunction, name); thisObj->putDirect(vm, propertyName, o, entry->attributes); return JSValue::encode(o); } @@ -673,18 +705,18 @@ EncodedJSValue JSCallbackObject::staticFunctionGetter(ExecState* exec, E } } - return JSValue::encode(throwException(exec, scope, createReferenceError(exec, "Static function property defined with NULL callAsFunction callback."_s))); + return JSValue::encode(throwException(globalObject, scope, createReferenceError(globalObject, "Static function property defined with NULL callAsFunction callback."_s))); } template -EncodedJSValue JSCallbackObject::callbackGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName propertyName) +EncodedJSValue JSCallbackObject::callbackGetterImpl(JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName propertyName) { - VM& vm = exec->vm(); + VM& vm = getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSCallbackObject* thisObj = asCallbackObject(thisValue); - JSObjectRef thisRef = toRef(thisObj); + JSObjectRef thisRef = toRef(jsCast(thisObj)); RefPtr propertyNameRef; if (StringImpl* name = propertyName.uid()) { @@ -692,23 +724,23 @@ EncodedJSValue JSCallbackObject::callbackGetter(ExecState* exec, Encoded if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) { if (!propertyNameRef) propertyNameRef = OpaqueJSString::tryCreate(name); - JSValueRef exception = 0; + JSValueRef exception = nullptr; JSValueRef value; - { - JSLock::DropAllLocks dropAllLocks(exec); - value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception); - } + // { + // JSLock::DropAllLocks dropAllLocks(globalObject); + value = getProperty(toRef(globalObject), thisRef, propertyNameRef.get(), &exception); + // } if (exception) { - throwException(exec, scope, toJS(exec, exception)); + throwException(globalObject, scope, toJS(globalObject, exception)); return JSValue::encode(jsUndefined()); } if (value) - return JSValue::encode(toJS(exec, value)); + return JSValue::encode(toJS(globalObject, value)); } } } - return JSValue::encode(throwException(exec, scope, createReferenceError(exec, "hasProperty callback returned true for a property that doesn't exist."_s))); + return JSValue::encode(throwException(globalObject, scope, createReferenceError(globalObject, "hasProperty callback returned true for a property that doesn't exist."_s))); } } // namespace JSC diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSClassRef.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSClassRef.h similarity index 60% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSClassRef.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSClassRef.h index 0dd0dca5..203cf10f 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSClassRef.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSClassRef.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Inc. All rights reserved. + * Copyright (C) 2006-2022 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,15 +26,18 @@ #ifndef JSClassRef_h #define JSClassRef_h +#include "JSObjectRef.h" #include "OpaqueJSString.h" #include "Protect.h" #include "Weak.h" -#include #include #include +#define STATIC_VALUE_ENTRY_METHOD(method) \ + WTF_VTBL_FUNCPTR_PTRAUTH_STR("StaticValueEntry." #method) method + struct StaticValueEntry { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(StaticValueEntry); public: StaticValueEntry(JSObjectGetPropertyCallback _getProperty, JSObjectSetPropertyCallback _setProperty, JSPropertyAttributes _attributes, String& propertyName) : getProperty(_getProperty) @@ -44,33 +47,40 @@ struct StaticValueEntry { { } - JSObjectGetPropertyCallback getProperty; - JSObjectSetPropertyCallback setProperty; + JSObjectGetPropertyCallback STATIC_VALUE_ENTRY_METHOD(getProperty); + JSObjectSetPropertyCallback STATIC_VALUE_ENTRY_METHOD(setProperty); JSPropertyAttributes attributes; RefPtr propertyNameRef; }; +#undef STATIC_VALUE_ENTRY_METHOD + +#define STATIC_FUNCTION_ENTRY_METHOD(method) \ + WTF_VTBL_FUNCPTR_PTRAUTH_STR("StaticFunctionEntry." #method) method + struct StaticFunctionEntry { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(StaticFunctionEntry); public: StaticFunctionEntry(JSObjectCallAsFunctionCallback _callAsFunction, JSPropertyAttributes _attributes) : callAsFunction(_callAsFunction), attributes(_attributes) { } - JSObjectCallAsFunctionCallback callAsFunction; + JSObjectCallAsFunctionCallback STATIC_FUNCTION_ENTRY_METHOD(callAsFunction); JSPropertyAttributes attributes; }; -typedef HashMap, std::unique_ptr> OpaqueJSClassStaticValuesTable; -typedef HashMap, std::unique_ptr> OpaqueJSClassStaticFunctionsTable; +#undef STATIC_FUNCTION_ENTRY_METHOD + +typedef UncheckedKeyHashMap, std::unique_ptr> OpaqueJSClassStaticValuesTable; +typedef UncheckedKeyHashMap, std::unique_ptr> OpaqueJSClassStaticFunctionsTable; struct OpaqueJSClass; // An OpaqueJSClass (JSClass) is created without a context, so it can be used with any context, even across context groups. // This structure holds data members that vary across context groups. struct OpaqueJSClassContextData { - WTF_MAKE_NONCOPYABLE(OpaqueJSClassContextData); WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_NONCOPYABLE(OpaqueJSClassContextData); WTF_DEPRECATED_MAKE_FAST_ALLOCATED(OpaqueJSClassContextData); public: OpaqueJSClassContextData(JSC::VM&, OpaqueJSClass*); @@ -82,35 +92,38 @@ struct OpaqueJSClassContextData { // 4. When it is used, the old context data is found in VM and used. RefPtr m_class; - std::unique_ptr staticValues; - std::unique_ptr staticFunctions; + OpaqueJSClassStaticValuesTable staticValues; + OpaqueJSClassStaticFunctionsTable staticFunctions; JSC::Weak cachedPrototype; }; +#define OPAQUE_JSCLASS_METHOD(method) \ + WTF_VTBL_FUNCPTR_PTRAUTH_STR("OpaqueJSClass." #method) method + struct OpaqueJSClass : public ThreadSafeRefCounted { static Ref create(const JSClassDefinition*); static Ref createNoAutomaticPrototype(const JSClassDefinition*); JS_EXPORT_PRIVATE ~OpaqueJSClass(); String className(); - OpaqueJSClassStaticValuesTable* staticValues(JSC::ExecState*); - OpaqueJSClassStaticFunctionsTable* staticFunctions(JSC::ExecState*); - JSC::JSObject* prototype(JSC::ExecState*); + OpaqueJSClassStaticValuesTable* staticValues(JSC::JSGlobalObject*); + OpaqueJSClassStaticFunctionsTable* staticFunctions(JSC::JSGlobalObject*); + JSC::JSObject* prototype(JSC::JSGlobalObject*); OpaqueJSClass* parentClass; OpaqueJSClass* prototypeClass; - JSObjectInitializeCallback initialize; - JSObjectFinalizeCallback finalize; - JSObjectHasPropertyCallback hasProperty; - JSObjectGetPropertyCallback getProperty; - JSObjectSetPropertyCallback setProperty; - JSObjectDeletePropertyCallback deleteProperty; - JSObjectGetPropertyNamesCallback getPropertyNames; - JSObjectCallAsFunctionCallback callAsFunction; - JSObjectCallAsConstructorCallback callAsConstructor; - JSObjectHasInstanceCallback hasInstance; - JSObjectConvertToTypeCallback convertToType; + JSObjectInitializeCallback OPAQUE_JSCLASS_METHOD(initialize); + JSObjectFinalizeCallback OPAQUE_JSCLASS_METHOD(finalize); + JSObjectHasPropertyCallback OPAQUE_JSCLASS_METHOD(hasProperty); + JSObjectGetPropertyCallback OPAQUE_JSCLASS_METHOD(getProperty); + JSObjectSetPropertyCallback OPAQUE_JSCLASS_METHOD(setProperty); + JSObjectDeletePropertyCallback OPAQUE_JSCLASS_METHOD(deleteProperty); + JSObjectGetPropertyNamesCallback OPAQUE_JSCLASS_METHOD(getPropertyNames); + JSObjectCallAsFunctionCallback OPAQUE_JSCLASS_METHOD(callAsFunction); + JSObjectCallAsConstructorCallback OPAQUE_JSCLASS_METHOD(callAsConstructor); + JSObjectHasInstanceCallback OPAQUE_JSCLASS_METHOD(hasInstance); + JSObjectConvertToTypeCallback OPAQUE_JSCLASS_METHOD(convertToType); private: friend struct OpaqueJSClassContextData; @@ -119,12 +132,14 @@ struct OpaqueJSClass : public ThreadSafeRefCounted { OpaqueJSClass(const OpaqueJSClass&); OpaqueJSClass(const JSClassDefinition*, OpaqueJSClass* protoClass); - OpaqueJSClassContextData& contextData(JSC::ExecState*); + OpaqueJSClassContextData& contextData(JSC::JSGlobalObject*); // Strings in these data members should not be put into any AtomStringTable. String m_className; - std::unique_ptr m_staticValues; - std::unique_ptr m_staticFunctions; + OpaqueJSClassStaticValuesTable m_staticValues; + OpaqueJSClassStaticFunctionsTable m_staticFunctions; }; +#undef OPAQUE_JSCLASS_METHOD + #endif // JSClassRef_h diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContext.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContext.h similarity index 93% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContext.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContext.h index 6b9c5d41..8e744288 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContext.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContext.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2019 Apple Inc. All rights reserved. + * Copyright (C) 2013-2024 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,10 +26,10 @@ #ifndef JSContext_h #define JSContext_h -#include -#include +#include "JavaScript.h" +#include "WebKitAvailability.h" -#if JSC_OBJC_API_ENABLED +#if defined(__OBJC__) && JSC_OBJC_API_ENABLED @class JSScript, JSVirtualMachine, JSValue, JSContext; @@ -174,9 +174,16 @@ JSC_CLASS_AVAILABLE(macos(10.9), ios(7.0)) /*! @property -@discussion Name of the JSContext. Exposed when remote debugging the context. +@discussion Name of the JSContext. Exposed when inspecting the context. */ @property (copy) NSString *name JSC_API_AVAILABLE(macos(10.10), ios(8.0)); + +/*! +@property +@discussion Controls whether this @link JSContext @/link is inspectable in Web Inspector. The default value is NO. +*/ +@property (nonatomic, getter=isInspectable) BOOL inspectable JSC_API_AVAILABLE(macos(13.3), ios(16.4)) NS_SWIFT_NAME(isInspectable); + @end /*! @@ -235,4 +242,4 @@ JSC_CLASS_AVAILABLE(macos(10.9), ios(7.0)) #endif -#endif // JSContext_h +#endif /* JSContext_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextInternal.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextInternal.h similarity index 96% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextInternal.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextInternal.h index 958c479f..44c5f58e 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextInternal.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextInternal.h @@ -32,12 +32,12 @@ struct CallbackData { CallbackData* next; JSContext *context; - JSValue *preservedException; + RetainPtr preservedException; JSValueRef calleeValue; JSValueRef thisValue; size_t argumentCount; const JSValueRef *arguments; - NSArray *currentArguments; + RetainPtr currentArguments; }; @class JSWrapperMap; diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextPrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextPrivate.h similarity index 94% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextPrivate.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextPrivate.h index 75f526b9..eafc8791 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextPrivate.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextPrivate.h @@ -69,7 +69,7 @@ @property @discussion Remote inspection setting of the JSContext. Default value is YES. */ -@property (setter=_setRemoteInspectionEnabled:) BOOL _remoteInspectionEnabled JSC_API_AVAILABLE(macos(10.10), ios(8.0)); +@property (setter=_setRemoteInspectionEnabled:) BOOL _remoteInspectionEnabled JSC_API_DEPRECATED_WITH_REPLACEMENT("inspectable", macos(10.10, 13.3), ios(8.0, 16.4)); /*! @property @@ -106,6 +106,12 @@ */ - (JSValue *)dependencyIdentifiersForModuleJSScript:(JSScript *)script JSC_API_AVAILABLE(macos(10.15), ios(13.0)); +/*! + @method + @abstract Mark this JSContext as an ITMLKit context for the purposes of remote inspection capabilities. + */ +- (void)_setITMLDebuggableType JSC_API_AVAILABLE(macos(11.0), ios(14.0)); + @end #endif diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextRef.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextRef.h similarity index 84% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextRef.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextRef.h index 1ce74358..439cdd71 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextRef.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextRef.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Inc. All rights reserved. + * Copyright (C) 2006 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,9 +26,9 @@ #ifndef JSContextRef_h #define JSContextRef_h -#include -#include -#include +#include "JSObjectRef.h" +#include "JSValueRef.h" +#include "WebKitAvailability.h" #ifndef __cplusplus #include @@ -143,19 +143,34 @@ JS_EXPORT JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx) JSC_API @abstract Gets a copy of the name of a context. @param ctx The JSGlobalContext whose name you want to get. @result The name for ctx. -@discussion A JSGlobalContext's name is exposed for remote debugging to make it -easier to identify the context you would like to attach to. +@discussion A JSGlobalContext's name is exposed when inspecting the context to make it easier to identify the context you would like to inspect. */ JS_EXPORT JSStringRef JSGlobalContextCopyName(JSGlobalContextRef ctx) JSC_API_AVAILABLE(macos(10.10), ios(8.0)); /*! @function -@abstract Sets the remote debugging name for a context. +@abstract Sets the name exposed when inspecting a context. @param ctx The JSGlobalContext that you want to name. -@param name The remote debugging name to set on ctx. +@param name The name to set on the context. */ JS_EXPORT void JSGlobalContextSetName(JSGlobalContextRef ctx, JSStringRef name) JSC_API_AVAILABLE(macos(10.10), ios(8.0)); +/*! +@function +@abstract Gets whether the context is inspectable in Web Inspector. +@param ctx The JSGlobalContext that you want to change the inspectability of. +@result Whether the context is inspectable in Web Inspector. +*/ +JS_EXPORT bool JSGlobalContextIsInspectable(JSGlobalContextRef ctx) JSC_API_AVAILABLE(macos(13.3), ios(16.4)); + +/*! +@function +@abstract Sets whether the context is inspectable in Web Inspector. Default value is NO. +@param ctx The JSGlobalContext that you want to change the inspectability of. +@param inspectable YES to allow Web Inspector to connect to the context, otherwise NO. +*/ +JS_EXPORT void JSGlobalContextSetInspectable(JSGlobalContextRef ctx, bool inspectable) JSC_API_AVAILABLE(macos(13.3), ios(16.4)); + #ifdef __cplusplus } #endif diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextRefInspectorSupport.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextRefInspectorSupport.h similarity index 97% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextRefInspectorSupport.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextRefInspectorSupport.h index a09d828b..06ef1415 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextRefInspectorSupport.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextRefInspectorSupport.h @@ -30,7 +30,7 @@ #error Requires C++ Support. #endif -#include +#include "JSContextRefPrivate.h" namespace Inspector { class AugmentableInspectorController; diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextRefInternal.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextRefInternal.h similarity index 97% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextRefInternal.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextRefInternal.h index 149f70ba..0dd994c7 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextRefInternal.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextRefInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextRefPrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextRefPrivate.h similarity index 74% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextRefPrivate.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextRefPrivate.h index 6ae649ef..c009bb5a 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSContextRefPrivate.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSContextRefPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,9 +26,9 @@ #ifndef JSContextRefPrivate_h #define JSContextRefPrivate_h -#include -#include -#include +#include "JSObjectRef.h" +#include "JSValueRef.h" +#include "WebKitAvailability.h" #ifndef __cplusplus #include @@ -94,6 +94,31 @@ JS_EXPORT void JSContextGroupSetExecutionTimeLimit(JSContextGroupRef group, doub */ JS_EXPORT void JSContextGroupClearExecutionTimeLimit(JSContextGroupRef group) JSC_API_AVAILABLE(macos(10.6), ios(7.0)); +/*! +@function +@abstract Enables sampling profiler. +@param group The JavaScript context group to start sampling. +@result The value of the enablement, true if the sampling profiler gets enabled, otherwise false. +@discussion Remote inspection is true by default. +*/ +JS_EXPORT bool JSContextGroupEnableSamplingProfiler(JSContextGroupRef group) JSC_API_AVAILABLE(macos(14.2), ios(17.2)); + +/*! +@function +@abstract Disables sampling profiler. +@param group The JavaScript context group to stop sampling. +*/ +JS_EXPORT void JSContextGroupDisableSamplingProfiler(JSContextGroupRef group) JSC_API_AVAILABLE(macos(14.2), ios(17.2)); + +/*! +@function +@abstract Gets sampling profiler output in JSON form and clears the sampling profiler records. +@param group The JavaScript context group whose sampling profile output is taken. +@result The sampling profiler output in JSON form. NULL if sampling profiler is not enabled ever before. +@discussion Calling this function clears the sampling data accumulated so far. +*/ +JS_EXPORT JSStringRef JSContextGroupTakeSamplesFromSamplingProfiler(JSContextGroupRef group) JSC_API_AVAILABLE(macos(14.2), ios(17.2)); + /*! @function @abstract Gets a whether or not remote inspection is enabled on the context. @@ -101,7 +126,7 @@ JS_EXPORT void JSContextGroupClearExecutionTimeLimit(JSContextGroupRef group) JS @result The value of the setting, true if remote inspection is enabled, otherwise false. @discussion Remote inspection is true by default. */ -JS_EXPORT bool JSGlobalContextGetRemoteInspectionEnabled(JSGlobalContextRef ctx) JSC_API_AVAILABLE(macos(10.10), ios(8.0)); +JS_EXPORT bool JSGlobalContextGetRemoteInspectionEnabled(JSGlobalContextRef ctx) JSC_API_DEPRECATED_WITH_REPLACEMENT("JSGlobalContextIsInspectable", macos(10.10, 13.3), ios(8.0, 16.4)); /*! @function @@ -109,7 +134,7 @@ JS_EXPORT bool JSGlobalContextGetRemoteInspectionEnabled(JSGlobalContextRef ctx) @param ctx The JSGlobalContext that you want to change. @param enabled The new remote inspection enabled setting for the context. */ -JS_EXPORT void JSGlobalContextSetRemoteInspectionEnabled(JSGlobalContextRef ctx, bool enabled) JSC_API_AVAILABLE(macos(10.10), ios(8.0)); +JS_EXPORT void JSGlobalContextSetRemoteInspectionEnabled(JSGlobalContextRef ctx, bool enabled) JSC_API_DEPRECATED_WITH_REPLACEMENT("JSGlobalContextSetInspectable", macos(10.10, 13.3), ios(8.0, 16.4)); /*! @function @@ -136,7 +161,16 @@ JS_EXPORT void JSGlobalContextSetIncludesNativeCallStackWhenReportingExceptions( @param function The callback function to set, which receives the promise and rejection reason as arguments. @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. */ -JS_EXPORT void JSGlobalContextSetUnhandledRejectionCallback(JSGlobalContextRef ctx, JSObjectRef function, JSValueRef* exception) JSC_API_AVAILABLE(macos(JSC_MAC_TBA), ios(JSC_IOS_TBA)); +JS_EXPORT void JSGlobalContextSetUnhandledRejectionCallback(JSGlobalContextRef ctx, JSObjectRef function, JSValueRef* exception) JSC_API_AVAILABLE(macos(10.15.4), ios(13.4)); + +/*! +@function +@abstract Sets whether a context allows use of eval (or the Function constructor). +@param ctx The JSGlobalContext that you want to change. +@param enabled The new eval enabled setting for the context. +@param message The error message to display when user attempts to call eval (or the Function constructor). Pass NULL when setting enabled to true. +*/ +JS_EXPORT void JSGlobalContextSetEvalEnabled(JSGlobalContextRef ctx, bool enabled, JSStringRef message) JSC_API_AVAILABLE(macos(12.3), ios(15.4)); #ifdef __cplusplus } diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSExport.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSExport.h similarity index 96% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSExport.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSExport.h index 5caace64..0059f59e 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSExport.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSExport.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013-2024 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,9 +23,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import +#ifndef JSExport_h +#define JSExport_h -#if JSC_OBJC_API_ENABLED +#include "JavaScriptCore.h" + +#if defined(__OBJC__) && JSC_OBJC_API_ENABLED /*! @protocol @@ -144,3 +147,5 @@ @optional Selector __JS_EXPORT_AS__##PropertyName:(id)argument; @required Selector #endif + +#endif /* JSExport_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSHeapFinalizerPrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSHeapFinalizerPrivate.h similarity index 94% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSHeapFinalizerPrivate.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSHeapFinalizerPrivate.h index 8c9b1525..7cab44a9 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSHeapFinalizerPrivate.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSHeapFinalizerPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Apple Inc. All rights reserved. + * Copyright (C) 2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,7 +26,7 @@ #ifndef JSHeapFinalizerPrivate_h #define JSHeapFinalizerPrivate_h -#include +#include "JSBase.h" #include #ifdef __cplusplus diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSBasePrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSLockRefPrivate.h similarity index 63% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSBasePrivate.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSLockRefPrivate.h index 2fc916b7..bc3d3e65 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSBasePrivate.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSLockRefPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2020 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,35 +20,33 @@ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSBasePrivate_h -#define JSBasePrivate_h +#pragma once -#include -#include +#include "JSBase.h" #ifdef __cplusplus extern "C" { #endif /*! -@function -@abstract Reports an object's non-GC memory payload to the garbage collector. -@param ctx The execution context to use. -@param size The payload's size, in bytes. -@discussion Use this function to notify the garbage collector that a GC object -owns a large non-GC memory region. Calling this function will encourage the -garbage collector to collect soon, hoping to reclaim that large non-GC memory -region. -*/ -JS_EXPORT void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) JSC_API_AVAILABLE(macos(10.6), ios(7.0)); + @function + @abstract Acquire the API lock for the given JSContextRef. + @param ctx The execution context to be locked. + @discussion The lock has to be held to perform any interactions with the JSContextRef. This function allows holding the lock across multiple interactions to amortize the cost. This lock is a recursive lock. + */ +JS_EXPORT void JSLock(JSContextRef ctx); -JS_EXPORT void JSDisableGCTimer(void); +/*! + @function + @abstract Release the API lock for the given JSContextRef. + @param ctx The execution context to be unlocked. + @discussion Releases the lock that was previously acquired using JSLock. + */ +JS_EXPORT void JSUnlock(JSContextRef ctx); #ifdef __cplusplus } #endif - -#endif /* JSBasePrivate_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSManagedValue.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSManagedValue.h similarity index 92% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSManagedValue.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSManagedValue.h index 3ebc7a4b..fd5f8bcb 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSManagedValue.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSManagedValue.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013-2024 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,10 +26,10 @@ #ifndef JSManagedValue_h #define JSManagedValue_h -#import -#import +#include "JSBase.h" +#include "WebKitAvailability.h" -#if JSC_OBJC_API_ENABLED +#if defined(__OBJC__) && JSC_OBJC_API_ENABLED @class JSValue; @class JSContext; @@ -76,6 +76,6 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @end -#endif // JSC_OBJC_API_ENABLED +#endif -#endif // JSManagedValue_h +#endif /* JSManagedValue_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSManagedValueInternal.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSManagedValueInternal.h similarity index 97% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSManagedValueInternal.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSManagedValueInternal.h index 2443fe5a..e2ba5738 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSManagedValueInternal.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSManagedValueInternal.h @@ -27,6 +27,7 @@ #define JSManagedValueInternal_h #import +#import #if JSC_OBJC_API_ENABLED diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSMarkingConstraintPrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSMarkingConstraintPrivate.h similarity index 95% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSMarkingConstraintPrivate.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSMarkingConstraintPrivate.h index aaf85cad..d3ee3753 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSMarkingConstraintPrivate.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSMarkingConstraintPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Apple Inc. All rights reserved. + * Copyright (C) 2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,7 +26,7 @@ #ifndef JSMarkingConstraintPrivate_h #define JSMarkingConstraintPrivate_h -#include +#include "JSContextRef.h" #include #ifdef __cplusplus diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSObjectRef.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSObjectRef.h similarity index 98% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSObjectRef.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSObjectRef.h index 330f5e3b..f73332e9 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSObjectRef.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSObjectRef.h @@ -27,9 +27,9 @@ #ifndef JSObjectRef_h #define JSObjectRef_h -#include -#include -#include +#include "JSBase.h" +#include "JSValueRef.h" +#include "WebKitAvailability.h" #ifndef __cplusplus #include @@ -339,6 +339,8 @@ JSStaticValue StaticValueArray[] = { Standard JavaScript practice calls for storing function objects in prototypes, so they can be shared. The default JSClass created by JSClassCreate follows this idiom, instantiating objects with a shared, automatically generating prototype containing the class's function objects. The kJSClassAttributeNoAutomaticPrototype attribute specifies that a JSClass should not automatically generate such a prototype. The resulting JSClass instantiates objects with the default object prototype, and gives each instance object its own copy of the class's function objects. A NULL callback specifies that the default object callback should substitute, except in the case of hasProperty, where it specifies that getProperty should substitute. + +It is not possible to use JS subclassing with objects created from a class definition that sets callAsConstructor by default. Subclassing is supported via the JSObjectMakeConstructor function, however. */ typedef struct { int version; /* current (and only) version is 0 */ @@ -426,7 +428,7 @@ JS_EXPORT JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStrin @param jsClass A JSClass that is the class your constructor will assign to the objects its constructs. jsClass will be used to set the constructor's .prototype property, and to evaluate 'instanceof' expressions. Pass NULL to use the default object class. @param callAsConstructor A JSObjectCallAsConstructorCallback to invoke when your constructor is used in a 'new' expression. Pass NULL to use the default object constructor. @result A JSObject that is a constructor. The object's prototype will be the default object prototype. -@discussion The default object constructor takes no arguments and constructs an object of class jsClass with no private data. +@discussion The default object constructor takes no arguments and constructs an object of class jsClass with no private data. If the constructor is inherited via JS subclassing and the value returned from callAsConstructor was created with jsClass, then the returned object will have it's prototype overridden to the derived class's prototype. */ JS_EXPORT JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor); diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSObjectRefPrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSObjectRefPrivate.h similarity index 98% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSObjectRefPrivate.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSObjectRefPrivate.h index 6e32612e..d12077c6 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSObjectRefPrivate.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSObjectRefPrivate.h @@ -26,7 +26,7 @@ #ifndef JSObjectRefPrivate_h #define JSObjectRefPrivate_h -#include +#include "JSObjectRef.h" #ifdef __cplusplus extern "C" { diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSRemoteInspector.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSRemoteInspector.h similarity index 81% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSRemoteInspector.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSRemoteInspector.h index 85768e4d..9c6fcc62 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSRemoteInspector.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSRemoteInspector.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2023 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,10 +26,11 @@ #ifndef JSRemoteInspector_h #define JSRemoteInspector_h -#include -#include +#include "JSBase.h" +#include "WebKitAvailability.h" #if defined(WIN32) || defined(_WIN32) +#include typedef int JSProcessID; #else #include @@ -47,7 +48,10 @@ JS_EXPORT void JSRemoteInspectorSetParentProcessInformation(JSProcessID, const u JS_EXPORT void JSRemoteInspectorSetLogToSystemConsole(bool) JSC_API_AVAILABLE(macos(10.11), ios(9.0)); JS_EXPORT bool JSRemoteInspectorGetInspectionEnabledByDefault(void) JSC_API_AVAILABLE(macos(10.11), ios(9.0)); -JS_EXPORT void JSRemoteInspectorSetInspectionEnabledByDefault(bool) JSC_API_AVAILABLE(macos(10.11), ios(9.0)); +JS_EXPORT void JSRemoteInspectorSetInspectionEnabledByDefault(bool) JSC_API_DEPRECATED("Use JSGlobalContextSetInspectable on a single JSGlobalContextRef.", macos(10.11, 13.3), ios(9.0, 16.4)); + +JS_EXPORT bool JSRemoteInspectorGetInspectionFollowsInternalPolicies(void) JSC_API_AVAILABLE(macos(13.3), ios(16.4)); +JS_EXPORT void JSRemoteInspectorSetInspectionFollowsInternalPolicies(bool) JSC_API_AVAILABLE(macos(13.3), ios(16.4)); #ifdef __cplusplus } diff --git a/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSRemoteInspectorServer.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSRemoteInspectorServer.h new file mode 100644 index 00000000..2bbcf899 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSRemoteInspectorServer.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 Sony Interactive Entertainment Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSRemoteInspectorServer_h +#define JSRemoteInspectorServer_h + +#include "JSBase.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +JS_EXPORT uint16_t JSRemoteInspectorServerStart(const char* address, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif /* JSRemoteInspectorServer_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSRetainPtr.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSRetainPtr.h similarity index 88% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSRetainPtr.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSRetainPtr.h index fd8412f3..4a4b1622 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSRetainPtr.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSRetainPtr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Apple Inc. All rights reserved. + * Copyright (C) 2005-2020 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,14 +28,18 @@ #pragma once -#include -#include +#include "JSContextRef.h" +#include "JSObjectRef.h" +#include "JSStringRef.h" #include +#include -inline void JSRetain(JSStringRef string) { JSStringRetain(string); } -inline void JSRelease(JSStringRef string) { JSStringRelease(string); } +inline void JSRetain(JSClassRef context) { JSClassRetain(context); } +inline void JSRelease(JSClassRef context) { JSClassRelease(context); } inline void JSRetain(JSGlobalContextRef context) { JSGlobalContextRetain(context); } inline void JSRelease(JSGlobalContextRef context) { JSGlobalContextRelease(context); } +inline void JSRetain(JSStringRef string) { JSStringRetain(string); } +inline void JSRelease(JSStringRef string) { JSStringRelease(string); } enum AdoptTag { Adopt }; @@ -74,6 +78,7 @@ template class JSRetainPtr { T m_ptr { nullptr }; }; +JSRetainPtr adopt(JSClassRef); JSRetainPtr adopt(JSStringRef); JSRetainPtr adopt(JSGlobalContextRef); @@ -82,6 +87,11 @@ template inline JSRetainPtr::JSRetainPtr(AdoptTag, T ptr) { } +inline JSRetainPtr adopt(JSClassRef o) +{ + return JSRetainPtr(Adopt, o); +} + inline JSRetainPtr adopt(JSStringRef o) { return JSRetainPtr(Adopt, o); @@ -161,23 +171,3 @@ template inline bool operator==(const JSRetainPtr& a, { return a.get() == b; } - -template inline bool operator==(T* a, const JSRetainPtr& b) -{ - return a == b.get(); -} - -template inline bool operator!=(const JSRetainPtr& a, const JSRetainPtr& b) -{ - return a.get() != b.get(); -} - -template inline bool operator!=(const JSRetainPtr& a, U* b) -{ - return a.get() != b; -} - -template inline bool operator!=(T* a, const JSRetainPtr& b) -{ - return a != b.get(); -} diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSScript.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSScript.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSScript.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSScript.h diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSScriptInternal.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSScriptInternal.h similarity index 99% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSScriptInternal.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSScriptInternal.h index 4a9427d2..951438d4 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSScriptInternal.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSScriptInternal.h @@ -23,14 +23,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#pragma once +#if JSC_OBJC_API_ENABLED #import "JSScript.h" #import "SourceCode.h" #import -#if JSC_OBJC_API_ENABLED - NS_ASSUME_NONNULL_BEGIN namespace JSC { diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSScriptRefPrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSScriptRefPrivate.h similarity index 97% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSScriptRefPrivate.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSScriptRefPrivate.h index e6224ce3..f895239d 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSScriptRefPrivate.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSScriptRefPrivate.h @@ -26,9 +26,9 @@ #ifndef JSScriptRefPrivate_h #define JSScriptRefPrivate_h -#include -#include -#include +#include "JSContextRef.h" +#include "JSStringRef.h" +#include "JSValueRef.h" /*! @typedef JSScriptRef A JavaScript script reference. */ typedef struct OpaqueJSScript* JSScriptRef; diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSScriptSourceProvider.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSScriptSourceProvider.h similarity index 88% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSScriptSourceProvider.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSScriptSourceProvider.h index 09e4018d..ee36ac13 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSScriptSourceProvider.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSScriptSourceProvider.h @@ -29,7 +29,7 @@ @class JSScript; -class JSScriptSourceProvider : public JSC::SourceProvider { +class JSScriptSourceProvider final : public JSC::SourceProvider { public: template static Ref create(JSScript *script, Args&&... args) @@ -37,9 +37,9 @@ class JSScriptSourceProvider : public JSC::SourceProvider { return adoptRef(*new JSScriptSourceProvider(script, std::forward(args)...)); } - unsigned hash() const override; - StringView source() const override; - RefPtr cachedBytecode() const override; + unsigned hash() const final; + StringView source() const final; + RefPtr cachedBytecode() const final; private: template @@ -48,7 +48,7 @@ class JSScriptSourceProvider : public JSC::SourceProvider { , m_script(script) { } - RetainPtr m_script; + const RetainPtr m_script; }; #endif // JSC_OBJC_API_ENABLED diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSStringRef.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSStringRef.h similarity index 93% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSStringRef.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSStringRef.h index bc03ed70..5fdea1d1 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSStringRef.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSStringRef.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Inc. All rights reserved. + * Copyright (C) 2006 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,7 +26,7 @@ #ifndef JSStringRef_h #define JSStringRef_h -#include +#include "JSValueRef.h" #ifndef __cplusplus #include @@ -37,7 +37,7 @@ extern "C" { #endif -#if !defined(_NATIVE_WCHAR_T_DEFINED) /* MSVC */ \ +#if !defined(_NATIVE_WCHAR_T_DEFINED) /* MSVC */ \ && (!defined(__WCHAR_MAX__) || (__WCHAR_MAX__ > 0xffffU)) /* ISO C/C++ */ \ && (!defined(WCHAR_MAX) || (WCHAR_MAX > 0xffffU)) /* RVCT */ /*! @@ -46,9 +46,9 @@ extern "C" { character. As with all scalar types, endianness depends on the underlying architecture. */ - typedef unsigned short JSChar; +typedef unsigned short JSChar; #else - typedef wchar_t JSChar; +typedef wchar_t JSChar; #endif /*! @@ -90,35 +90,35 @@ JS_EXPORT void JSStringRelease(JSStringRef string); JS_EXPORT size_t JSStringGetLength(JSStringRef string); /*! @function -@abstract Returns a pointer to the Unicode character buffer that +@abstract Returns a pointer to the Unicode character buffer that serves as the backing store for a JavaScript string. @param string The JSString whose backing store you want to access. -@result A pointer to the Unicode character buffer that serves as string's +@result A pointer to the Unicode character buffer that serves as string's backing store, which will be deallocated when string is deallocated. */ JS_EXPORT const JSChar* JSStringGetCharactersPtr(JSStringRef string); /*! @function -@abstract Returns the maximum number of bytes a JavaScript string will +@abstract Returns the maximum number of bytes a JavaScript string will take up if converted into a null-terminated UTF8 string. -@param string The JSString whose maximum converted size (in bytes) you +@param string The JSString whose maximum converted size (in bytes) you want to know. -@result The maximum number of bytes that could be required to convert string into a - null-terminated UTF8 string. The number of bytes that the conversion actually ends +@result The maximum number of bytes that could be required to convert string into a + null-terminated UTF8 string. The number of bytes that the conversion actually ends up requiring could be less than this, but never more. */ JS_EXPORT size_t JSStringGetMaximumUTF8CStringSize(JSStringRef string); /*! @function -@abstract Converts a JavaScript string into a null-terminated UTF8 string, +@abstract Converts a JavaScript string into a null-terminated UTF8 string, and copies the result into an external byte buffer. @param string The source JSString. -@param buffer The destination byte buffer into which to copy a null-terminated - UTF8 representation of string. On return, buffer contains a UTF8 string - representation of string. If bufferSize is too small, buffer will contain only - partial results. If buffer is not at least bufferSize bytes in size, - behavior is undefined. +@param buffer The destination byte buffer into which to copy a null-terminated + UTF8 representation of string. On return, buffer contains a UTF8 string + representation of string. If bufferSize is too small, buffer will contain only + partial results. If buffer is not at least bufferSize bytes in size, + behavior is undefined. @param bufferSize The size of the external buffer in bytes. @result The number of bytes written into buffer (including the null-terminator byte). */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSStringRefBSTR.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSStringRefBSTR.h similarity index 97% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSStringRefBSTR.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSStringRefBSTR.h index 066c68d5..0f0a0ccd 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSStringRefBSTR.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSStringRefBSTR.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSStringRefCF.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSStringRefCF.h similarity index 97% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSStringRefCF.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSStringRefCF.h index 1e210c7a..7667fb47 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSStringRefCF.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSStringRefCF.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,8 +26,8 @@ #ifndef JSStringRefCF_h #define JSStringRefCF_h -#include "JSBase.h" #include +#include "JSBase.h" #ifdef __cplusplus extern "C" { diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSStringRefPrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSStringRefPrivate.h similarity index 97% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSStringRefPrivate.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSStringRefPrivate.h index f1db806e..76a8470a 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSStringRefPrivate.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSStringRefPrivate.h @@ -26,7 +26,7 @@ #ifndef JSStringRefPrivate_h #define JSStringRefPrivate_h -#include +#include "JSStringRef.h" #ifdef __cplusplus extern "C" { diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSTypedArray.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSTypedArray.h similarity index 99% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSTypedArray.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSTypedArray.h index 7eaf76c5..e28c2cff 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSTypedArray.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSTypedArray.h @@ -27,8 +27,8 @@ #ifndef JSTypedArray_h #define JSTypedArray_h -#include -#include +#include "JSBase.h" +#include "JSValueRef.h" #ifdef __cplusplus extern "C" { diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSValue.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSValue.h similarity index 69% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSValue.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSValue.h index 1b5845e9..6b2438de 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSValue.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSValue.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2019 Apple Inc. All rights reserved. + * Copyright (C) 2013-2024 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,7 +26,7 @@ #ifndef JSValue_h #define JSValue_h -#if JSC_OBJC_API_ENABLED +#if defined(__OBJC__) && JSC_OBJC_API_ENABLED #import @@ -51,7 +51,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @property @abstract The JSContext that this value originates from. */ -@property (readonly, strong) JSContext *context; +@property (readonly, strong) JSContext * _Null_unspecified context; /*! @methodgroup Creating JavaScript Values @@ -63,7 +63,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param value The Objective-C object to be converted. @result The new JSValue. */ -+ (JSValue *)valueWithObject:(id)value inContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithObject:(id _Null_unspecified)value inContext:(JSContext * _Null_unspecified)context; /*! @method @@ -71,7 +71,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param context The JSContext in which the resulting JSValue will be created. @result The new JSValue representing the equivalent boolean value. */ -+ (JSValue *)valueWithBool:(BOOL)value inContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithBool:(BOOL)value inContext:(JSContext * _Null_unspecified)context; /*! @method @@ -79,7 +79,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param context The JSContext in which the resulting JSValue will be created. @result The new JSValue representing the equivalent boolean value. */ -+ (JSValue *)valueWithDouble:(double)value inContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithDouble:(double)value inContext:(JSContext * _Null_unspecified)context; /*! @method @@ -87,7 +87,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param context The JSContext in which the resulting JSValue will be created. @result The new JSValue representing the equivalent boolean value. */ -+ (JSValue *)valueWithInt32:(int32_t)value inContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithInt32:(int32_t)value inContext:(JSContext * _Null_unspecified)context; /*! @method @@ -95,7 +95,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param context The JSContext in which the resulting JSValue will be created. @result The new JSValue representing the equivalent boolean value. */ -+ (JSValue *)valueWithUInt32:(uint32_t)value inContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithUInt32:(uint32_t)value inContext:(JSContext * _Null_unspecified)context; /*! @method @@ -103,7 +103,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param context The JSContext in which the resulting object will be created. @result The new JavaScript object. */ -+ (JSValue *)valueWithNewObjectInContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithNewObjectInContext:(JSContext * _Null_unspecified)context; /*! @method @@ -111,7 +111,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param context The JSContext in which the resulting array will be created. @result The new JavaScript array. */ -+ (JSValue *)valueWithNewArrayInContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithNewArrayInContext:(JSContext * _Null_unspecified)context; /*! @method @@ -121,7 +121,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param context The JSContext in which the resulting regular expression object will be created. @result The new JavaScript regular expression object. */ -+ (JSValue *)valueWithNewRegularExpressionFromPattern:(NSString *)pattern flags:(NSString *)flags inContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithNewRegularExpressionFromPattern:(NSString * _Null_unspecified)pattern flags:(NSString * _Null_unspecified)flags inContext:(JSContext * _Null_unspecified)context; /*! @method @@ -130,7 +130,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param context The JSContext in which the resulting error object will be created. @result The new JavaScript error object. */ -+ (JSValue *)valueWithNewErrorFromMessage:(NSString *)message inContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithNewErrorFromMessage:(NSString * _Null_unspecified)message inContext:(JSContext * _Null_unspecified)context; /*! @method @@ -140,7 +140,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @result The JSValue representing a new promise JavaScript object. @discussion This method is equivalent to calling the Promise constructor in JavaScript. the resolve and reject callbacks each normally take a single value, which they forward to all relevent pending reactions. While inside the executor callback context will act as if it were in any other callback, except calleeFunction will be nil. This also means means the new promise object may be accessed via [context thisValue]. */ -+ (JSValue *)valueWithNewPromiseInContext:(JSContext *)context fromExecutor:(void (^)(JSValue *resolve, JSValue *reject))callback JSC_API_AVAILABLE(macos(10.15), ios(13.0)); ++ (JSValue * _Null_unspecified)valueWithNewPromiseInContext:(JSContext * _Null_unspecified)context fromExecutor:(void (^ _Null_unspecified)(JSValue * _Null_unspecified resolve, JSValue * _Null_unspecified reject))callback JSC_API_AVAILABLE(macos(10.15), ios(13.0)); /*! @method @@ -150,7 +150,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @result The JSValue representing a new promise JavaScript object. @discussion This method is equivalent to calling [JSValue valueWithNewPromiseFromExecutor:^(JSValue *resolve, JSValue *reject) { [resolve callWithArguments:@[result]]; } inContext:context] */ -+ (JSValue *)valueWithNewPromiseResolvedWithResult:(id)result inContext:(JSContext *)context JSC_API_AVAILABLE(macos(10.15), ios(13.0)); ++ (JSValue * _Null_unspecified)valueWithNewPromiseResolvedWithResult:(id _Null_unspecified)result inContext:(JSContext * _Null_unspecified)context JSC_API_AVAILABLE(macos(10.15), ios(13.0)); /*! @method @@ -160,7 +160,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @result The JSValue representing a new promise JavaScript object. @discussion This method is equivalent to calling [JSValue valueWithNewPromiseFromExecutor:^(JSValue *resolve, JSValue *reject) { [reject callWithArguments:@[reason]]; } inContext:context] */ -+ (JSValue *)valueWithNewPromiseRejectedWithReason:(id)reason inContext:(JSContext *)context JSC_API_AVAILABLE(macos(10.15), ios(13.0)); ++ (JSValue * _Null_unspecified)valueWithNewPromiseRejectedWithReason:(id _Null_unspecified)reason inContext:(JSContext * _Null_unspecified)context JSC_API_AVAILABLE(macos(10.15), ios(13.0)); /*! @method @@ -169,7 +169,45 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param context The JSContext to which the resulting JSValue belongs. @result The JSValue representing a unique JavaScript value with type symbol. */ -+ (JSValue *)valueWithNewSymbolFromDescription:(NSString *)description inContext:(JSContext *)context JSC_API_AVAILABLE(macos(10.15), ios(13.0)); ++ (JSValue * _Null_unspecified)valueWithNewSymbolFromDescription:(NSString * _Null_unspecified)description inContext:(JSContext * _Null_unspecified)context JSC_API_AVAILABLE(macos(10.15), ios(13.0)); + +/*! +@method +@abstract Create a new BigInt value from a numeric string. +@param string The string representation of the BigInt JavaScript value being created. +@param context The JSContext to which the resulting JSValue belongs. +@result The JSValue representing a JavaScript value with type BigInt. +@discussion This is equivalent to calling the BigInt constructor from JavaScript with a string argument. +*/ ++ (nullable JSValue *)valueWithNewBigIntFromString:(nonnull NSString *)string inContext:(nonnull JSContext *)context JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! +@method +@abstract Create a new BigInt value from a int64_t. +@param int64 The signed 64-bit integer of the BigInt JavaScript value being created. +@param context The JSContext to which the resulting JSValue belongs. +@result The JSValue representing a JavaScript value with type BigInt. +*/ ++ (nullable JSValue *)valueWithNewBigIntFromInt64:(int64_t)int64 inContext:(nonnull JSContext *)context JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! +@method +@abstract Create a new BigInt value from a uint64_t. +@param uint64 The unsigned 64-bit integer of the BigInt JavaScript value being created. +@param context The JSContext to which the resulting JSValue belongs. +@result The JSValue representing a JavaScript value with type BigInt. +*/ ++ (nullable JSValue *)valueWithNewBigIntFromUInt64:(uint64_t)uint64 inContext:(nonnull JSContext *)context JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! +@method +@abstract Create a new BigInt value from a double. +@param value The value of the BigInt JavaScript value being created. +@param context The JSContext to which the resulting JSValue belongs. +@result The JSValue representing a JavaScript value with type BigInt. +@discussion If the value is not an integer, an exception is thrown. +*/ ++ (nullable JSValue *)valueWithNewBigIntFromDouble:(double)value inContext:(nonnull JSContext *)context JSC_API_AVAILABLE(macos(15.0), ios(18.0)); /*! @method @@ -177,7 +215,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param context The JSContext to which the resulting JSValue belongs. @result The JSValue representing the JavaScript value null. */ -+ (JSValue *)valueWithNullInContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithNullInContext:(JSContext * _Null_unspecified)context; /*! @method @@ -185,7 +223,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param context The JSContext to which the resulting JSValue belongs. @result The JSValue representing the JavaScript value undefined. */ -+ (JSValue *)valueWithUndefinedInContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithUndefinedInContext:(JSContext * _Null_unspecified)context; /*! @methodgroup Converting to Objective-C Types @@ -240,7 +278,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) to the conversion rules specified above. @result The Objective-C representation of this JSValue. */ -- (id)toObject; +- (id _Null_unspecified)toObject; /*! @method @@ -249,7 +287,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) If the result is not of the specified Class then nil will be returned. @result An Objective-C object of the specified Class or nil. */ -- (id)toObjectOfClass:(Class)expectedClass; +- (id _Null_unspecified)toObjectOfClass:(Class _Null_unspecified)expectedClass; /*! @method @@ -263,17 +301,15 @@ NS_CLASS_AVAILABLE(10_9, 7_0) /*! @method @abstract Convert a JSValue to a double. -@discussion The JSValue is converted to a number according to the rules specified - by the JavaScript language. @result The double result of the conversion. +@discussion Convert the JSValue to a number according to the rules specified by the JavaScript language. Unless the JSValue is a BigInt then this is equivalent to Number(value) in JavaScript. */ - (double)toDouble; /*! @method @abstract Convert a JSValue to an int32_t. -@discussion The JSValue is converted to an integer according to the rules specified - by the JavaScript language. +@discussion The JSValue is converted to an integer according to the rules specified by the JavaScript language. If the JSValue is a BigInt, then the value is truncated to an int32_t. @result The int32_t result of the conversion. */ - (int32_t)toInt32; @@ -281,21 +317,33 @@ NS_CLASS_AVAILABLE(10_9, 7_0) /*! @method @abstract Convert a JSValue to a uint32_t. -@discussion The JSValue is converted to an integer according to the rules specified - by the JavaScript language. +@discussion The JSValue is converted to an integer according to the rules specified by the JavaScript language. If the JSValue is a BigInt, then the value is truncated to a uint32_t. @result The uint32_t result of the conversion. */ - (uint32_t)toUInt32; +/*! +@method +@abstract Convert a JSValue to a int64_t. +@discussion The JSValue is converted to an integer according to the rules specified by the JavaScript language. If the value is a BigInt, then the value is truncated to an int64_t. +*/ +- (int64_t)toInt64 JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! +@method +@abstract Convert a JSValue to a uint64_t. +@discussion The JSValue is converted to an integer according to the rules specified by the JavaScript language. If the value is a BigInt, then the value is truncated to a uint64_t. +*/ +- (uint64_t)toUInt64 JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + /*! @method @abstract Convert a JSValue to a NSNumber. -@discussion If the JSValue represents a boolean, a NSNumber value of YES or NO - will be returned. For all other types the value will be converted to a number according - to the rules specified by the JavaScript language. +@discussion If the JSValue represents a boolean, a NSNumber value of YES or NO + will be returned. For all other types, the result is equivalent to Number(value) in JavaScript. @result The NSNumber result of the conversion. */ -- (NSNumber *)toNumber; +- (NSNumber * _Null_unspecified)toNumber; /*! @method @@ -304,7 +352,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) by the JavaScript language. @result The NSString containing the result of the conversion. */ -- (NSString *)toString; +- (NSString * _Null_unspecified)toString; /*! @method @@ -313,7 +361,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) since 1970 which is then used to create a new NSDate instance. @result The NSDate created using the converted time interval. */ -- (NSDate *)toDate; +- (NSDate * _Null_unspecified)toDate; /*! @method @@ -322,12 +370,12 @@ NS_CLASS_AVAILABLE(10_9, 7_0) If the value is not an object then a JavaScript TypeError will be thrown. The property length is read from the object, converted to an unsigned integer, and an NSArray of this size is allocated. Properties corresponding - to indicies within the array bounds will be copied to the array, with + to indices within the array bounds will be copied to the array, with JSValues converted to equivalent Objective-C objects as specified. @result The NSArray containing the recursively converted contents of the converted JavaScript array. */ -- (NSArray *)toArray; +- (NSArray * _Null_unspecified)toArray; /*! @method @@ -339,10 +387,10 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @result The NSDictionary containing the recursively converted contents of the converted JavaScript object. */ -- (NSDictionary *)toDictionary; +- (NSDictionary * _Null_unspecified)toDictionary; /*! -@functiongroup Checking JavaScript Types +@methodgroup Checking JavaScript Types */ /*! @@ -402,26 +450,72 @@ NS_CLASS_AVAILABLE(10_9, 7_0) */ @property (readonly) BOOL isSymbol JSC_API_AVAILABLE(macos(10.15), ios(13.0)); +/*! +@property +@abstract Check if a JSValue is a BigInt. +*/ +@property (readonly) BOOL isBigInt JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! +@method +@abstract Check if a JSValue is an instance of another object. +@discussion This method has the same function as the JavaScript operator instanceof. + If an object other than a JSValue is passed, it will first be converted according to + the aforementioned rules. +*/ +- (BOOL)isInstanceOf:(id _Null_unspecified)value; + +/*! +@methodgroup Compare JavaScript values +*/ + /*! @method @abstract Compare two JSValues using JavaScript's === operator. */ -- (BOOL)isEqualToObject:(id)value; +- (BOOL)isEqualToObject:(id _Null_unspecified)value; /*! @method @abstract Compare two JSValues using JavaScript's == operator. */ -- (BOOL)isEqualWithTypeCoercionToObject:(id)value; +- (BOOL)isEqualWithTypeCoercionToObject:(id _Null_unspecified)value; /*! @method -@abstract Check if a JSValue is an instance of another object. -@discussion This method has the same function as the JavaScript operator instanceof. - If an object other than a JSValue is passed, it will first be converted according to - the aforementioned rules. +@abstract Compare two JSValues. +@other The JSValue to compare with. +@result A value of JSRelationCondition, a kJSRelationConditionUndefined is returned if an exception is thrown. +@discussion The result is computed by comparing the results of JavaScript's ==, <, and > operators. If either self or other is (or would coerce to) NaN in JavaScript, then the result is kJSRelationConditionUndefined. +*/ +- (JSRelationCondition)compareJSValue:(nonnull JSValue *)other JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! +@method +@abstract Compare a JSValue with a int64_t. +@other The int64_t to compare with. +@result A value of JSRelationCondition, a kJSRelationConditionUndefined is returned if an exception is thrown. +@discussion The JSValue is converted to an integer according to the rules specified by the JavaScript language then compared with other. +*/ +- (JSRelationCondition)compareInt64:(int64_t)other JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! +@method +@abstract Compare a JSValue with a uint64_t. +@other The uint64_t to compare with. +@result A value of JSRelationCondition, a kJSRelationConditionUndefined is returned if an exception is thrown. +@discussion The JSValue is converted to an integer according to the rules specified by the JavaScript language then compared with other. +*/ +- (JSRelationCondition)compareUInt64:(uint64_t)other JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! +@method +@abstract Compare a JSValue with a double. +@other The double to compare with. +@result A value of JSRelationCondition, a kJSRelationConditionUndefined is returned if an exception is thrown. +@discussion The JSValue is converted to a double according to the rules specified by the JavaScript language then compared with other. */ -- (BOOL)isInstanceOf:(id)value; +- (JSRelationCondition)compareDouble:(double)other JSC_API_AVAILABLE(macos(15.0), ios(18.0)); /*! @methodgroup Calling Functions and Constructors @@ -434,7 +528,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param arguments The arguments to pass to the function. @result The return value of the function call. */ -- (JSValue *)callWithArguments:(NSArray *)arguments; +- (JSValue * _Null_unspecified)callWithArguments:(NSArray * _Null_unspecified)arguments; /*! @method @@ -443,7 +537,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param arguments The arguments to pass to the constructor. @result The return value of the constructor call. */ -- (JSValue *)constructWithArguments:(NSArray *)arguments; +- (JSValue * _Null_unspecified)constructWithArguments:(NSArray * _Null_unspecified)arguments; /*! @method @@ -455,7 +549,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @param arguments The arguments to pass to the method. @result The return value of the method call. */ -- (JSValue *)invokeMethod:(NSString *)method withArguments:(NSArray *)arguments; +- (JSValue * _Null_unspecified)invokeMethod:(NSString * _Null_unspecified)method withArguments:(NSArray * _Null_unspecified)arguments; @end @@ -478,7 +572,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @result A newly allocated JavaScript object containing properties named x and y, with values from the CGPoint. */ -+ (JSValue *)valueWithPoint:(CGPoint)point inContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithPoint:(CGPoint)point inContext:(JSContext * _Null_unspecified)context; /*! @method @@ -486,7 +580,7 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @result A newly allocated JavaScript object containing properties named location and length, with values from the NSRange. */ -+ (JSValue *)valueWithRange:(NSRange)range inContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithRange:(NSRange)range inContext:(JSContext * _Null_unspecified)context; /*! @method @@ -495,7 +589,7 @@ Create a JSValue from a CGRect. @result A newly allocated JavaScript object containing properties named x, y, width, and height, with values from the CGRect. */ -+ (JSValue *)valueWithRect:(CGRect)rect inContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithRect:(CGRect)rect inContext:(JSContext * _Null_unspecified)context; /*! @method @@ -503,7 +597,7 @@ Create a JSValue from a CGRect. @result A newly allocated JavaScript object containing properties named width and height, with values from the CGSize. */ -+ (JSValue *)valueWithSize:(CGSize)size inContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithSize:(CGSize)size inContext:(JSContext * _Null_unspecified)context; /*! @method @@ -550,9 +644,9 @@ Create a JSValue from a CGRect. @interface JSValue (PropertyAccess) #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500) || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000) -typedef NSString *JSValueProperty; +typedef NSString * _Null_unspecified JSValueProperty; #else -typedef id JSValueProperty; +typedef id _Null_unspecified JSValueProperty; #endif /*! @@ -562,14 +656,14 @@ typedef id JSValueProperty; if the property does not exist. @discussion Corresponds to the JavaScript operation object[property]. Starting with macOS 10.15 and iOS 13, 'property' can be any 'id' and will be converted to a JSValue using the conversion rules of valueWithObject:inContext:. Prior to macOS 10.15 and iOS 13, 'property' was expected to be an NSString *. */ -- (JSValue *)valueForProperty:(JSValueProperty)property; +- (JSValue * _Null_unspecified)valueForProperty:(JSValueProperty)property; /*! @method @abstract Set a property on a JSValue. @discussion Corresponds to the JavaScript operation object[property] = value. Starting with macOS 10.15 and iOS 13, 'property' can be any 'id' and will be converted to a JSValue using the conversion rules of valueWithObject:inContext:. Prior to macOS 10.15 and iOS 13, 'property' was expected to be an NSString *. */ -- (void)setValue:(id)value forProperty:(JSValueProperty)property; +- (void)setValue:(id _Null_unspecified)value forProperty:(JSValueProperty)property; /*! @method @@ -594,7 +688,7 @@ typedef id JSValueProperty; @discussion This method may be used to create a data or accessor property on an object. This method operates in accordance with the Object.defineProperty method in the JavaScript language. Starting with macOS 10.15 and iOS 13, 'property' can be any 'id' and will be converted to a JSValue using the conversion rules of valueWithObject:inContext:. Prior to macOS 10.15 and iOS 13, 'property' was expected to be an NSString *. */ -- (void)defineProperty:(JSValueProperty)property descriptor:(id)descriptor; +- (void)defineProperty:(JSValueProperty)property descriptor:(id _Null_unspecified)descriptor; /*! @method @@ -602,7 +696,7 @@ typedef id JSValueProperty; @result The JSValue for the property at the specified index. Returns the JavaScript value undefined if no property exists at that index. */ -- (JSValue *)valueAtIndex:(NSUInteger)index; +- (JSValue * _Null_unspecified)valueAtIndex:(NSUInteger)index; /*! @method @@ -610,7 +704,7 @@ typedef id JSValueProperty; @discussion For JSValues that are JavaScript arrays, indices greater than UINT_MAX - 1 will not affect the length of the array. */ -- (void)setValue:(id)value atIndex:(NSUInteger)index; +- (void)setValue:(id _Null_unspecified)value atIndex:(NSUInteger)index; @end @@ -635,10 +729,10 @@ typedef id JSValueProperty; */ @interface JSValue (SubscriptSupport) -- (JSValue *)objectForKeyedSubscript:(id)key; -- (JSValue *)objectAtIndexedSubscript:(NSUInteger)index; -- (void)setObject:(id)object forKeyedSubscript:(id)key; -- (void)setObject:(id)object atIndexedSubscript:(NSUInteger)index; +- (JSValue * _Null_unspecified)objectForKeyedSubscript:(id _Null_unspecified)key; +- (JSValue * _Null_unspecified)objectAtIndexedSubscript:(NSUInteger)index; +- (void)setObject:(id _Null_unspecified)object forKeyedSubscript:(id _Null_unspecified)key; +- (void)setObject:(id _Null_unspecified)object atIndexedSubscript:(NSUInteger)index; @end @@ -653,14 +747,14 @@ typedef id JSValueProperty; @abstract Creates a JSValue, wrapping its C API counterpart. @result The Objective-C API equivalent of the specified JSValueRef. */ -+ (JSValue *)valueWithJSValueRef:(JSValueRef)value inContext:(JSContext *)context; ++ (JSValue * _Null_unspecified)valueWithJSValueRef:(JSValueRef _Null_unspecified)value inContext:(JSContext * _Null_unspecified)context; /*! @property @abstract Returns the C API counterpart wrapped by a JSContext. @result The C API equivalent of this JSValue. */ -@property (readonly) JSValueRef JSValueRef; +@property (readonly) JSValueRef _Null_unspecified JSValueRef; @end #ifdef __cplusplus @@ -699,27 +793,27 @@ extern "C" { /*! @const */ -JS_EXPORT extern NSString * const JSPropertyDescriptorWritableKey; +JS_EXPORT extern NSString * _Null_unspecified const JSPropertyDescriptorWritableKey; /*! @const */ -JS_EXPORT extern NSString * const JSPropertyDescriptorEnumerableKey; +JS_EXPORT extern NSString * _Null_unspecified const JSPropertyDescriptorEnumerableKey; /*! @const */ -JS_EXPORT extern NSString * const JSPropertyDescriptorConfigurableKey; +JS_EXPORT extern NSString * _Null_unspecified const JSPropertyDescriptorConfigurableKey; /*! @const */ -JS_EXPORT extern NSString * const JSPropertyDescriptorValueKey; +JS_EXPORT extern NSString * _Null_unspecified const JSPropertyDescriptorValueKey; /*! @const */ -JS_EXPORT extern NSString * const JSPropertyDescriptorGetKey; +JS_EXPORT extern NSString * _Null_unspecified const JSPropertyDescriptorGetKey; /*! @const */ -JS_EXPORT extern NSString * const JSPropertyDescriptorSetKey; +JS_EXPORT extern NSString * _Null_unspecified const JSPropertyDescriptorSetKey; #ifdef __cplusplus } // extern "C" @@ -727,4 +821,4 @@ JS_EXPORT extern NSString * const JSPropertyDescriptorSetKey; #endif -#endif // JSValue_h +#endif /* JSValue_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSValueInternal.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSValueInternal.h similarity index 97% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSValueInternal.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSValueInternal.h index 54b755ef..a9369553 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSValueInternal.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSValueInternal.h @@ -28,6 +28,10 @@ #import +#ifdef __cplusplus +extern "C" { +#endif + #if JSC_OBJC_API_ENABLED @interface JSValue(Internal) @@ -54,4 +58,8 @@ NSInvocation *valueToTypeInvocationFor(const char* encodedType); #endif +#ifdef __cplusplus +} +#endif + #endif // JSValueInternal_h diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSValuePrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSValuePrivate.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSValuePrivate.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSValuePrivate.h diff --git a/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSValueRef.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSValueRef.h new file mode 100644 index 00000000..c1feecc3 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSValueRef.h @@ -0,0 +1,558 @@ +/* + * Copyright (C) 2006-2024 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSValueRef_h +#define JSValueRef_h +#ifndef __cplusplus +#include +#endif +#include "JSBase.h" +#include "WebKitAvailability.h" + +#ifndef __cplusplus +#include +#endif +#include /* for size_t */ +#include /* for int64_t and uint64_t */ + +/*! +@enum JSType +@abstract A constant identifying the type of a JSValue. +@constant kJSTypeUndefined The unique undefined value. +@constant kJSTypeNull The unique null value. +@constant kJSTypeBoolean A primitive boolean value, one of true or false. +@constant kJSTypeNumber A primitive number value. +@constant kJSTypeString A primitive string value. +@constant kJSTypeObject An object value (meaning that this JSValueRef is a JSObjectRef). +@constant kJSTypeSymbol A primitive symbol value. +@constant kJSTypeBigInt A primitive BigInt value. +*/ +typedef enum { + kJSTypeUndefined, + kJSTypeNull, + kJSTypeBoolean, + kJSTypeNumber, + kJSTypeString, + kJSTypeObject, + kJSTypeSymbol JSC_API_AVAILABLE(macos(10.15), ios(13.0)), + kJSTypeBigInt JSC_API_AVAILABLE(macos(15.0), ios(18.0)) +} JSType; + +/*! + @enum JSTypedArrayType + @abstract A constant identifying the Typed Array type of a JSObjectRef. + @constant kJSTypedArrayTypeInt8Array Int8Array + @constant kJSTypedArrayTypeInt16Array Int16Array + @constant kJSTypedArrayTypeInt32Array Int32Array + @constant kJSTypedArrayTypeUint8Array Uint8Array + @constant kJSTypedArrayTypeUint8ClampedArray Uint8ClampedArray + @constant kJSTypedArrayTypeUint16Array Uint16Array + @constant kJSTypedArrayTypeUint32Array Uint32Array + @constant kJSTypedArrayTypeFloat32Array Float32Array + @constant kJSTypedArrayTypeFloat64Array Float64Array + @constant kJSTypedArrayTypeBigInt64Array BigInt64Array + @constant kJSTypedArrayTypeBigUint64Array BigUint64Array + @constant kJSTypedArrayTypeArrayBuffer ArrayBuffer + @constant kJSTypedArrayTypeNone Not a Typed Array + + */ +typedef enum { + kJSTypedArrayTypeInt8Array, + kJSTypedArrayTypeInt16Array, + kJSTypedArrayTypeInt32Array, + kJSTypedArrayTypeUint8Array, + kJSTypedArrayTypeUint8ClampedArray, + kJSTypedArrayTypeUint16Array, + kJSTypedArrayTypeUint32Array, + kJSTypedArrayTypeFloat32Array, + kJSTypedArrayTypeFloat64Array, + kJSTypedArrayTypeArrayBuffer, + kJSTypedArrayTypeNone, + kJSTypedArrayTypeBigInt64Array, + kJSTypedArrayTypeBigUint64Array, +} JSTypedArrayType JSC_API_AVAILABLE(macos(10.12), ios(10.0)); + +/*! +@enum JSRelationCondition +@abstract A constant identifying the type of JavaScript relation condition. +@constant kJSRelationConditionUndefined Fail to compare two operands. +@constant kJSRelationConditionEqual Two operands have equivalent values. +@constant kJSRelationConditionGreaterThan The left operand is greater than the right operand. +@constant kJSRelationConditionLessThan The left operand is less than the right operand. +*/ +JSC_CF_ENUM(JSRelationCondition, + kJSRelationConditionUndefined, + kJSRelationConditionEqual, + kJSRelationConditionGreaterThan, + kJSRelationConditionLessThan +) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@function +@abstract Returns a JavaScript value's type. +@param ctx The execution context to use. +@param value The JSValue whose type you want to obtain. +@result A value of type JSType that identifies value's type. +*/ +JS_EXPORT JSType JSValueGetType(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value); + +/*! +@function +@abstract Tests whether a JavaScript value's type is the undefined type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the undefined type, otherwise false. +*/ +JS_EXPORT bool JSValueIsUndefined(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value); + +/*! +@function +@abstract Tests whether a JavaScript value's type is the null type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the null type, otherwise false. +*/ +JS_EXPORT bool JSValueIsNull(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value); + +/*! +@function +@abstract Tests whether a JavaScript value's type is the boolean type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the boolean type, otherwise false. +*/ +JS_EXPORT bool JSValueIsBoolean(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value); + +/*! +@function +@abstract Tests whether a JavaScript value's type is the number type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the number type, otherwise false. +*/ +JS_EXPORT bool JSValueIsNumber(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value); + +/*! +@function +@abstract Tests whether a JavaScript value's type is the string type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the string type, otherwise false. +*/ +JS_EXPORT bool JSValueIsString(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value); + +/*! +@function +@abstract Tests whether a JavaScript value's type is the symbol type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the symbol type, otherwise false. +*/ +JS_EXPORT bool JSValueIsSymbol(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value) JSC_API_AVAILABLE(macos(10.15), ios(13.0)); + +JSC_ASSUME_NONNULL_BEGIN +/*! +@function +@abstract Tests whether a JavaScript value's type is the BigInt type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the BigInt type, otherwise false. +*/ +JS_EXPORT bool JSValueIsBigInt(JSContextRef ctx, JSValueRef value) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); +JSC_ASSUME_NONNULL_END + +/*! +@function +@abstract Tests whether a JavaScript value's type is the object type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the object type, otherwise false. +*/ +JS_EXPORT bool JSValueIsObject(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value); + + +/*! +@function +@abstract Tests whether a JavaScript value is an object with a given class in its class chain. +@param ctx The execution context to use. +@param value The JSValue to test. +@param jsClass The JSClass to test against. +@result true if value is an object and has jsClass in its class chain, otherwise false. +*/ +JS_EXPORT bool JSValueIsObjectOfClass(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value, JSC_NULL_UNSPECIFIED JSClassRef jsClass); + +/*! +@function +@abstract Tests whether a JavaScript value is an array. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value is an array, otherwise false. +*/ +JS_EXPORT bool JSValueIsArray(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value) JSC_API_AVAILABLE(macos(10.11), ios(9.0)); + +/*! +@function +@abstract Tests whether a JavaScript value is a date. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value is a date, otherwise false. +*/ +JS_EXPORT bool JSValueIsDate(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value) JSC_API_AVAILABLE(macos(10.11), ios(9.0)); + +/*! +@function +@abstract Returns a JavaScript value's Typed Array type. +@param ctx The execution context to use. +@param value The JSValue whose Typed Array type to return. +@param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. +@result A value of type JSTypedArrayType that identifies value's Typed Array type, or kJSTypedArrayTypeNone if the value is not a Typed Array object. + */ +JS_EXPORT JSTypedArrayType JSValueGetTypedArrayType(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value, JSC_NULL_UNSPECIFIED JSValueRef* JSC_NULL_UNSPECIFIED exception) JSC_API_AVAILABLE(macos(10.12), ios(10.0)); + +/* Comparing values */ + +/*! +@function +@abstract Tests whether two JavaScript values are equal, as compared by the JS == operator. +@param ctx The execution context to use. +@param a The first value to test. +@param b The second value to test. +@param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. +@result true if the two values are equal, false if they are not equal or an exception is thrown. +*/ +JS_EXPORT bool JSValueIsEqual(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef a, JSC_NULL_UNSPECIFIED JSValueRef b, JSC_NULL_UNSPECIFIED JSValueRef* JSC_NULL_UNSPECIFIED exception); + +/*! +@function +@abstract Tests whether two JavaScript values are strict equal, as compared by the JS === operator. +@param ctx The execution context to use. +@param a The first value to test. +@param b The second value to test. +@result true if the two values are strict equal, otherwise false. +*/ +JS_EXPORT bool JSValueIsStrictEqual(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef a, JSC_NULL_UNSPECIFIED JSValueRef b); + +/*! +@function +@abstract Tests whether a JavaScript value is an object constructed by a given constructor, as compared by the JS instanceof operator. +@param ctx The execution context to use. +@param value The JSValue to test. +@param constructor The constructor to test against. +@param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. +@result true if value is an object constructed by constructor, as compared by the JS instanceof operator, otherwise false. +*/ +JS_EXPORT bool JSValueIsInstanceOfConstructor(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value, JSC_NULL_UNSPECIFIED JSObjectRef constructor, JSC_NULL_UNSPECIFIED JSValueRef* JSC_NULL_UNSPECIFIED exception); + +JSC_ASSUME_NONNULL_BEGIN +/*! + @function + @abstract Compares two JSValues. + @param ctx The execution context to use. + @param left The JSValue as the left operand. + @param right The JSValue as the right operand. + @param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. + @result A value of JSRelationCondition, a kJSRelationConditionUndefined is returned if an exception is thrown. + @discussion The result is computed by comparing the results of JavaScript's `==`, `<`, and `>` operators. If either `left` or `right` is (or would coerce to) `NaN` in JavaScript, then the result is kJSRelationConditionUndefined. +*/ +JS_EXPORT JSRelationCondition JSValueCompare(JSContextRef ctx, JSValueRef left, JSValueRef right, JSC_NULLABLE JSValueRef* JSC_NULLABLE exception) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! + @function + @abstract Compares a JSValue with a signed 64-bit integer. + @param ctx The execution context to use. + @param left The JSValue as the left operand. + @param right The int64_t as the right operand. + @param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. + @result A value of JSRelationCondition, a kJSRelationConditionUndefined is returned if an exception is thrown. + @discussion `left` is converted to an integer according to the rules specified by the JavaScript language then compared with `right`. +*/ +JS_EXPORT JSRelationCondition JSValueCompareInt64(JSContextRef ctx, JSValueRef left, int64_t right, JSC_NULLABLE JSValueRef* JSC_NULLABLE exception) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! + @function + @abstract Compares a JSValue with an unsigned 64-bit integer. + @param ctx The execution context to use. + @param left The JSValue as the left operand. + @param right The uint64_t as the right operand. + @param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. + @result A value of JSRelationCondition, a kJSRelationConditionUndefined is returned if an exception is thrown. + @discussion `left` is converted to an integer according to the rules specified by the JavaScript language then compared with `right`. +*/ +JS_EXPORT JSRelationCondition JSValueCompareUInt64(JSContextRef ctx, JSValueRef left, uint64_t right, JSC_NULLABLE JSValueRef* JSC_NULLABLE exception) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! + @function + @abstract Compares a JSValue with a double. + @param ctx The execution context to use. + @param left The JSValue as the left operand. + @param right The double as the right operand. + @param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. + @result A value of JSRelationCondition, a kJSRelationConditionUndefined is returned if an exception is thrown. + @discussion `left` is converted to a double according to the rules specified by the JavaScript language then compared with `right`. +*/ +JS_EXPORT JSRelationCondition JSValueCompareDouble(JSContextRef ctx, JSValueRef left, double right, JSC_NULLABLE JSValueRef* JSC_NULLABLE exception) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); +JSC_ASSUME_NONNULL_END + +/* Creating values */ + +/*! +@function +@abstract Creates a JavaScript value of the undefined type. +@param ctx The execution context to use. +@result The unique undefined value. +*/ +JS_EXPORT JSC_NULL_UNSPECIFIED JSValueRef JSValueMakeUndefined(JSC_NULL_UNSPECIFIED JSContextRef ctx); + +/*! +@function +@abstract Creates a JavaScript value of the null type. +@param ctx The execution context to use. +@result The unique null value. +*/ +JS_EXPORT JSC_NULL_UNSPECIFIED JSValueRef JSValueMakeNull(JSC_NULL_UNSPECIFIED JSContextRef ctx); + +/*! +@function +@abstract Creates a JavaScript value of the boolean type. +@param ctx The execution context to use. +@param boolean The bool to assign to the newly created JSValue. +@result A JSValue of the boolean type, representing the value of boolean. +*/ +JS_EXPORT JSC_NULL_UNSPECIFIED JSValueRef JSValueMakeBoolean(JSC_NULL_UNSPECIFIED JSContextRef ctx, bool boolean); + +/*! +@function +@abstract Creates a JavaScript value of the number type. +@param ctx The execution context to use. +@param number The double to assign to the newly created JSValue. +@result A JSValue of the number type, representing the value of number. +*/ +JS_EXPORT JSC_NULL_UNSPECIFIED JSValueRef JSValueMakeNumber(JSC_NULL_UNSPECIFIED JSContextRef ctx, double number); + +/*! +@function +@abstract Creates a JavaScript value of the string type. +@param ctx The execution context to use. +@param string The JSString to assign to the newly created JSValue. The + newly created JSValue retains string, and releases it upon garbage collection. +@result A JSValue of the string type, representing the value of string. +*/ +JS_EXPORT JSC_NULL_UNSPECIFIED JSValueRef JSValueMakeString(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSStringRef string); + +/*! + @function + @abstract Creates a JavaScript value of the symbol type. + @param ctx The execution context to use. + @param description A description of the newly created symbol value. + @result A unique JSValue of the symbol type, whose description matches the one provided. + */ +JS_EXPORT JSC_NULL_UNSPECIFIED JSValueRef JSValueMakeSymbol(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSStringRef description) JSC_API_AVAILABLE(macos(10.15), ios(13.0)); + +JSC_ASSUME_NONNULL_BEGIN +/*! + @function + @abstract Creates a JavaScript BigInt with a double. + @param ctx The execution context to use. + @param value The value to copy into the new BigInt JSValue. + @param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. + @result A BigInt JSValue of the value, or NULL if an exception is thrown. + @discussion If the value is not an integer, an exception is thrown. +*/ +JS_EXPORT JSValueRef JSBigIntCreateWithDouble(JSContextRef ctx, double value, JSC_NULLABLE JSValueRef* JSC_NULLABLE exception) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! + @function + @abstract Creates a JavaScript BigInt with a 64-bit signed integer. + @param ctx The execution context to use. + @param integer The 64-bit signed integer to copy into the new BigInt JSValue. + @param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. + @result A BigInt JSValue of the integer, or NULL if an exception is thrown. +*/ +JS_EXPORT JSValueRef JSBigIntCreateWithInt64(JSContextRef ctx, int64_t integer, JSC_NULLABLE JSValueRef* JSC_NULLABLE exception) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! + @function + @abstract Creates a JavaScript BigInt with a 64-bit unsigned integer. + @param ctx The execution context to use. + @param integer The 64-bit unsigned integer to copy into the new BigInt JSValue. + @param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. + @result A BigInt JSValue of the integer, or NULL if an exception is thrown. +*/ +JS_EXPORT JSValueRef JSBigIntCreateWithUInt64(JSContextRef ctx, uint64_t integer, JSC_NULLABLE JSValueRef* JSC_NULLABLE exception) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! + @function + @abstract Creates a JavaScript BigInt with an integer represented in string. + @param ctx The execution context to use. + @param string The JSStringRef representation of an integer. + @param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. + @result A BigInt JSValue of the string, or NULL if an exception is thrown. + @discussion This is equivalent to calling the `BigInt` constructor from JavaScript with a string argument. +*/ +JS_EXPORT JSValueRef JSBigIntCreateWithString(JSContextRef ctx, JSStringRef string, JSC_NULLABLE JSValueRef* JSC_NULLABLE exception) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); +JSC_ASSUME_NONNULL_END + +/* Converting to and from JSON formatted strings */ + +/*! + @function + @abstract Creates a JavaScript value from a JSON formatted string. + @param ctx The execution context to use. + @param string The JSString containing the JSON string to be parsed. + @result A JSValue containing the parsed value, or NULL if the input is invalid. + */ +JS_EXPORT JSC_NULL_UNSPECIFIED JSValueRef JSValueMakeFromJSONString(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSStringRef string) JSC_API_AVAILABLE(macos(10.7), ios(7.0)); + +/*! + @function + @abstract Creates a JavaScript string containing the JSON serialized representation of a JS value. + @param ctx The execution context to use. + @param value The value to serialize. + @param indent The number of spaces to indent when nesting. If 0, the resulting JSON will not contains newlines. The size of the indent is clamped to 10 spaces. + @param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. + @result A JSString with the result of serialization, or NULL if an exception is thrown. + */ +JS_EXPORT JSC_NULL_UNSPECIFIED JSStringRef JSValueCreateJSONString(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value, unsigned indent, JSC_NULL_UNSPECIFIED JSValueRef* JSC_NULL_UNSPECIFIED exception) JSC_API_AVAILABLE(macos(10.7), ios(7.0)); + +/* Converting to primitive values */ + +/*! +@function +@abstract Converts a JavaScript value to boolean and returns the resulting boolean. +@param ctx The execution context to use. +@param value The JSValue to convert. +@result The boolean result of conversion. +*/ +JS_EXPORT bool JSValueToBoolean(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value); + +/*! +@function +@abstract Converts a JavaScript value to number and returns the resulting number. +@param ctx The execution context to use. +@param value The JSValue to convert. +@param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. +@result The numeric result of conversion, or NaN if an exception is thrown. +@discussion The result is equivalent to `Number(value)` in JavaScript. +*/ +JS_EXPORT double JSValueToNumber(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value, JSC_NULL_UNSPECIFIED JSValueRef* JSC_NULL_UNSPECIFIED exception); + +JSC_ASSUME_NONNULL_BEGIN +/*! + @function + @abstract Converts a JSValue to a singed 32-bit integer and returns the resulting integer. + @param ctx The execution context to use. + @param value The JSValue to convert. + @param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. + @result An int32_t with the result of conversion, or 0 if an exception is thrown. Since 0 is valid value, `exception` must be checked after the call. + @discussion The JSValue is converted to an integer according to the rules specified by the JavaScript language. If the value is a BigInt, then the JSValue is truncated to an int32_t. +*/ +JS_EXPORT int32_t JSValueToInt32(JSContextRef ctx, JSValueRef value, JSC_NULLABLE JSValueRef* JSC_NULLABLE exception) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! + @function + @abstract Converts a JSValue to an unsigned 32-bit integer and returns the resulting integer. + @param ctx The execution context to use. + @param value The JSValue to convert. + @param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. + @result A uint32_t with the result of conversion, or 0 if an exception is thrown. Since 0 is valid value, `exception` must be checked after the call. + @discussion The JSValue is converted to an integer according to the rules specified by the JavaScript language. If the value is a BigInt, then the JSValue is truncated to a uint32_t. +*/ +JS_EXPORT uint32_t JSValueToUInt32(JSContextRef ctx, JSValueRef value, JSC_NULLABLE JSValueRef* JSC_NULLABLE exception) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! + @function + @abstract Converts a JSValue to a singed 64-bit integer and returns the resulting integer. + @param ctx The execution context to use. + @param value The JSValue to convert. + @param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. + @result An int64_t with the result of conversion, or 0 if an exception is thrown. Since 0 is valid value, `exception` must be checked after the call. + @discussion The JSValue is converted to an integer according to the rules specified by the JavaScript language. If the value is a BigInt, then the JSValue is truncated to an int64_t. +*/ +JS_EXPORT int64_t JSValueToInt64(JSContextRef ctx, JSValueRef value, JSC_NULLABLE JSValueRef* JSC_NULLABLE exception) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); + +/*! + @function + @abstract Converts a JSValue to an unsigned 64-bit integer and returns the resulting integer. + @param ctx The execution context to use. + @param value The JSValue to convert. + @param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. + @result A uint64_t with the result of conversion, or 0 if an exception is thrown. Since 0 is valid value, `exception` must be checked after the call. + @discussion The JSValue is converted to an integer according to the rules specified by the JavaScript language. If the value is a BigInt, then the JSValue is truncated to a uint64_t. +*/ +JS_EXPORT uint64_t JSValueToUInt64(JSContextRef ctx, JSValueRef value, JSC_NULLABLE JSValueRef* JSC_NULLABLE exception) JSC_API_AVAILABLE(macos(15.0), ios(18.0)); +JSC_ASSUME_NONNULL_END + +/*! +@function +@abstract Converts a JavaScript value to string and copies the result into a JavaScript string. +@param ctx The execution context to use. +@param value The JSValue to convert. +@param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. +@result A JSString with the result of conversion, or NULL if an exception is thrown. Ownership follows the Create Rule. +*/ +JS_EXPORT JSC_NULL_UNSPECIFIED JSStringRef JSValueToStringCopy(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value, JSC_NULL_UNSPECIFIED JSValueRef* JSC_NULL_UNSPECIFIED exception); + +/*! +@function +@abstract Converts a JavaScript value to object and returns the resulting object. +@param ctx The execution context to use. +@param value The JSValue to convert. +@param exception A pointer to a JSValueRef in which to store an exception, if any. To reliable detect exception, initialize this to null before the call. Pass NULL if you do not care to store an exception. +@result The JSObject result of conversion, or NULL if an exception is thrown. +*/ +JS_EXPORT JSC_NULL_UNSPECIFIED JSObjectRef JSValueToObject(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value, JSC_NULL_UNSPECIFIED JSValueRef* JSC_NULL_UNSPECIFIED exception); + +/* Garbage collection */ +/*! +@function +@abstract Protects a JavaScript value from garbage collection. +@param ctx The execution context to use. +@param value The JSValue to protect. +@discussion Use this method when you want to store a JSValue in a global or on the heap, where the garbage collector will not be able to discover your reference to it. + +A value may be protected multiple times and must be unprotected an equal number of times before becoming eligible for garbage collection. +*/ +JS_EXPORT void JSValueProtect(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value); + +/*! +@function +@abstract Unprotects a JavaScript value from garbage collection. +@param ctx The execution context to use. +@param value The JSValue to unprotect. +@discussion A value may be protected multiple times and must be unprotected an + equal number of times before becoming eligible for garbage collection. +*/ +JS_EXPORT void JSValueUnprotect(JSC_NULL_UNSPECIFIED JSContextRef ctx, JSC_NULL_UNSPECIFIED JSValueRef value); + + +#ifdef __cplusplus +} +#endif + +#endif /* JSValueRef_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSVirtualMachine.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSVirtualMachine.h similarity index 93% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSVirtualMachine.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSVirtualMachine.h index e9c75da0..3060b883 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSVirtualMachine.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSVirtualMachine.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013-2024 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,9 +23,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import +#ifndef JSVirtualMachine_h +#define JSVirtualMachine_h -#if JSC_OBJC_API_ENABLED +#include "JavaScriptCore.h" + +#if defined(__OBJC__) && JSC_OBJC_API_ENABLED /*! @interface @@ -85,3 +88,5 @@ NS_CLASS_AVAILABLE(10_9, 7_0) @end #endif + +#endif /* JSVirtualMachine_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSVirtualMachineInternal.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSVirtualMachineInternal.h similarity index 87% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSVirtualMachineInternal.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSVirtualMachineInternal.h index b533482a..08a9c4e8 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSVirtualMachineInternal.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSVirtualMachineInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2017 Apple Inc. All rights reserved. + * Copyright (C) 2013-2021 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,7 +32,7 @@ namespace JSC { class VM; -class SlotVisitor; +class AbstractSlotVisitor; } #if defined(__OBJC__) @@ -46,16 +46,16 @@ JSContextGroupRef getGroupFromVirtualMachine(JSVirtualMachine *); - (JSContext *)contextForGlobalContextRef:(JSGlobalContextRef)globalContext; - (void)addContext:(JSContext *)wrapper forGlobalContextRef:(JSGlobalContextRef)globalContext; -- (JSC::VM&)vm; - - (BOOL)isWebThreadAware; +@property (readonly) JSContextGroupRef JSContextGroupRef; + @end #endif // defined(__OBJC__) -void scanExternalObjectGraph(JSC::VM&, JSC::SlotVisitor&, void* root); -void scanExternalRememberedSet(JSC::VM&, JSC::SlotVisitor&); +void scanExternalObjectGraph(JSC::VM&, JSC::AbstractSlotVisitor&, void* root); +void scanExternalRememberedSet(JSC::VM&, JSC::AbstractSlotVisitor&); #endif // JSC_OBJC_API_ENABLED diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSVirtualMachinePrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSVirtualMachinePrivate.h similarity index 97% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSVirtualMachinePrivate.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSVirtualMachinePrivate.h index 950afc73..ff8906a2 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSVirtualMachinePrivate.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSVirtualMachinePrivate.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "JSExportMacros.h" -#include +#import +#import #if JSC_OBJC_API_ENABLED @@ -45,8 +45,6 @@ - (void)shrinkFootprintWhenIdle JSC_API_AVAILABLE(macos(10.14), ios(12.0)); -#if ENABLE(DFG_JIT) - /*! @method @abstract Set the number of threads to be used by the DFG JIT compiler. @@ -80,8 +78,6 @@ */ + (void)setCrashOnVMCreation:(BOOL)shouldCrash; -#endif // ENABLE(DFG_JIT) - @end #endif // JSC_OBJC_API_ENABLED diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWeakObjectMapRefInternal.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWeakObjectMapRefInternal.h similarity index 88% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWeakObjectMapRefInternal.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWeakObjectMapRefInternal.h index 9037947d..957dcb00 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWeakObjectMapRefInternal.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWeakObjectMapRefInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010-2022 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -39,6 +39,9 @@ typedef void (*JSWeakMapDestroyedCallback)(struct OpaqueJSWeakObjectMap*, void*) typedef JSC::WeakGCMap WeakMapType; +#define OPAQUE_JSWEAK_OBJECT_MAP_METHOD(method) \ + WTF_VTBL_FUNCPTR_PTRAUTH_STR("OpaqueJSWeakObjectMap." #method) method + struct OpaqueJSWeakObjectMap : public RefCounted { public: static Ref create(JSC::VM& vm, void* data, JSWeakMapDestroyedCallback callback) @@ -62,8 +65,9 @@ struct OpaqueJSWeakObjectMap : public RefCounted { } WeakMapType m_map; void* m_data; - JSWeakMapDestroyedCallback m_callback; + JSWeakMapDestroyedCallback OPAQUE_JSWEAK_OBJECT_MAP_METHOD(m_callback); }; +#undef OPAQUE_JSWEAK_OBJECT_MAP_METHOD #endif // JSWeakObjectMapInternal_h diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWeakObjectMapRefPrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWeakObjectMapRefPrivate.h similarity index 97% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWeakObjectMapRefPrivate.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWeakObjectMapRefPrivate.h index a335e23c..1df7f4a6 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWeakObjectMapRefPrivate.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWeakObjectMapRefPrivate.h @@ -26,8 +26,8 @@ #ifndef JSWeakObjectMapRefPrivate_h #define JSWeakObjectMapRefPrivate_h -#include -#include +#include "JSContextRef.h" +#include "JSValueRef.h" #ifdef __cplusplus extern "C" { diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWeakPrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWeakPrivate.h similarity index 94% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWeakPrivate.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWeakPrivate.h index 9ca2ffa6..b77c8b9c 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWeakPrivate.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWeakPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Apple Inc. All rights reserved. + * Copyright (C) 2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,7 +26,7 @@ #ifndef JSWeakPrivate_h #define JSWeakPrivate_h -#include +#include "JSObjectRef.h" #ifdef __cplusplus extern "C" { diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWeakValue.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWeakValue.h similarity index 97% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWeakValue.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWeakValue.h index 177ef41c..e5ab2b14 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWeakValue.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWeakValue.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. * Copyright (C) 2018 Igalia S.L. * * Redistribution and use in source and binary forms, with or without diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWrapperMap.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWrapperMap.h similarity index 95% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWrapperMap.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWrapperMap.h index 6c18c64b..a5946a8f 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSWrapperMap.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JSWrapperMap.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013-2023 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#import "JSValueInternal.h" #import -#import #import #if JSC_OBJC_API_ENABLED diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JavaScript.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JavaScript.h similarity index 85% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JavaScript.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JavaScript.h index 251e3937..093e9f35 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JavaScript.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JavaScript.h @@ -21,17 +21,17 @@ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef JavaScript_h #define JavaScript_h -#include -#include -#include -#include -#include -#include +#include "JSBase.h" +#include "JSContextRef.h" +#include "JSObjectRef.h" +#include "JSStringRef.h" +#include "JSTypedArray.h" +#include "JSValueRef.h" #endif /* JavaScript_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JavaScriptCore.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JavaScriptCore.h similarity index 84% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JavaScriptCore.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JavaScriptCore.h index b2fde1db..b940825a 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JavaScriptCore.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/JavaScriptCore.h @@ -26,17 +26,13 @@ #ifndef JavaScriptCore_h #define JavaScriptCore_h -#include -#include +#include "JavaScript.h" +#include "JSStringRefCF.h" -#if defined(__OBJC__) && JSC_OBJC_API_ENABLED - -#import "JSContext.h" -#import "JSValue.h" -#import "JSManagedValue.h" -#import "JSVirtualMachine.h" -#import "JSExport.h" - -#endif +#include "JSContext.h" +#include "JSValue.h" +#include "JSManagedValue.h" +#include "JSVirtualMachine.h" +#include "JSExport.h" #endif /* JavaScriptCore_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/MarkedJSValueRefArray.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/MarkedJSValueRefArray.h new file mode 100644 index 00000000..519951bf --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/MarkedJSValueRefArray.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2020-2021 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "APICast.h" +#include "ArgList.h" +#include +#include +#include +#include + +WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN + +namespace JSC { + +class MarkedJSValueRefArray final : public BasicRawSentinelNode { + WTF_MAKE_NONCOPYABLE(MarkedJSValueRefArray); + WTF_MAKE_NONMOVABLE(MarkedJSValueRefArray); + WTF_FORBID_HEAP_ALLOCATION; +public: + static constexpr size_t inlineCapacity = MarkedArgumentBuffer::inlineCapacity; + + JS_EXPORT_PRIVATE MarkedJSValueRefArray(JSGlobalContextRef, unsigned); + JS_EXPORT_PRIVATE ~MarkedJSValueRefArray(); + + size_t size() const { return m_size; } + bool isEmpty() const { return !m_size; } + + JSValueRef& operator[](unsigned index) LIFETIME_BOUND { return data()[index]; } + + const JSValueRef* data() const LIFETIME_BOUND + { + return const_cast(this)->data(); + } + + JSValueRef* data() LIFETIME_BOUND + { + if (m_buffer) + return m_buffer.get(); + return m_inlineBuffer; + } + + template void visitAggregate(Visitor&); + +private: + unsigned m_size; + JSValueRef m_inlineBuffer[inlineCapacity] { }; + UniqueArray m_buffer; +}; + +} // namespace JSC + +WTF_ALLOW_UNSAFE_BUFFER_USAGE_END diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/ObjCCallbackFunction.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/ObjCCallbackFunction.h similarity index 82% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/ObjCCallbackFunction.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/ObjCCallbackFunction.h index c30c1562..c6016fa7 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/ObjCCallbackFunction.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/ObjCCallbackFunction.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2013-2022 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,36 +25,42 @@ #ifndef ObjCCallbackFunction_h #define ObjCCallbackFunction_h -#include +#include "JSBase.h" #if JSC_OBJC_API_ENABLED -#import +#import "JSCallbackFunction.h" #if defined(__OBJC__) +@class JSContext; + JSObjectRef objCCallbackFunctionForMethod(JSContext *, Class, Protocol *, BOOL isInstanceMethod, SEL, const char* types); JSObjectRef objCCallbackFunctionForBlock(JSContext *, id); JSObjectRef objCCallbackFunctionForInit(JSContext *, Class, Protocol *, SEL, const char* types); -id tryUnwrapConstructor(JSC::VM*, JSObjectRef); +id tryUnwrapConstructor(JSObjectRef); #endif namespace JSC { class ObjCCallbackFunctionImpl; +#define OBJC_CALLBACK_FUNCTION_METHOD(method) \ + WTF_VTBL_FUNCPTR_PTRAUTH_STR("ObjCCallbackFunction." #method) method + class ObjCCallbackFunction : public InternalFunction { friend struct APICallbackFunction; public: typedef InternalFunction Base; template - static IsoSubspace* subspaceFor(VM& vm) + static GCClient::IsoSubspace* subspaceFor(VM& vm) { return vm.objCCallbackFunctionSpace(); } static ObjCCallbackFunction* create(VM&, JSGlobalObject*, const String& name, std::unique_ptr); + static constexpr DestructionMode needsDestruction = NeedsDestruction; static void destroy(JSCell*); static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) @@ -74,11 +80,13 @@ class ObjCCallbackFunction : public InternalFunction { JSObjectCallAsFunctionCallback functionCallback() { return m_functionCallback; } JSObjectCallAsConstructorCallback constructCallback() { return m_constructCallback; } - JSObjectCallAsFunctionCallback m_functionCallback; - JSObjectCallAsConstructorCallback m_constructCallback; + JSObjectCallAsFunctionCallback OBJC_CALLBACK_FUNCTION_METHOD(m_functionCallback); + JSObjectCallAsConstructorCallback OBJC_CALLBACK_FUNCTION_METHOD(m_constructCallback); std::unique_ptr m_impl; }; +#undef OBJC_CALLBACK_FUNCTION_METHOD + } // namespace JSC #endif diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/ObjcRuntimeExtras.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/ObjcRuntimeExtras.h similarity index 81% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/ObjcRuntimeExtras.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/ObjcRuntimeExtras.h index 20d8b858..48dd1a93 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/ObjcRuntimeExtras.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/ObjcRuntimeExtras.h @@ -27,10 +27,13 @@ #import #import #import +#import #import #import #import +WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN + template inline std::unique_ptr> adoptSystem(U value) { @@ -39,10 +42,9 @@ inline std::unique_ptr> adoptSystem(U value) inline bool protocolImplementsProtocol(Protocol *candidate, Protocol *target) { - unsigned protocolProtocolsCount; - auto protocolProtocols = adoptSystem<__unsafe_unretained Protocol*[]>(protocol_copyProtocolList(candidate, &protocolProtocolsCount)); - for (unsigned i = 0; i < protocolProtocolsCount; ++i) { - if (protocol_isEqual(protocolProtocols[i], target)) + auto protocolProtocols = protocol_copyProtocolListSpan(candidate); + for (auto* protocolProtocol : protocolProtocols.span()) { + if (protocol_isEqual(protocolProtocol, target)) return true; } return false; @@ -54,13 +56,12 @@ inline void forEachProtocolImplementingProtocol(Class cls, Protocol *target, voi ASSERT(target); Vector worklist; - HashSet visited; + UncheckedKeyHashSet visited; // Initially fill the worklist with the Class's protocols. { - unsigned protocolsCount; - auto protocols = adoptSystem<__unsafe_unretained Protocol*[]>(class_copyProtocolList(cls, &protocolsCount)); - worklist.append(protocols.get(), protocolsCount); + auto protocols = class_copyProtocolListSpan(cls); + worklist.append(protocols.span()); } bool stop = false; @@ -80,36 +81,29 @@ inline void forEachProtocolImplementingProtocol(Class cls, Protocol *target, voi } // Add incorporated protocols to the worklist. - { - unsigned protocolsCount; - auto protocols = adoptSystem<__unsafe_unretained Protocol*[]>(protocol_copyProtocolList(protocol, &protocolsCount)); - worklist.append(protocols.get(), protocolsCount); - } + worklist.append(protocol_copyProtocolListSpan(protocol).span()); } } inline void forEachMethodInClass(Class cls, void (^callback)(Method)) { - unsigned count; - auto methods = adoptSystem(class_copyMethodList(cls, &count)); - for (unsigned i = 0; i < count; ++i) - callback(methods[i]); + auto methods = class_copyMethodListSpan(cls); + for (auto& method : methods.span()) + callback(method); } inline void forEachMethodInProtocol(Protocol *protocol, BOOL isRequiredMethod, BOOL isInstanceMethod, void (^callback)(SEL, const char*)) { - unsigned count; - auto methods = adoptSystem(protocol_copyMethodDescriptionList(protocol, isRequiredMethod, isInstanceMethod, &count)); - for (unsigned i = 0; i < count; ++i) - callback(methods[i].name, methods[i].types); + auto methods = protocol_copyMethodDescriptionListSpan(protocol, isRequiredMethod, isInstanceMethod); + for (auto& method : methods.span()) + callback(method.name, method.types); } inline void forEachPropertyInProtocol(Protocol *protocol, void (^callback)(objc_property_t)) { - unsigned count; - auto properties = adoptSystem(protocol_copyPropertyList(protocol, &count)); - for (unsigned i = 0; i < count; ++i) - callback(properties[i]); + auto properties = protocol_copyPropertyListSpan(protocol); + for (auto& property : properties.span()) + callback(property); } template @@ -131,10 +125,10 @@ class StringRange { WTF_MAKE_NONCOPYABLE(StringRange); public: StringRange(const char* begin, const char* end) - : m_string(begin, end - begin) + : m_string({ begin, end }) { } - operator const char*() const { return m_string.data(); } - const char* get() const { return m_string.data(); } + operator const char*() const LIFETIME_BOUND { return m_string.data(); } + const char* get() const LIFETIME_BOUND { return m_string.data(); } private: CString m_string; @@ -243,8 +237,8 @@ typename DelegateType::ResultType parseObjCType(const char*& position) extern "C" { // Forward declare some Objective-C runtime internal methods that are not API. const char *_protocol_getMethodTypeEncoding(Protocol *, SEL, BOOL isRequiredMethod, BOOL isInstanceMethod); - id objc_initWeak(id *, id); - void objc_destroyWeak(id *); bool _Block_has_signature(void *); const char * _Block_signature(void *); } + +WTF_ALLOW_UNSAFE_BUFFER_USAGE_END diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/OpaqueJSString.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/OpaqueJSString.h similarity index 75% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/OpaqueJSString.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/OpaqueJSString.h index 4a4b5edf..b6c43f35 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/OpaqueJSString.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/OpaqueJSString.h @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OpaqueJSString_h -#define OpaqueJSString_h +#pragma once #include #include @@ -41,14 +40,14 @@ struct OpaqueJSString : public ThreadSafeRefCounted { return adoptRef(*new OpaqueJSString); } - static Ref create(const LChar* characters, unsigned length) + static Ref create(std::span characters) { - return adoptRef(*new OpaqueJSString(characters, length)); + return adoptRef(*new OpaqueJSString(characters)); } - static Ref create(const UChar* characters, unsigned length) + static Ref create(std::span characters) { - return adoptRef(*new OpaqueJSString(characters, length)); + return adoptRef(*new OpaqueJSString(characters)); } JS_EXPORT_PRIVATE static RefPtr tryCreate(const String&); @@ -57,11 +56,11 @@ struct OpaqueJSString : public ThreadSafeRefCounted { JS_EXPORT_PRIVATE ~OpaqueJSString(); bool is8Bit() { return m_string.is8Bit(); } - const LChar* characters8() { return m_string.characters8(); } - const UChar* characters16() { return m_string.characters16(); } + std::span span8() LIFETIME_BOUND { return m_string.span8(); } + std::span span16() LIFETIME_BOUND { return m_string.span16(); } unsigned length() { return m_string.length(); } - const UChar* characters(); + const char16_t* characters() LIFETIME_BOUND; JS_EXPORT_PRIVATE String string() const; JSC::Identifier identifier(JSC::VM*) const; @@ -78,32 +77,30 @@ struct OpaqueJSString : public ThreadSafeRefCounted { OpaqueJSString(const String& string) : m_string(string.isolatedCopy()) - , m_characters(m_string.impl() && m_string.is8Bit() ? nullptr : const_cast(m_string.characters16())) + , m_characters(m_string.impl() && m_string.is8Bit() ? nullptr : const_cast(m_string.span16().data())) { } explicit OpaqueJSString(String&& string) : m_string(WTFMove(string)) - , m_characters(m_string.impl() && m_string.is8Bit() ? nullptr : const_cast(m_string.characters16())) + , m_characters(m_string.impl() && m_string.is8Bit() ? nullptr : const_cast(m_string.span16().data())) { } - OpaqueJSString(const LChar* characters, unsigned length) - : m_string(characters, length) + OpaqueJSString(std::span characters) + : m_string(characters) , m_characters(nullptr) { } - OpaqueJSString(const UChar* characters, unsigned length) - : m_string(characters, length) - , m_characters(m_string.impl() && m_string.is8Bit() ? nullptr : const_cast(m_string.characters16())) + OpaqueJSString(std::span characters) + : m_string(characters) + , m_characters(m_string.impl() && m_string.is8Bit() ? nullptr : const_cast(m_string.span16().data())) { } String m_string; // This will be initialized on demand when characters() is called if the string needs up-conversion. - std::atomic m_characters; + std::atomic m_characters; }; - -#endif diff --git a/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/PASReportCrashPrivate.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/PASReportCrashPrivate.h new file mode 100644 index 00000000..ce7bbc8a --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/PASReportCrashPrivate.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "JSBase.h" + +#ifdef __APPLE__ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +JS_EXPORT kern_return_t PASReportCrashExtractResults(vm_address_t fault_address, mach_vm_address_t pas_dead_root, unsigned version, task_t task, pas_report_crash_pgm_report *report, crash_reporter_memory_reader_t crm_reader); + +#ifdef __cplusplus +} +#endif + +#endif /* __APPLE__ */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/WebKitAvailability.h b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/WebKitAvailability.h similarity index 86% rename from test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/WebKitAvailability.h rename to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/WebKitAvailability.h index 2a1ce7ce..ab63ae80 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/WebKitAvailability.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/WebKitAvailability.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009, 2010, 2014 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009, 2010, 2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,13 +31,13 @@ #include #include -#if defined(BUILDING_GTK__) -#undef JSC_API_AVAILABLE -#define JSC_API_AVAILABLE(...) #endif -#else +#ifndef JSC_FRAMEWORK_HEADER_POSTPROCESSING_ENABLED #define JSC_API_AVAILABLE(...) +#define JSC_API_DEPRECATED(...) +#define JSC_API_DEPRECATED_WITH_REPLACEMENT(...) +#define JSC_CLASS_AVAILABLE(...) JS_EXPORT #endif #endif /* __WebKitAvailability__ */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/APICallbackFunction.h b/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/APICallbackFunction.h deleted file mode 100644 index e5283b5b..00000000 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/APICallbackFunction.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef APICallbackFunction_h -#define APICallbackFunction_h - -#include "APICast.h" -#include "Error.h" -#include "JSCallbackConstructor.h" -#include "JSLock.h" -#include - -namespace JSC { - -struct APICallbackFunction { - -template static EncodedJSValue JSC_HOST_CALL call(ExecState*); -template static EncodedJSValue JSC_HOST_CALL construct(ExecState*); - -}; - -template -EncodedJSValue JSC_HOST_CALL APICallbackFunction::call(ExecState* exec) -{ - VM& vm = exec->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - JSContextRef execRef = toRef(exec); - JSObjectRef functionRef = toRef(exec->jsCallee()); - JSObjectRef thisObjRef = toRef(jsCast(exec->thisValue().toThis(exec, NotStrictMode))); - - int argumentCount = static_cast(exec->argumentCount()); - Vector arguments; - arguments.reserveInitialCapacity(argumentCount); - for (int i = 0; i < argumentCount; i++) - arguments.uncheckedAppend(toRef(exec, exec->uncheckedArgument(i))); - - JSValueRef exception = 0; - JSValueRef result; - { - JSLock::DropAllLocks dropAllLocks(exec); - result = jsCast(toJS(functionRef))->functionCallback()(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception); - } - if (exception) - throwException(exec, scope, toJS(exec, exception)); - - // result must be a valid JSValue. - if (!result) - return JSValue::encode(jsUndefined()); - - return JSValue::encode(toJS(exec, result)); -} - -template -EncodedJSValue JSC_HOST_CALL APICallbackFunction::construct(ExecState* exec) -{ - VM& vm = exec->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - JSObject* constructor = exec->jsCallee(); - JSContextRef ctx = toRef(exec); - JSObjectRef constructorRef = toRef(constructor); - - JSObjectCallAsConstructorCallback callback = jsCast(constructor)->constructCallback(); - if (callback) { - size_t argumentCount = exec->argumentCount(); - Vector arguments; - arguments.reserveInitialCapacity(argumentCount); - for (size_t i = 0; i < argumentCount; ++i) - arguments.uncheckedAppend(toRef(exec, exec->uncheckedArgument(i))); - - JSValueRef exception = 0; - JSObjectRef result; - { - JSLock::DropAllLocks dropAllLocks(exec); - result = callback(ctx, constructorRef, argumentCount, arguments.data(), &exception); - } - if (exception) { - throwException(exec, scope, toJS(exec, exception)); - return JSValue::encode(toJS(exec, exception)); - } - // result must be a valid JSValue. - if (!result) - return throwVMTypeError(exec, scope); - return JSValue::encode(toJS(result)); - } - - return JSValue::encode(toJS(JSObjectMake(ctx, jsCast(constructor)->classRef(), 0))); -} - -} // namespace JSC - -#endif // APICallbackFunction_h diff --git a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSValueRef.h b/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSValueRef.h deleted file mode 100644 index 911b4bfc..00000000 --- a/test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/JSValueRef.h +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (C) 2006-2019 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JSValueRef_h -#define JSValueRef_h - -#include -#include - -#ifndef __cplusplus -#include -#endif - -/*! -@enum JSType -@abstract A constant identifying the type of a JSValue. -@constant kJSTypeUndefined The unique undefined value. -@constant kJSTypeNull The unique null value. -@constant kJSTypeBoolean A primitive boolean value, one of true or false. -@constant kJSTypeNumber A primitive number value. -@constant kJSTypeString A primitive string value. -@constant kJSTypeObject An object value (meaning that this JSValueRef is a JSObjectRef). -@constant kJSTypeSymbol A primitive symbol value. -*/ -typedef enum { - kJSTypeUndefined, - kJSTypeNull, - kJSTypeBoolean, - kJSTypeNumber, - kJSTypeString, - kJSTypeObject, - kJSTypeSymbol JSC_API_AVAILABLE(macos(10.15), ios(13.0)) -} JSType; - -/*! - @enum JSTypedArrayType - @abstract A constant identifying the Typed Array type of a JSObjectRef. - @constant kJSTypedArrayTypeInt8Array Int8Array - @constant kJSTypedArrayTypeInt16Array Int16Array - @constant kJSTypedArrayTypeInt32Array Int32Array - @constant kJSTypedArrayTypeUint8Array Uint8Array - @constant kJSTypedArrayTypeUint8ClampedArray Uint8ClampedArray - @constant kJSTypedArrayTypeUint16Array Uint16Array - @constant kJSTypedArrayTypeUint32Array Uint32Array - @constant kJSTypedArrayTypeFloat32Array Float32Array - @constant kJSTypedArrayTypeFloat64Array Float64Array - @constant kJSTypedArrayTypeArrayBuffer ArrayBuffer - @constant kJSTypedArrayTypeNone Not a Typed Array - - */ -typedef enum { - kJSTypedArrayTypeInt8Array, - kJSTypedArrayTypeInt16Array, - kJSTypedArrayTypeInt32Array, - kJSTypedArrayTypeUint8Array, - kJSTypedArrayTypeUint8ClampedArray, - kJSTypedArrayTypeUint16Array, - kJSTypedArrayTypeUint32Array, - kJSTypedArrayTypeFloat32Array, - kJSTypedArrayTypeFloat64Array, - kJSTypedArrayTypeArrayBuffer, - kJSTypedArrayTypeNone, -} JSTypedArrayType JSC_API_AVAILABLE(macos(10.12), ios(10.0)); - -#ifdef __cplusplus -extern "C" { -#endif - -/*! -@function -@abstract Returns a JavaScript value's type. -@param ctx The execution context to use. -@param value The JSValue whose type you want to obtain. -@result A value of type JSType that identifies value's type. -*/ -JS_EXPORT JSType JSValueGetType(JSContextRef ctx, JSValueRef value); - -/*! -@function -@abstract Tests whether a JavaScript value's type is the undefined type. -@param ctx The execution context to use. -@param value The JSValue to test. -@result true if value's type is the undefined type, otherwise false. -*/ -JS_EXPORT bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value); - -/*! -@function -@abstract Tests whether a JavaScript value's type is the null type. -@param ctx The execution context to use. -@param value The JSValue to test. -@result true if value's type is the null type, otherwise false. -*/ -JS_EXPORT bool JSValueIsNull(JSContextRef ctx, JSValueRef value); - -/*! -@function -@abstract Tests whether a JavaScript value's type is the boolean type. -@param ctx The execution context to use. -@param value The JSValue to test. -@result true if value's type is the boolean type, otherwise false. -*/ -JS_EXPORT bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value); - -/*! -@function -@abstract Tests whether a JavaScript value's type is the number type. -@param ctx The execution context to use. -@param value The JSValue to test. -@result true if value's type is the number type, otherwise false. -*/ -JS_EXPORT bool JSValueIsNumber(JSContextRef ctx, JSValueRef value); - -/*! -@function -@abstract Tests whether a JavaScript value's type is the string type. -@param ctx The execution context to use. -@param value The JSValue to test. -@result true if value's type is the string type, otherwise false. -*/ -JS_EXPORT bool JSValueIsString(JSContextRef ctx, JSValueRef value); - -/*! -@function -@abstract Tests whether a JavaScript value's type is the symbol type. -@param ctx The execution context to use. -@param value The JSValue to test. -@result true if value's type is the symbol type, otherwise false. -*/ -JS_EXPORT bool JSValueIsSymbol(JSContextRef ctx, JSValueRef value) JSC_API_AVAILABLE(macos(10.15), ios(13.0)); - -/*! -@function -@abstract Tests whether a JavaScript value's type is the object type. -@param ctx The execution context to use. -@param value The JSValue to test. -@result true if value's type is the object type, otherwise false. -*/ -JS_EXPORT bool JSValueIsObject(JSContextRef ctx, JSValueRef value); - - -/*! -@function -@abstract Tests whether a JavaScript value is an object with a given class in its class chain. -@param ctx The execution context to use. -@param value The JSValue to test. -@param jsClass The JSClass to test against. -@result true if value is an object and has jsClass in its class chain, otherwise false. -*/ -JS_EXPORT bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass); - -/*! -@function -@abstract Tests whether a JavaScript value is an array. -@param ctx The execution context to use. -@param value The JSValue to test. -@result true if value is an array, otherwise false. -*/ -JS_EXPORT bool JSValueIsArray(JSContextRef ctx, JSValueRef value) JSC_API_AVAILABLE(macos(10.11), ios(9.0)); - -/*! -@function -@abstract Tests whether a JavaScript value is a date. -@param ctx The execution context to use. -@param value The JSValue to test. -@result true if value is a date, otherwise false. -*/ -JS_EXPORT bool JSValueIsDate(JSContextRef ctx, JSValueRef value) JSC_API_AVAILABLE(macos(10.11), ios(9.0)); - -/*! -@function -@abstract Returns a JavaScript value's Typed Array type. -@param ctx The execution context to use. -@param value The JSValue whose Typed Array type to return. -@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. -@result A value of type JSTypedArrayType that identifies value's Typed Array type, or kJSTypedArrayTypeNone if the value is not a Typed Array object. - */ -JS_EXPORT JSTypedArrayType JSValueGetTypedArrayType(JSContextRef ctx, JSValueRef value, JSValueRef* exception) JSC_API_AVAILABLE(macos(10.12), ios(10.0)); - -/* Comparing values */ - -/*! -@function -@abstract Tests whether two JavaScript values are equal, as compared by the JS == operator. -@param ctx The execution context to use. -@param a The first value to test. -@param b The second value to test. -@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. -@result true if the two values are equal, false if they are not equal or an exception is thrown. -*/ -JS_EXPORT bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception); - -/*! -@function -@abstract Tests whether two JavaScript values are strict equal, as compared by the JS === operator. -@param ctx The execution context to use. -@param a The first value to test. -@param b The second value to test. -@result true if the two values are strict equal, otherwise false. -*/ -JS_EXPORT bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b); - -/*! -@function -@abstract Tests whether a JavaScript value is an object constructed by a given constructor, as compared by the JS instanceof operator. -@param ctx The execution context to use. -@param value The JSValue to test. -@param constructor The constructor to test against. -@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. -@result true if value is an object constructed by constructor, as compared by the JS instanceof operator, otherwise false. -*/ -JS_EXPORT bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception); - -/* Creating values */ - -/*! -@function -@abstract Creates a JavaScript value of the undefined type. -@param ctx The execution context to use. -@result The unique undefined value. -*/ -JS_EXPORT JSValueRef JSValueMakeUndefined(JSContextRef ctx); - -/*! -@function -@abstract Creates a JavaScript value of the null type. -@param ctx The execution context to use. -@result The unique null value. -*/ -JS_EXPORT JSValueRef JSValueMakeNull(JSContextRef ctx); - -/*! -@function -@abstract Creates a JavaScript value of the boolean type. -@param ctx The execution context to use. -@param boolean The bool to assign to the newly created JSValue. -@result A JSValue of the boolean type, representing the value of boolean. -*/ -JS_EXPORT JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool boolean); - -/*! -@function -@abstract Creates a JavaScript value of the number type. -@param ctx The execution context to use. -@param number The double to assign to the newly created JSValue. -@result A JSValue of the number type, representing the value of number. -*/ -JS_EXPORT JSValueRef JSValueMakeNumber(JSContextRef ctx, double number); - -/*! -@function -@abstract Creates a JavaScript value of the string type. -@param ctx The execution context to use. -@param string The JSString to assign to the newly created JSValue. The - newly created JSValue retains string, and releases it upon garbage collection. -@result A JSValue of the string type, representing the value of string. -*/ -JS_EXPORT JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string); - -/*! - @function - @abstract Creates a JavaScript value of the symbol type. - @param ctx The execution context to use. - @param description A description of the newly created symbol value. - @result A unique JSValue of the symbol type, whose description matches the one provided. - */ -JS_EXPORT JSValueRef JSValueMakeSymbol(JSContextRef ctx, JSStringRef description) JSC_API_AVAILABLE(macos(10.15), ios(13.0)); - -/* Converting to and from JSON formatted strings */ - -/*! - @function - @abstract Creates a JavaScript value from a JSON formatted string. - @param ctx The execution context to use. - @param string The JSString containing the JSON string to be parsed. - @result A JSValue containing the parsed value, or NULL if the input is invalid. - */ -JS_EXPORT JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string) JSC_API_AVAILABLE(macos(10.7), ios(7.0)); - -/*! - @function - @abstract Creates a JavaScript string containing the JSON serialized representation of a JS value. - @param ctx The execution context to use. - @param value The value to serialize. - @param indent The number of spaces to indent when nesting. If 0, the resulting JSON will not contains newlines. The size of the indent is clamped to 10 spaces. - @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. - @result A JSString with the result of serialization, or NULL if an exception is thrown. - */ -JS_EXPORT JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef value, unsigned indent, JSValueRef* exception) JSC_API_AVAILABLE(macos(10.7), ios(7.0)); - -/* Converting to primitive values */ - -/*! -@function -@abstract Converts a JavaScript value to boolean and returns the resulting boolean. -@param ctx The execution context to use. -@param value The JSValue to convert. -@result The boolean result of conversion. -*/ -JS_EXPORT bool JSValueToBoolean(JSContextRef ctx, JSValueRef value); - -/*! -@function -@abstract Converts a JavaScript value to number and returns the resulting number. -@param ctx The execution context to use. -@param value The JSValue to convert. -@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. -@result The numeric result of conversion, or NaN if an exception is thrown. -*/ -JS_EXPORT double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception); - -/*! -@function -@abstract Converts a JavaScript value to string and copies the result into a JavaScript string. -@param ctx The execution context to use. -@param value The JSValue to convert. -@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. -@result A JSString with the result of conversion, or NULL if an exception is thrown. Ownership follows the Create Rule. -*/ -JS_EXPORT JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception); - -/*! -@function -@abstract Converts a JavaScript value to object and returns the resulting object. -@param ctx The execution context to use. -@param value The JSValue to convert. -@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. -@result The JSObject result of conversion, or NULL if an exception is thrown. -*/ -JS_EXPORT JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception); - -/* Garbage collection */ -/*! -@function -@abstract Protects a JavaScript value from garbage collection. -@param ctx The execution context to use. -@param value The JSValue to protect. -@discussion Use this method when you want to store a JSValue in a global or on the heap, where the garbage collector will not be able to discover your reference to it. - -A value may be protected multiple times and must be unprotected an equal number of times before becoming eligible for garbage collection. -*/ -JS_EXPORT void JSValueProtect(JSContextRef ctx, JSValueRef value); - -/*! -@function -@abstract Unprotects a JavaScript value from garbage collection. -@param ctx The execution context to use. -@param value The JSValue to unprotect. -@discussion A value may be protected multiple times and must be unprotected an - equal number of times before becoming eligible for garbage collection. -*/ -JS_EXPORT void JSValueUnprotect(JSContextRef ctx, JSValueRef value); - -#ifdef __cplusplus -} -#endif - -#endif /* JSValueRef_h */ diff --git a/test-app/runtime/src/main/cpp/napi/jsc/jsc-api.cpp b/test-app/runtime/src/main/cpp/napi/jsc/jsc-api.cpp index 0f2a615d..3a609a84 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/jsc-api.cpp +++ b/test-app/runtime/src/main/cpp/napi/jsc/jsc-api.cpp @@ -1,4 +1,7 @@ #include "jsc-api.h" +// Native weak references (JSWeakCreate / JSWeakGetObject) live in this private +// JSC header; used by napi_ref__ to back weak references. +#include "JavaScriptCore/JSWeakPrivate.h" #include #include #include @@ -534,37 +537,6 @@ class ExternalInfo: public BaseInfoT { } }; -class ReferenceInfo : public BaseInfoT { - public: - static napi_status Initialize(napi_env env, napi_value object, FinalizerT finalizer) { - - napi_valuetype type; - napi_typeof(env, object, &type); - - if (type == napi_object || type == napi_function) { - ReferenceInfo* info = new ReferenceInfo(env); - if (info == nullptr) { - return napi_set_last_error(env, napi_generic_failure); - } - - // JSObjectRef ref{JSObjectMake(env->context, info->_class, info)}; - // JSObjectSetPrototype(env->context, prototype, JSObjectGetPrototype(env->context, ToJSObject(env, object))); - // JSObjectSetPrototype(env->context, ToJSObject(env, object), prototype); - - NativeInfo::SetNativeInfo(env->context, ToJSObject(env, object), info->_class, "[[jsc_reference_info]]", info); - - info->AddFinalizer(finalizer); - } - - return napi_ok; - } - - private: - ReferenceInfo(napi_env env) - : BaseInfoT{env, "Native (Reference)"} { - } -}; - class WrapperInfo : public BaseInfoT { public: static napi_status Wrap(napi_env env, napi_value object, WrapperInfo** result) { @@ -659,12 +631,13 @@ struct napi_ref__ { } napi_status init(napi_env env) { - // track the ref values to support weak refs - auto pair{env->active_ref_values.insert(_value)}; - if (pair.second) { - CHECK_NAPI(ReferenceInfo::Initialize(env, _value, [value = _value](ReferenceInfo* info) { - info->Env()->active_ref_values.erase(value); - })); + // For objects we hold a native JSC weak reference, which lets value() + // report when the target has been collected without pinning it or + // mutating the object. Non-object values (e.g. symbols) cannot be + // weakly tracked and are returned on a best-effort basis. + JSValueRef jsValue{ToJSValue(_value)}; + if (JSValueIsObject(env->context, jsValue)) { + _weak = JSWeakCreate(JSContextGetGroup(env->context), ToJSObject(env, _value)); } if (_count != 0) { @@ -679,6 +652,11 @@ struct napi_ref__ { unprotect(env); } + if (_weak != nullptr) { + JSWeakRelease(JSContextGetGroup(env->context), _weak); + _weak = nullptr; + } + _value = nullptr; _count = 0; } @@ -700,10 +678,13 @@ struct napi_ref__ { } napi_value value(napi_env env) const { - if (env->active_ref_values.find(_value) == env->active_ref_values.end()) { - return nullptr; + if (_weak != nullptr) { + // Returns NULL once the target object has been garbage-collected. + JSObjectRef object{JSWeakGetObject(_weak)}; + return object != nullptr ? ToNapi(object) : nullptr; } + // Non-object value: not weakly trackable, returned as-is. return _value; } @@ -721,6 +702,7 @@ struct napi_ref__ { napi_value _value{}; uint32_t _count{}; + JSWeakRef _weak{}; std::list::iterator _iter{}; }; @@ -867,7 +849,8 @@ napi_status napi_get_property_names(napi_env env, CHECK_NAPI(napi_get_global(env, &global)); CHECK_NAPI(napi_get_named_property(env, global, "Object", &object_ctor)); CHECK_NAPI(napi_get_named_property(env, object_ctor, "getOwnPropertyNames", &function)); - CHECK_NAPI(napi_call_function(env, object_ctor, function, 0, nullptr, result)); + // Object.getOwnPropertyNames(object) + CHECK_NAPI(napi_call_function(env, object_ctor, function, 1, &object, result)); return napi_ok; } @@ -959,20 +942,23 @@ napi_status napi_delete_property(napi_env env, } NAPI_EXTERN napi_status napi_has_own_property(napi_env env, -napi_value object, - napi_value key, -bool* result) { -CHECK_ENV(env); -CHECK_ARG(env, result); + napi_value object, + napi_value key, + bool* result) { + CHECK_ENV(env); + CHECK_ARG(env, key); + CHECK_ARG(env, result); -napi_value global{}, object_ctor{}, function{}, value{}; -CHECK_NAPI(napi_get_global(env, &global)); -CHECK_NAPI(napi_get_named_property(env, global, "Object", &object_ctor)); -CHECK_NAPI(napi_get_named_property(env, object_ctor, "hasOwnProperty", &function)); -CHECK_NAPI(napi_call_function(env, object_ctor, function, 0, nullptr, &value)); -*result = JSValueToBoolean(env->context, ToJSValue(value)); + // Object.prototype.hasOwnProperty.call(object, key) + napi_value global{}, object_ctor{}, proto{}, function{}, value{}; + CHECK_NAPI(napi_get_global(env, &global)); + CHECK_NAPI(napi_get_named_property(env, global, "Object", &object_ctor)); + CHECK_NAPI(napi_get_named_property(env, object_ctor, "prototype", &proto)); + CHECK_NAPI(napi_get_named_property(env, proto, "hasOwnProperty", &function)); + CHECK_NAPI(napi_call_function(env, object, function, 1, &key, &value)); + *result = JSValueToBoolean(env->context, ToJSValue(value)); -return napi_ok; + return napi_ok; } napi_status napi_set_named_property(napi_env env, @@ -1128,7 +1114,7 @@ napi_status napi_define_properties(napi_env env, CHECK_NAPI(napi_set_named_property(env, descriptor, "configurable", configurable)); napi_value enumerable{}; - CHECK_NAPI(napi_get_boolean(env, (p->attributes & napi_configurable), &enumerable)); + CHECK_NAPI(napi_get_boolean(env, (p->attributes & napi_enumerable), &enumerable)); CHECK_NAPI(napi_set_named_property(env, descriptor, "enumerable", enumerable)); if (p->getter != nullptr || p->setter != nullptr) { @@ -1367,10 +1353,17 @@ napi_status napi_create_symbol(napi_env env, CHECK_ENV(env); CHECK_ARG(env, result); - napi_value global{}, symbol_func{}; - CHECK_NAPI(napi_get_global(env, &global)); - CHECK_NAPI(napi_get_named_property(env, global, "Symbol", &symbol_func)); - CHECK_NAPI(napi_call_function(env, global, symbol_func, 1, &description, result)); + // Create the symbol directly instead of round-tripping through the JS + // `Symbol()` constructor. A null description yields `Symbol()`. + if (description == nullptr || + JSValueIsUndefined(env->context, ToJSValue(description))) { + *result = ToNapi(JSValueMakeSymbol(env->context, nullptr)); + } else { + JSValueRef exception{}; + JSString descriptionString{ToJSString(env, description, &exception)}; + CHECK_JSC(env, exception); + *result = ToNapi(JSValueMakeSymbol(env->context, descriptionString)); + } return napi_ok; } @@ -1429,12 +1422,29 @@ napi_status napi_create_range_error(napi_env env, return napi_ok; } +napi_status napi_create_syntax_error(napi_env env, + napi_value code, + napi_value msg, + napi_value* result) { + CHECK_ENV(env); + CHECK_ARG(env, msg); + CHECK_ARG(env, result); + + napi_value global{}, error_ctor{}, error{}; + CHECK_NAPI(napi_get_global(env, &global)); + CHECK_NAPI(napi_get_named_property(env, global, "SyntaxError", &error_ctor)); + CHECK_NAPI(napi_new_instance(env, error_ctor, 1, &msg, &error)); + CHECK_NAPI(napi_set_error_code(env, error, code, nullptr)); + + *result = error; + return napi_ok; +} + napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype* result) { CHECK_ENV(env); CHECK_ARG(env, value); CHECK_ARG(env, result); - // JSC does not support BigInt JSType valueType = JSValueGetType(env->context, ToJSValue(value)); switch (valueType) { case kJSTypeUndefined: *result = napi_undefined; break; @@ -1443,6 +1453,7 @@ napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype* result) case kJSTypeNumber: *result = napi_number; break; case kJSTypeString: *result = napi_string; break; case kJSTypeSymbol: *result = napi_symbol; break; + case kJSTypeBigInt: *result = napi_bigint; break; default: JSObjectRef object{ToJSObject(env, value)}; if (JSObjectIsFunction(env->context, object)) { @@ -1635,14 +1646,10 @@ napi_status napi_get_value_int32(napi_env env, napi_value value, int32_t* result CHECK_ARG(env, result); JSValueRef exception{}; - double number = JSValueToNumber(env->context, ToJSValue(value), &exception); - - if (number > INT_MAX) { - *result = -1; - } else { - *result = static_cast(number); - } - + // JSValueToInt32 applies the ECMAScript ToInt32 conversion (modulo 2^32, + // NaN/Infinity -> 0), matching Node's napi_get_value_int32 semantics, and + // truncates BigInt values. + *result = JSValueToInt32(env->context, ToJSValue(value), &exception); CHECK_JSC(env, exception); return napi_ok; @@ -1654,14 +1661,9 @@ napi_status napi_get_value_uint32(napi_env env, napi_value value, uint32_t* resu CHECK_ARG(env, result); JSValueRef exception{}; - *result = static_cast(JSValueToNumber(env->context, ToJSValue(value), &exception)); - - double number = JSValueToNumber(env->context, ToJSValue(value), &exception); - if (number > UINT32_MAX) { - *result = -1; - } else { - *result = static_cast(number); - } + // JSValueToUInt32 applies the ECMAScript ToUint32 conversion (modulo 2^32, + // NaN/Infinity -> 0), matching Node's napi_get_value_uint32 semantics. + *result = JSValueToUInt32(env->context, ToJSValue(value), &exception); CHECK_JSC(env, exception); return napi_ok; @@ -1693,6 +1695,84 @@ napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result) { return napi_ok; } +// BigInt support relies on JSC APIs available in newer JavaScriptCore +// (macOS 15 / iOS 18 and the corresponding Android build). +napi_status napi_create_bigint_int64(napi_env env, + int64_t value, + napi_value* result) { + CHECK_ENV(env); + CHECK_ARG(env, result); + + JSValueRef exception{}; + JSValueRef bigint{JSBigIntCreateWithInt64(env->context, value, &exception)}; + CHECK_JSC(env, exception); + + *result = ToNapi(bigint); + return napi_ok; +} + +napi_status napi_create_bigint_uint64(napi_env env, + uint64_t value, + napi_value* result) { + CHECK_ENV(env); + CHECK_ARG(env, result); + + JSValueRef exception{}; + JSValueRef bigint{JSBigIntCreateWithUInt64(env->context, value, &exception)}; + CHECK_JSC(env, exception); + + *result = ToNapi(bigint); + return napi_ok; +} + +napi_status napi_get_value_bigint_int64(napi_env env, + napi_value value, + int64_t* result, + bool* lossless) { + CHECK_ENV(env); + CHECK_ARG(env, value); + CHECK_ARG(env, result); + CHECK_ARG(env, lossless); + + RETURN_STATUS_IF_FALSE( + env, JSValueIsBigInt(env->context, ToJSValue(value)), napi_bigint_expected); + + JSValueRef exception{}; + *result = JSValueToInt64(env->context, ToJSValue(value), &exception); + CHECK_JSC(env, exception); + + // The conversion is lossless when the (truncated) int64 compares equal to + // the original BigInt. + *lossless = JSValueCompareInt64(env->context, ToJSValue(value), *result, &exception) == + kJSRelationConditionEqual; + CHECK_JSC(env, exception); + + return napi_ok; +} + +napi_status napi_get_value_bigint_uint64(napi_env env, + napi_value value, + uint64_t* result, + bool* lossless) { + CHECK_ENV(env); + CHECK_ARG(env, value); + CHECK_ARG(env, result); + CHECK_ARG(env, lossless); + + RETURN_STATUS_IF_FALSE( + env, JSValueIsBigInt(env->context, ToJSValue(value)), napi_bigint_expected); + + JSValueRef exception{}; + *result = JSValueToUInt64(env->context, ToJSValue(value), &exception); + CHECK_JSC(env, exception); + + *lossless = JSValueCompareUInt64(env->context, ToJSValue(value), *result, &exception) == + kJSRelationConditionEqual; + CHECK_JSC(env, exception); + + return napi_ok; +} + // Copies a JavaScript string into a LATIN-1 string buffer. The result is the // number of bytes (excluding the null terminator) copied into buf. // A sufficient buffer size should be greater than the length of string, @@ -2405,6 +2485,13 @@ napi_status napi_get_version(napi_env env, uint32_t* result) { return napi_ok; } +// Holds the resolve/reject functions of a deferred promise. Both are protected +// from GC for the lifetime of the deferred and released when it is settled. +struct napi_deferred__ { + JSObjectRef resolve; + JSObjectRef reject; +}; + napi_status napi_create_promise(napi_env env, napi_deferred* deferred, napi_value* promise) { @@ -2412,70 +2499,62 @@ napi_status napi_create_promise(napi_env env, CHECK_ARG(env, deferred); CHECK_ARG(env, promise); - napi_value global{}, promise_ctor{}; - CHECK_NAPI(napi_get_global(env, &global)); - CHECK_NAPI(napi_get_named_property(env, global, "Promise", &promise_ctor)); + // Create the promise and its resolve/reject functions directly through the + // JSC C API instead of round-tripping through the JS `Promise` constructor + // with a native executor callback. + JSObjectRef resolve{}, reject{}; + JSValueRef exception{}; + JSObjectRef promiseObject{ + JSObjectMakeDeferredPromise(env->context, &resolve, &reject, &exception)}; + CHECK_JSC(env, exception); - struct Wrapper { - napi_value resolve{}; - napi_value reject{}; + napi_deferred__* holder{new napi_deferred__{resolve, reject}}; + if (holder == nullptr) { + return napi_set_last_error(env, napi_generic_failure); + } + JSValueProtect(env->context, resolve); + JSValueProtect(env->context, reject); - static napi_value Callback(napi_env env, napi_callback_info cbinfo) { - Wrapper* wrapper = reinterpret_cast(cbinfo->data); - wrapper->resolve = cbinfo->argv[0]; - wrapper->reject = cbinfo->argv[1]; - return nullptr; - } - } wrapper; + *deferred = reinterpret_cast(holder); + *promise = ToNapi(promiseObject); - napi_value executor{}; - CHECK_NAPI(napi_create_function(env, "executor", NAPI_AUTO_LENGTH, Wrapper::Callback, &wrapper, &executor)); - CHECK_NAPI(napi_new_instance(env, promise_ctor, 1, &executor, promise)); + return napi_ok; +} + +// Shared body for resolve/reject: invokes the stored settle function with the +// given value, then releases and frees the deferred. +static napi_status napi_settle_deferred(napi_env env, + napi_deferred deferred, + napi_value value, + bool resolve) { + CHECK_ENV(env); + CHECK_ARG(env, deferred); + + napi_deferred__* holder{reinterpret_cast(deferred)}; + JSObjectRef settle{resolve ? holder->resolve : holder->reject}; - napi_value deferred_value{}; - CHECK_NAPI(napi_create_object(env, &deferred_value)); - CHECK_NAPI(napi_set_named_property(env, deferred_value, "resolve", wrapper.resolve)); - CHECK_NAPI(napi_set_named_property(env, deferred_value, "reject", wrapper.reject)); + JSValueRef exception{}; + JSValueRef argument{ToJSValue(value)}; + JSObjectCallAsFunction(env->context, settle, nullptr, 1, &argument, &exception); - napi_ref deferred_ref{}; - CHECK_NAPI(napi_create_reference(env, deferred_value, 1, &deferred_ref)); - *deferred = reinterpret_cast(deferred_ref); + JSValueUnprotect(env->context, holder->resolve); + JSValueUnprotect(env->context, holder->reject); + delete holder; + CHECK_JSC(env, exception); return napi_ok; } napi_status napi_resolve_deferred(napi_env env, napi_deferred deferred, napi_value resolution) { - CHECK_ENV(env); - CHECK_ARG(env, deferred); - - napi_ref deferred_ref{reinterpret_cast(deferred)}; - napi_value undefined{}, deferred_value{}, resolve{}; - CHECK_NAPI(napi_get_undefined(env, &undefined)); - CHECK_NAPI(napi_get_reference_value(env, deferred_ref, &deferred_value)); - CHECK_NAPI(napi_get_named_property(env, deferred_value, "resolve", &resolve)); - CHECK_NAPI(napi_call_function(env, undefined, resolve, 1, &resolution, nullptr)); - CHECK_NAPI(napi_delete_reference(env, deferred_ref)); - - return napi_ok; + return napi_settle_deferred(env, deferred, resolution, /*resolve*/ true); } napi_status napi_reject_deferred(napi_env env, napi_deferred deferred, napi_value rejection) { - CHECK_ENV(env); - CHECK_ARG(env, deferred); - - napi_ref deferred_ref{reinterpret_cast(deferred)}; - napi_value undefined{}, deferred_value{}, reject{}; - CHECK_NAPI(napi_get_undefined(env, &undefined)); - CHECK_NAPI(napi_get_reference_value(env, deferred_ref, &deferred_value)); - CHECK_NAPI(napi_get_named_property(env, deferred_value, "reject", &reject)); - CHECK_NAPI(napi_call_function(env, undefined, reject, 1, &rejection, nullptr)); - CHECK_NAPI(napi_delete_reference(env, deferred_ref)); - - return napi_ok; + return napi_settle_deferred(env, deferred, rejection, /*resolve*/ false); } napi_status napi_is_promise(napi_env env, @@ -2699,4 +2778,278 @@ napi_status napi_object_seal(napi_env env, CHECK_NAPI(napi_get_named_property(env, object_ctor, "seal", &seal)); CHECK_NAPI(napi_call_function(env, object_ctor, seal, 1, &object, nullptr)); return napi_ok; -} \ No newline at end of file +} + +#ifdef USE_HOST_OBJECT + +namespace { +static std::once_flag hostObjectClassOnceFlag; +static JSClassRef hostObjectClass{}; + +// JSC has no dedicated indexed-property callbacks: every property operation +// arrives as a JSStringRef. To honour the `napi_host_object_methods` contract +// (a number for indexed access, a string otherwise) we detect canonical array +// indices ourselves and route them to the `indexed_*` fast paths when present, +// matching the V8 implementation's behaviour. +bool HostObjectToIndex(JSStringRef str, uint32_t* out) { + size_t length{JSStringGetLength(str)}; + if (length == 0) { + return false; + } + const JSChar* chars{JSStringGetCharactersPtr(str)}; + if (length > 1 && chars[0] == '0') { + return false; // reject leading zeros ("01" is not a canonical index) + } + uint64_t value{0}; + for (size_t i = 0; i < length; ++i) { + JSChar ch{chars[i]}; + if (ch < '0' || ch > '9') { + return false; + } + value = value * 10 + (ch - '0'); + if (value > 0xFFFFFFFEull) { // max valid array index is 2^32 - 2 + return false; + } + } + *out = static_cast(value); + return true; +} +} + +// A "host object" is a transparent proxy: every property operation is +// dispatched to the native callbacks in `_methods`, which receive the host +// object itself and the `_data` pointer. The callbacks are wired through a +// single shared JSClass so a host object can be recognized by its class. +struct HostObjectInfo { + napi_env _env; + napi_finalize _finalize; + void* _data; + napi_host_object_methods _methods; + + static JSClassRef Class() { + std::call_once(hostObjectClassOnceFlag, []() { + JSClassDefinition definition{kJSClassDefinitionEmpty}; + definition.className = "NapiHostObject"; + definition.getProperty = GetProperty; + definition.setProperty = SetProperty; + definition.hasProperty = HasProperty; + definition.deleteProperty = DeleteProperty; + definition.getPropertyNames = GetPropertyNames; + definition.finalize = Finalize; + hostObjectClass = JSClassCreate(&definition); + }); + return hostObjectClass; + } + + static HostObjectInfo* From(JSObjectRef object) { + return reinterpret_cast(JSObjectGetPrivate(object)); + } + + // Propagate any exception raised by a napi callback back to JSC. + static bool ForwardException(napi_env env, JSValueRef* exception) { + if (env->last_exception != nullptr) { + if (exception != nullptr) { + *exception = env->last_exception; + } + env->last_exception = nullptr; + return true; + } + return false; + } + + // JSObjectGetPropertyCallback + static JSValueRef GetProperty(JSContextRef ctx, + JSObjectRef object, + JSStringRef propertyName, + JSValueRef* exception) { + HostObjectInfo* info{From(object)}; + if (info == nullptr) { + return nullptr; + } + napi_env env{info->_env}; + napi_clear_last_error(env); + + napi_value host{ToNapi(object)}; + napi_value result{nullptr}; + uint32_t index{}; + if (HostObjectToIndex(propertyName, &index) && + info->_methods.indexed_get != nullptr) { + result = info->_methods.indexed_get(env, host, index, info->_data); + } else { + napi_value prop{ToNapi(JSValueMakeString(ctx, propertyName))}; + result = info->_methods.get(env, host, prop, info->_data); + } + + if (ForwardException(env, exception)) { + return nullptr; + } + return result != nullptr ? ToJSValue(result) : JSValueMakeUndefined(ctx); + } + + // JSObjectSetPropertyCallback + static bool SetProperty(JSContextRef ctx, + JSObjectRef object, + JSStringRef propertyName, + JSValueRef value, + JSValueRef* exception) { + HostObjectInfo* info{From(object)}; + if (info == nullptr) { + return false; + } + napi_env env{info->_env}; + napi_clear_last_error(env); + + napi_value host{ToNapi(object)}; + napi_value val{ToNapi(value)}; + uint32_t index{}; + if (HostObjectToIndex(propertyName, &index) && + info->_methods.indexed_set != nullptr) { + info->_methods.indexed_set(env, host, index, val, info->_data); + } else { + napi_value prop{ToNapi(JSValueMakeString(ctx, propertyName))}; + info->_methods.set(env, host, prop, val, info->_data); + } + + ForwardException(env, exception); + return true; // fully handled + } + + // JSObjectHasPropertyCallback (no exception out-param available) + static bool HasProperty(JSContextRef ctx, + JSObjectRef object, + JSStringRef propertyName) { + HostObjectInfo* info{From(object)}; + if (info == nullptr || info->_methods.has == nullptr) { + return false; + } + napi_env env{info->_env}; + napi_clear_last_error(env); + + napi_value host{ToNapi(object)}; + napi_value prop{ToNapi(JSValueMakeString(ctx, propertyName))}; + bool present{info->_methods.has(env, host, prop, info->_data) != 0}; + env->last_exception = nullptr; + return present; + } + + // JSObjectDeletePropertyCallback + static bool DeleteProperty(JSContextRef ctx, + JSObjectRef object, + JSStringRef propertyName, + JSValueRef* exception) { + HostObjectInfo* info{From(object)}; + if (info == nullptr || info->_methods.delete_property == nullptr) { + return false; + } + napi_env env{info->_env}; + napi_clear_last_error(env); + + napi_value host{ToNapi(object)}; + napi_value prop{ToNapi(JSValueMakeString(ctx, propertyName))}; + bool deleted{info->_methods.delete_property(env, host, prop, info->_data) != 0}; + + ForwardException(env, exception); + return deleted; + } + + // JSObjectGetPropertyNamesCallback + static void GetPropertyNames(JSContextRef ctx, + JSObjectRef object, + JSPropertyNameAccumulatorRef propertyNames) { + HostObjectInfo* info{From(object)}; + if (info == nullptr || info->_methods.own_keys == nullptr) { + return; + } + napi_env env{info->_env}; + napi_clear_last_error(env); + + napi_value host{ToNapi(object)}; + napi_value keys{info->_methods.own_keys(env, host, info->_data)}; + env->last_exception = nullptr; + if (keys == nullptr) { + return; + } + + uint32_t length{}; + if (napi_get_array_length(env, keys, &length) != napi_ok) { + return; + } + for (uint32_t i = 0; i < length; ++i) { + napi_value element{}; + if (napi_get_element(env, keys, i, &element) != napi_ok) { + continue; + } + JSValueRef exception{}; + JSStringRef name{JSValueToStringCopy(ctx, ToJSValue(element), &exception)}; + if (name != nullptr) { + JSPropertyNameAccumulatorAddName(propertyNames, name); + JSStringRelease(name); + } + } + } + + // JSObjectFinalizeCallback + static void Finalize(JSObjectRef object) { + HostObjectInfo* info{From(object)}; + if (info == nullptr) { + return; + } + if (info->_finalize != nullptr) { + info->_finalize(info->_env, info->_data, nullptr); + } + delete info; + } +}; + +napi_status napi_create_host_object(napi_env env, + napi_finalize finalize, + void* data, + const napi_host_object_methods* methods, + napi_value* result) { + CHECK_ENV(env); + CHECK_ARG(env, methods); + CHECK_ARG(env, result); + RETURN_STATUS_IF_FALSE( + env, methods->get != nullptr && methods->set != nullptr, napi_invalid_arg); + + HostObjectInfo* info{new HostObjectInfo{env, finalize, data, *methods}}; + if (info == nullptr) { + return napi_set_last_error(env, napi_generic_failure); + } + + JSObjectRef object{JSObjectMake(env->context, HostObjectInfo::Class(), info)}; + *result = ToNapi(object); + return napi_ok; +} + +napi_status napi_get_host_object_data(napi_env env, + napi_value object, + void** data) { + CHECK_ENV(env); + CHECK_ARG(env, object); + CHECK_ARG(env, data); + + *data = nullptr; + JSValueRef value{ToJSValue(object)}; + if (JSValueIsObjectOfClass(env->context, value, HostObjectInfo::Class())) { + HostObjectInfo* info{HostObjectInfo::From(ToJSObject(env, object))}; + if (info != nullptr) { + *data = info->_data; + } + } + return napi_ok; +} + +napi_status napi_is_host_object(napi_env env, + napi_value object, + bool* result) { + CHECK_ENV(env); + CHECK_ARG(env, object); + CHECK_ARG(env, result); + + *result = JSValueIsObjectOfClass( + env->context, ToJSValue(object), HostObjectInfo::Class()); + return napi_ok; +} + +#endif // USE_HOST_OBJECT \ No newline at end of file diff --git a/test-app/runtime/src/main/cpp/napi/jsc/jsc-api.h b/test-app/runtime/src/main/cpp/napi/jsc/jsc-api.h index d22aa153..782331da 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/jsc-api.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/jsc-api.h @@ -7,7 +7,7 @@ #include "js_native_api.h" #include "js_native_api_types.h" -#include +#include "JavaScriptCore/JavaScript.h" #include #include #include @@ -17,7 +17,8 @@ struct napi_env__ { JSGlobalContextRef context{}; JSValueRef last_exception{}; napi_extended_error_info last_error{nullptr, nullptr, 0, napi_ok}; - std::unordered_set active_ref_values{}; + // Strong (protected) napi references, released on env teardown. Weak + // references are backed by native JSC weak handles inside napi_ref__. std::list strong_refs{}; JSValueRef constructor_info_symbol{}; diff --git a/test-app/runtime/src/main/cpp/napi/jsc/jsr.cpp b/test-app/runtime/src/main/cpp/napi/jsc/jsr.cpp index d5b66d58..170d766e 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/jsr.cpp +++ b/test-app/runtime/src/main/cpp/napi/jsc/jsr.cpp @@ -1,12 +1,12 @@ #include "jsr.h" -napi_status js_create_runtime(napi_runtime *runtime) { +napi_status js_create_runtime(jsr_ns_runtime *runtime) { if (!runtime) return napi_invalid_arg; - *runtime = (napi_runtime) JSGlobalContextCreateInGroup(nullptr, nullptr); + *runtime = (jsr_ns_runtime) JSGlobalContextCreateInGroup(nullptr, nullptr); return napi_ok; } -napi_status js_create_napi_env(napi_env* env, napi_runtime runtime) { +napi_status js_create_napi_env(napi_env* env, jsr_ns_runtime runtime) { if (env == nullptr) return napi_invalid_arg; *env = new napi_env__((JSGlobalContextRef) runtime); @@ -46,7 +46,7 @@ napi_status js_free_napi_env(napi_env env) { return napi_ok; } -napi_status js_free_runtime(napi_runtime runtime) { +napi_status js_free_runtime(jsr_ns_runtime runtime) { // JSContextGroupRelease((JSContextGroupRef) runtime); return napi_ok; } diff --git a/test-app/runtime/src/main/cpp/napi/jsc/jsr.h b/test-app/runtime/src/main/cpp/napi/jsc/jsr.h index 3bbc5313..66ba9ab5 100644 --- a/test-app/runtime/src/main/cpp/napi/jsc/jsr.h +++ b/test-app/runtime/src/main/cpp/napi/jsc/jsr.h @@ -8,8 +8,6 @@ #include "jsr_common.h" #include "jsc-api.h" -typedef struct napi_runtime__ *napi_runtime; - class NapiScope { public: explicit NapiScope(napi_env env, bool openHandle = true) diff --git a/test-app/runtime/src/main/cpp/napi/primjs/code_cache.cc b/test-app/runtime/src/main/cpp/napi/primjs/code_cache.cc deleted file mode 100644 index 1194bda0..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/code_cache.cc +++ /dev/null @@ -1,261 +0,0 @@ -/** - * Copyright (c) 2017 Node.js API collaborators. All Rights Reserved. - * - * Use of this source code is governed by a MIT license that can be - * found in the LICENSE file in the root of the source tree. - */ - -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -#include "code_cache.h" - -#include - -#include -#include - -#if OS_ANDROID -#include "basic/log/logging.h" -#else -#define VLOGD(...) void((__VA_ARGS__)) -#endif // OS_ANDROID - -#ifdef PROFILE_CODECACHE -#define INCREASE(target) ++(target) -#else -#define INCREASE(target) -#endif // PROFILE_CODECACHE - -constexpr double CacheBlob::MAGIC; - -bool CacheBlob::insert(const std::string& filename, const uint8_t* data, - int length) { - // too large (more than half of MAX) cached data must be discarded - if (length == 0 || data == nullptr) { - INCREASE(expired_query_); - return false; - } - CachedData* target = nullptr; - const uint8_t* old_data = nullptr; - { - std::unique_lock lock(write_mutex_); - auto it = cache_map_.find(filename); - if (it != cache_map_.end()) { - target = it->second; - current_size_ -= target->length_; - remove_from_ranking_list(target); - - if (get_enough_space(length)) { - if (mode_ == kAppending) mode_ = kWriting; - target->length_ = length; - } else { - cache_map_.erase(it); - return false; - } - - } else if (get_enough_space(length)) { - target = new CachedData(length, nullptr, filename); - cache_map_[filename] = target; - if (mode_ == kAppending) { - if (append_vec_ == nullptr) { - append_vec_ = new CacheVector(); - } - append_vec_->push_back(target); - } - } else { - return false; - } - - old_data = target->data_; - target->data_ = data; - } - - heat_ranking_.push_back(target); - current_size_ += length; - if (old_data) { - delete[] old_data; - } - INCREASE(target->used_times_); - - return true; -} - -// That len will be not nullptr is ensured by the context. -const CachedData* CacheBlob::find(const std::string& filename, int* len) const { - if (!write_mutex_.try_lock()) { - INCREASE(missed_query_); - INCREASE(total_query_); - return empty_cache_.get(); - } - auto it = cache_map_.find(filename); - write_mutex_.unlock(); - CachedData* result = nullptr; - if (it != cache_map_.end()) { - // every time a cache is searched, its heat-ranking - // rises and thus the ranking list changes - result = it->second; - *len = result->length_; - INCREASE(result->used_times_); - } else { - *len = 0; - INCREASE(missed_query_); - } - INCREASE(total_query_); - - // NOTE: - // The result cached data is safe beyond this scope, - // because JS engines got this data and then use it - // consecutively in one thread. Tasks that insert new - // data for the same filename will only be posted after - // that cached data has been already used up. - return result; -} - -void CacheBlob::remove(const std::string& filename) { - auto it = cache_map_.find(filename); - if (it != cache_map_.end()) { - current_size_ -= it->second->length_; - delete it->second; - cache_map_.erase(it); - if (mode_ == kAppending) mode_ = kWriting; - } -} - -// cache file structure: -// Header: -// | magic number | --> 8 bytes -// Body : -// | file name size | --> 2 bytes -// | file name | --> x bytes -// | cache data length | --> 4 bytes -// | cache data | --> y bytes -// ... -void CacheBlob::output() { - if (mode_ == kAppending && append_vec_ == nullptr) return; - bool appending = mode_ == kAppending && append_vec_ != nullptr; - - FILE* file_out = appending ? fopen(target_path_.c_str(), "ab") - : fopen(target_path_.c_str(), "wb"); - if (file_out) { - if (appending) { - for (auto it : *append_vec_) write_cache_unit(file_out, it); - } else { - fwrite(&MAGIC, DOUBLE_SIZE, 1, file_out); - for (auto& it : cache_map_) write_cache_unit(file_out, it.second); - } - fclose(file_out); - VLOGD("codecache: output cache file %s succeed.\n", target_path_.c_str()); - } -} - -// steps to rebuild blob: -// 1. read and check magic number; -// 2. read 2 bytes to get the size (x) of file name; -// 3. read x bytes to get the file name; -// 4. read 4 bytes to get the size (y) of cache data; -// 5. read y bytes to get the actual content of cache data; -// 6. go back to step 2 until EOF -bool CacheBlob::input() { - FILE* file_in = fopen(target_path_.c_str(), "rb"); - - bool succeeded = false; - if (file_in) { - double maybe_magic; - fread(reinterpret_cast(&maybe_magic), DOUBLE_SIZE, 1, file_in); - // check whether file is valid. - if (maybe_magic == MAGIC) { - int c; - while ((c = fgetc(file_in)) != EOF) { - ungetc(c, file_in); - read_cache_unit(file_in); - } - mode_ = kAppending; - succeeded = true; - } - fclose(file_in); - } - return succeeded; -} - -#ifdef PROFILE_CODECACHE -void CacheBlob::dump_status(void* p) { - std::vector >* status_vec = - reinterpret_cast >*>(p); - std::sort(heat_ranking_.begin(), heat_ranking_.end(), CachedData::compare); - status_vec->push_back(std::pair("Total", total_query_)); - status_vec->push_back(std::pair("Missed", missed_query_)); - status_vec->push_back(std::pair("Expired", expired_query_)); - status_vec->push_back(std::pair( - "Updated", mode_ == kAppending && append_vec_ == nullptr ? 0 : 1)); - status_vec->push_back(std::pair("Size", current_size_)); - status_vec->push_back(std::pair("Heat Ranking, total ", - heat_ranking_.size())); - for (size_t i = 0; i < heat_ranking_.size(); ++i) { - CachedData* dt = heat_ranking_[i]; - status_vec->push_back( - std::pair(dt->file_name_, dt->used_times_)); - } -} -#endif // PROFILE_CODECACHE - -void CacheBlob::write_cache_unit(FILE* file_out, const CachedData* unit) { - // write file name - uint16_t size = static_cast(unit->file_name_.size()); - fwrite(static_cast(&size), SHORT_SIZE, 1, file_out); - fwrite(unit->file_name_.c_str(), 1, unit->file_name_.size(), file_out); - - uint32_t length = unit->length_; - fwrite(static_cast(&length), INT_SIZE, 1, file_out); - fwrite(unit->data_, 1, unit->length_, file_out); -} - -void CacheBlob::read_cache_unit(FILE* file_in) { - uint16_t filename_length; - fread(&filename_length, SHORT_SIZE, 1, file_in); - std::string name(filename_length, '\0'); - fread(&name[0], 1, filename_length, file_in); - - uint32_t data_length; - fread(&data_length, INT_SIZE, 1, file_in); - uint8_t* data = new uint8_t[data_length]; - fread(data, 1, data_length, file_in); - - CachedData* cd = new CachedData(static_cast(data_length), data, name); - - current_size_ += data_length; - heat_ranking_.push_back(cd); - cache_map_[name] = cd; -} - -void CacheBlob::remove_from_ranking_list(CachedData* target) { - for (size_t i = 0; i < heat_ranking_.size(); ++i) { - if (target == heat_ranking_[i]) { - heat_ranking_.erase(heat_ranking_.begin() + i); - break; - } - } -} - -// This is a vast-time-costing function -bool CacheBlob::get_enough_space(int data_size) { - // 0. check whether available space is enough - if (current_size_ + data_size <= max_capacity_) return true; - int size_needed = data_size + current_size_ - max_capacity_; - // 1. sort the heat_ranking_ - std::sort(heat_ranking_.begin(), heat_ranking_.end(), CachedData::compare); - // 2. pick CachedDatas - for (int i = heat_ranking_.size() - 1; i >= 0; --i) { - size_needed -= heat_ranking_[i]->length_; - if (size_needed <= 0) { - for (size_t j = i; j < heat_ranking_.size(); ++j) { - CachedData* it = heat_ranking_[j]; - remove(it->file_name_); - } - heat_ranking_.erase(heat_ranking_.begin() + i, heat_ranking_.end()); - return true; - } - } - return false; -} diff --git a/test-app/runtime/src/main/cpp/napi/primjs/code_cache.h b/test-app/runtime/src/main/cpp/napi/primjs/code_cache.h deleted file mode 100644 index f10a44ee..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/code_cache.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright (c) 2017 Node.js API collaborators. All Rights Reserved. - * - * Use of this source code is governed by a MIT license that can be - * found in the LICENSE file in the root of the source tree. - */ - -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -#ifndef SRC_NAPI_COMMON_CODE_CACHE_H_ -#define SRC_NAPI_COMMON_CODE_CACHE_H_ - -#include -#include -#include -#include -#include - -struct CachedData { - CachedData() : length_(0), data_(nullptr), file_name_("") {} - - CachedData(int length, const uint8_t* data, const std::string& name) - : length_(length), data_(data), file_name_(name) {} - - // carefully copy and move objects of this class - ~CachedData() { - if (data_) delete[] data_; - } - - static bool compare(CachedData* left, CachedData* right) { - if (left->used_times_ > right->used_times_) { - return true; - } else if (left->used_times_ < right->used_times_) { - return false; - } else { - return left->length_ > right->length_; - } - } - - int used_times_ = 0; - int length_; - const uint8_t* data_; - const std::string file_name_; -}; - -typedef std::unordered_map CacheMap; -typedef std::vector CacheVector; -#define SHORT_SIZE 2 -#define INT_SIZE 4 -#define DOUBLE_SIZE 8 - -class CacheBlob { - private: - enum CacheMode { kWriting, kAppending }; - static constexpr double MAGIC = 3.14159265; - - public: - explicit CacheBlob(const std::string& path, int max_cap = 1 << 20) - : current_size_(0), - target_path_(path), - max_capacity_(max_cap), - empty_cache_(new CachedData) {} - - virtual ~CacheBlob() { - for (auto it : cache_map_) delete it.second; - if (append_vec_) delete append_vec_; - } - - // NOTE: modifications on CacheBlob can only happen in worker Thread. - bool insert(const std::string& filename, const uint8_t* data, int length); - const CachedData* find(const std::string& filename, int* len) const; - void remove(const std::string& filename); - void output(); - bool input(); - int size() const { return current_size_; } - -#ifdef PROFILE_CODECACHE - void dump_status(void* p); -#endif // PROFILE_CODECACHE - - private: - void write_cache_unit(FILE* file_out, const CachedData* unit); - void read_cache_unit(FILE* file_in); - void remove_from_ranking_list(CachedData* target); - // This is a vast-time-costing function - bool get_enough_space(int data_size); - - CacheMap cache_map_; - // ranking list for caches' frequency of being used. - CacheVector heat_ranking_; - int current_size_; - const std::string target_path_; - int max_capacity_; - mutable std::mutex write_mutex_; - std::unique_ptr empty_cache_; - -#ifdef PROFILE_CODECACHE - mutable int total_query_ = 0; - mutable int missed_query_ = 0; - mutable int expired_query_ = 0; -#endif // PROFILE_CODECACHE - CacheMode mode_ = kWriting; - CacheVector* append_vec_ = nullptr; -}; - -#endif // SRC_NAPI_COMMON_CODE_CACHE_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/allocator.h b/test-app/runtime/src/main/cpp/napi/primjs/include/allocator.h similarity index 98% rename from test-app/runtime/src/main/cpp/napi/primjs/include/gc/allocator.h rename to test-app/runtime/src/main/cpp/napi/primjs/include/allocator.h index bcf6f0d9..8ccbe123 100644 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/allocator.h +++ b/test-app/runtime/src/main/cpp/napi/primjs/include/allocator.h @@ -93,6 +93,9 @@ struct malloc_state { size_t footprint; size_t max_footprint; size_t footprint_limit; + size_t outer_heap_size; + size_t gc_info_threshold; + size_t gc_info_interval_size; flag_t mflags; #if USE_LOCKS MLOCK_T mutex; diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/base_export.h b/test-app/runtime/src/main/cpp/napi/primjs/include/base_export.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/base_export.h rename to test-app/runtime/src/main/cpp/napi/primjs/include/base_export.h diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/basic/log/logging.h b/test-app/runtime/src/main/cpp/napi/primjs/include/basic/log/logging.h deleted file mode 100644 index 2cb633ee..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/basic/log/logging.h +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -#ifndef SRC_BASIC_LOG_LOGGING_H_ -#define SRC_BASIC_LOG_LOGGING_H_ - -#include -#include -#include - -#include "quickjs/include/base_export.h" - -#if defined(OS_ANDROID) -#include - -#define VLOGW(...) __android_log_print(ANDROID_LOG_WARN, "PRIMJS", __VA_ARGS__) -#define VLOGE(...) __android_log_print(ANDROID_LOG_ERROR, "PRIMJS", __VA_ARGS__) -#define VLOGI(...) __android_log_print(ANDROID_LOG_INFO, "PRIMJS", __VA_ARGS__) -#define VLOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PRIMJS", __VA_ARGS__) -#else -#include - -#define VLOGW(format, ...) \ - fprintf(stderr, "[PRIMJS] " format "\n", ##__VA_ARGS__) -#define VLOGE(format, ...) \ - fprintf(stderr, "[PRIMJS] " format "\n", ##__VA_ARGS__) -#define VLOGI(format, ...) \ - fprintf(stderr, "[PRIMJS] " format "\n", ##__VA_ARGS__) -#define VLOGD(format, ...) \ - fprintf(stderr, "[PRIMJS] " format "\n", ##__VA_ARGS__) -#endif - -namespace primjs { -namespace general { -namespace logging { - -class LogMessage; -void Log(LogMessage *msg); - -QJS_HIDE void SetMinLogLevel(int level); - -QJS_EXPORT int GetMinAllLogLevel(); - -#define PRIMJS_LOG_LEVEL_VERBOSE -1 -#define PRIMJS_LOG_LEVEL_INFO 0 -#define PRIMJS_LOG_LEVEL_WARNING 1 -#define PRIMJS_LOG_LEVEL_ERROR 2 -#define PRIMJS_LOG_LEVEL_FATAL 3 -#define PRIMJS_LOG_LEVEL_NUM 4 - -typedef int LogSeverity; -const LogSeverity LOG_VERBOSE = PRIMJS_LOG_LEVEL_VERBOSE; -const LogSeverity LOG_INFO = PRIMJS_LOG_LEVEL_INFO; -const LogSeverity LOG_WARNING = PRIMJS_LOG_LEVEL_WARNING; -const LogSeverity LOG_ERROR = PRIMJS_LOG_LEVEL_ERROR; -const LogSeverity LOG_FATAL = PRIMJS_LOG_LEVEL_FATAL; -const LogSeverity LOG_NUM_SEVERITIES = PRIMJS_LOG_LEVEL_NUM; - -// This class is used to explicitly ignore values in the conditional -// logging macros. This avoids compiler warnings like "value computed -// is not used" and "statement has no effect". -class LogMessageVoidify { - public: - LogMessageVoidify() = default; - // This has to be an operator with a precedence lower than << but - // higher than ?: - void operator&(std::ostream &) {} -}; - -#define LOG_IS_ON(severity) \ - ((primjs::general::logging::LOG_##severity) >= \ - primjs::general::logging::GetMinAllLogLevel()) - -#define LOG_STREAM(severity) \ - primjs::general::logging::LogMessage( \ - __FILE__, __LINE__, primjs::general::logging::LOG_##severity) \ - .stream() - -#define LAZY_STREAM(stream, condition) \ - !(condition) ? (void)0 \ - : primjs::general::logging::LogMessageVoidify() & (stream) - -// Use this macro to suppress warning if the variable in log is not used. -#define UNUSED_LOG_VARIABLE __attribute__((unused)) - -#ifndef PRIMJS_MIN_LOG_LEVEL -#define PRIMJS_MIN_LOG_LEVEL PRIMJS_LOG_LEVEL_VERBOSE -#endif - -// TODO(zhixuan): Currently, the usage of log macros is like "LOGI("abc" << -// variable)", which is mixed of stream pattern and format string pattern. -// Change the loggin fashion entirely to format string pattern in future. -#if PRIMJS_MIN_LOG_LEVEL <= PRIMJS_LOG_LEVEL_VERBOSE -#define LOGV(msg) LAZY_STREAM(LOG_STREAM(VERBOSE), LOG_IS_ON(VERBOSE)) << msg -#define DLOGV(msg) LAZY_STREAM(LOG_STREAM(VERBOSE), LOG_IS_ON(VERBOSE)) << msg -#else -#define LOGV(msg) -#define DLOGV(msg) -#endif - -#if PRIMJS_MIN_LOG_LEVEL <= PRIMJS_LOG_LEVEL_INFO -#define LOGI(msg) LAZY_STREAM(LOG_STREAM(INFO), LOG_IS_ON(INFO)) << msg -#define DLOGI(msg) LAZY_STREAM(LOG_STREAM(INFO), LOG_IS_ON(INFO)) << msg -#else -#define LOGI(msg) -#define DLOGI(msg) -#endif - -#if PRIMJS_MIN_LOG_LEVEL <= PRIMJS_LOG_LEVEL_WARNING -#define LOGW(msg) LAZY_STREAM(LOG_STREAM(WARNING), LOG_IS_ON(WARNING)) << msg -#define DLOGW(msg) LAZY_STREAM(LOG_STREAM(WARNING), LOG_IS_ON(WARNING)) << msg -#else -#define LOGW(msg) -#define DLOGW(msg) -#endif - -#if PRIMJS_MIN_LOG_LEVEL <= PRIMJS_LOG_LEVEL_ERROR -#define LOGE(msg) LAZY_STREAM(LOG_STREAM(ERROR), LOG_IS_ON(ERROR)) << msg -#define DLOGE(msg) LAZY_STREAM(LOG_STREAM(ERROR), LOG_IS_ON(ERROR)) << msg -#else -#define LOGE(msg) -#define DLOGE(msg) -#endif - -#if PRIMJS_MIN_LOG_LEVEL <= PRIMJS_LOG_LEVEL_FATAL -#define LOGF(msg) LAZY_STREAM(LOG_STREAM(FATAL), LOG_IS_ON(FATAL)) << msg -#define DLOGF(msg) LAZY_STREAM(LOG_STREAM(FATAL), LOG_IS_ON(FATAL)) << msg -#else -#define LOGF(msg) -#define DLOGF(msg) -#endif - -#ifndef DCHECK -// for debug, if check failed, log fatal and abort -#if !defined(NDEBUG) -#define DCHECK(condition) \ - LAZY_STREAM(LOG_STREAM(FATAL), !(condition)) \ - << "Check failed: " #condition ". " -#else -// for release, do nothing -#define DCHECK(condition) !(condition) ? (void)0 : (void)0 -#endif -#endif - -#define NOTREACHED() LOGF("") - -class QJS_EXPORT LogMessage { - public: - LogMessage(const char *file, int line, LogSeverity severity); - ~LogMessage(); - std::ostringstream &stream(); - LogSeverity severity() { return severity_; } - - private: - void Init(const char *file, int line); - - LogSeverity severity_; - std::ostringstream stream_; - - const char *file_; - const int line_; - LogMessage(const LogMessage &) = delete; - LogMessage &operator=(const LogMessage &) = delete; -}; - -} // namespace logging -} // namespace general -} // namespace primjs - -#endif // SRC_BASIC_LOG_LOGGING_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/cutils.h b/test-app/runtime/src/main/cpp/napi/primjs/include/cutils.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/cutils.h rename to test-app/runtime/src/main/cpp/napi/primjs/include/cutils.h diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/base-global-handles.h b/test-app/runtime/src/main/cpp/napi/primjs/include/gc/base-global-handles.h deleted file mode 100644 index 348e8724..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/base-global-handles.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2009 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -#ifndef SRC_GC_BASE_GLOBAL_HANDLES_H_ -#define SRC_GC_BASE_GLOBAL_HANDLES_H_ - -#define ITERATOR(NODETYPE) \ - NodeIterator final { \ - public: \ - explicit NodeIterator(NodeBlock* block) : block_(block) {} \ - NodeIterator(NodeIterator&& other) \ - : block_(other.block_), index_(other.index_) {} \ - NodeIterator(const NodeIterator&) = delete; \ - NodeIterator& operator=(const NodeIterator&) = delete; \ - bool operator==(const NodeIterator& other) const { \ - return block_ == other.block_; \ - } \ - bool operator!=(const NodeIterator& other) const { \ - return block_ != other.block_; \ - } \ - NodeIterator& operator++() { \ - if (++index_ < kBlockSize) return *this; \ - index_ = 0; \ - block_ = block_->next_used(); \ - return *this; \ - } \ - NODETYPE* operator*() { return block_->at(index_); } \ - NODETYPE* operator->() { return block_->at(index_); } \ - \ - private: \ - NodeBlock* block_ = nullptr; \ - size_t index_ = 0; \ - }; - -#define NODEBLOCK(HANDLETYPE, NODETYPE) \ - NodeBlock final { \ - public: \ - inline static const NodeBlock* From(const NODETYPE* node); \ - inline static NodeBlock* From(NODETYPE* node); \ - NodeBlock(HANDLETYPE* global_handles, HANDLETYPE::NodeSpace* space, \ - NodeBlock* next) \ - : next_(next), global_handles_(global_handles), space_(space) {} \ - ~NodeBlock() = default; \ - NodeBlock(const NodeBlock&) = delete; \ - NodeBlock& operator=(const NodeBlock&) = delete; \ - NODETYPE* at(size_t index) { return &nodes_[index]; } \ - const NODETYPE* at(size_t index) const { return &nodes_[index]; } \ - HANDLETYPE::NodeSpace* space() const { return space_; } \ - HANDLETYPE* global_handles() const { return global_handles_; } \ - inline bool IncreaseUsage(); \ - inline bool DecreaseUsage(); \ - inline void ListAdd(NodeBlock** top); \ - inline void ListRemove(NodeBlock** top); \ - NodeBlock* next() const { return next_; } \ - NodeBlock* next_used() const { return next_used_; } \ - const void* begin_address() const { return nodes_; } \ - const void* end_address() const { return &nodes_[kBlockSize]; } \ - \ - private: \ - NODETYPE nodes_[kBlockSize]; \ - NodeBlock* const next_; \ - HANDLETYPE* const global_handles_; \ - HANDLETYPE::NodeSpace* const space_; \ - NodeBlock* next_used_ = nullptr; \ - NodeBlock* prev_used_ = nullptr; \ - uint32_t used_nodes_ = 0; \ - }; -#endif // SRC_GC_BASE_GLOBAL_HANDLES_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/collector.h b/test-app/runtime/src/main/cpp/napi/primjs/include/gc/collector.h deleted file mode 100644 index ada95c1a..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/collector.h +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -#ifndef SRC_GC_COLLECTOR_H_ -#define SRC_GC_COLLECTOR_H_ - -#include - -#include "gc/trace-gc.h" -#include "quickjs/include/quickjs-inner.h" - -enum HandleType; -class Visitor; -class Finalizer; -class Sweeper; -typedef struct JSString JSAtomStruct; -struct LEPUSRuntime; -typedef struct malloc_state *mstate; -struct JSAsyncFunctionState; -struct JSProperty; -struct JSRegExp; -struct BCReaderState; -struct JSToken; -struct ValueBuffer; -class GarbageCollector { - public: - GarbageCollector(LEPUSRuntime *rt, mstate) noexcept; - ~GarbageCollector(); - // gc - void CollectGarbage(size_t size = 0) noexcept; - void DoOnlyFinalizer() noexcept; - - void Init(LEPUSRuntime *rt); - Visitor *GetVisitor() { return visitor; } - Finalizer *GetFinalizer() { return finalizer; } - // gc pause suppression mode - void SetGCPauseSuppressionMode(bool mode) { - gc_pause_suppression_mode_ = mode; - } - bool GetGCPauseSuppressionMode() { return gc_pause_suppression_mode_; } - // forbid_gc - void SetForbidGC() { forbid_gc_++; } - void ResetForbidGC() { forbid_gc_--; } - - // for debug -#ifdef ENABLE_GC_DEBUG_TOOLS - size_t mem_order_cnt; - std::unordered_map cur_mems; - std::unordered_set delete_mems[THREAD_NUM]; - size_t delete_order_cnt; - std::unordered_map del_mems; - - size_t handle_order_cnt; - std::unordered_map cur_handles; - size_t qjsvalue_order_cnt; - std::unordered_map cur_qjsvalues; -#endif - - size_t GetHandleSize() { -#ifdef ENABLE_GC_DEBUG_TOOLS - return cur_handles.size(); -#else - return 0; -#endif - } - - size_t GetQjsValueSize() { -#ifdef ENABLE_GC_DEBUG_TOOLS - return cur_qjsvalues.size(); -#else - return 0; -#endif - } - - void SetMaxLimit(size_t limit); - size_t GetMaxLimit(); - void AddGCDuration(int64_t gc_time) { total_duration += gc_time; } - int64_t GetGCDuration() { return total_duration; } - int js_ref_count; - - private: - // gc - void MarkLiveObjects() noexcept; - void SweepDeadObjects() noexcept; -#ifdef ENABLE_TRACING_GC_LOG - void PrintGCLog(int64_t mark_begin, int64_t mark_end) noexcept; -#endif - void UpdateFootprintLimit(size_t size) noexcept; - void UpdateNGFootprintLimit(size_t size) noexcept; - void UpdateGCInfo(size_t heapsize_before, int64_t duration); - - // field - LEPUSRuntime *rt_; - int forbid_gc_; - bool gc_pause_suppression_mode_ = false; - Visitor *visitor; - Finalizer *finalizer; - Sweeper *sweeper; - size_t max_limit; -#ifdef ENABLE_TRACING_GC_LOG - int64_t gc_begin_time; - int64_t last_gc_time; -#endif - int64_t total_duration; - std::stringstream gc_info; - int info_size; -}; - -class Visitor { - public: - Visitor(LEPUSRuntime *rt) noexcept - : rt_(rt), objs(nullptr), objs_len(0), idx(0) { - for (int i = 0; i < THREAD_NUM; i++) { - queue[i] = new Queue(rt_); - } - } - ~Visitor() { - for (int i = 0; i < THREAD_NUM; i++) { - delete queue[i]; - } - if (objs != nullptr) { - system_free(objs); - } - } - void ScanRoots(); - void VisitRootLEPUSValue(LEPUSValue *val, int local_idx) noexcept; - void VisitRootLEPUSValue(LEPUSValue &val, int local_idx) noexcept; - void AddObjectDuringGC(void *ptr) { - if (objs == nullptr) { - objs = static_cast(system_malloc(16 * sizeof(void *))); - objs_len = 16; - } - if (idx >= objs_len) { - int new_len = objs_len * 2; - void **new_objs = - static_cast(system_realloc(objs, new_len * sizeof(void *))); - if (!new_objs) abort(); - objs = new_objs; - objs_len = new_len; - } - objs[idx] = ptr; - idx++; - } - void VisitObjectDuringGC() { - for (int i = 0; i < idx; i++) { - VisitRootHeapObj(objs[i], 0); - } - idx = 0; - } - - private: - // private scanner - void ScanStack() noexcept; - void ScanRuntime() noexcept; - void ScanHandles() noexcept; - void ScanContext(LEPUSContext *ctx) noexcept; - - // visit root - void VisitRoot(void *ptr, HandleType type, int local_idx) noexcept; - void VisitRootHeapObj(void *ptr, int local_idx) noexcept; - void VisitRootHeapObjForTask(Queue *q, void *ptr) noexcept; - void VisitRootCString(char *cstr, int local_idx) noexcept; - void VisitRootJSToken(JSToken *token, int local_idx) noexcept; - void VisitRootBCReaderState(BCReaderState *s, int local_idx) noexcept; - void VisitRootValueBuffer(ValueBuffer *b, int local_idx) noexcept; - void VisitJSAtom(JSAtom atom, int local_idx) noexcept; - - // visitor - /* LEPUSValue with tag -> begin */ - void VisitEntry(void *ptr, int local_idx) noexcept; - void VisitLEPUSLepusRef(void *ptr, int local_idx) noexcept; - void VisitJShape(void *ptr, int local_idx) noexcept; - void VisitJSVarRef(void *ptr, int local_idx) noexcept; - void VisitJSFunctionBytecode(void *ptr, int local_idx) noexcept; - void VisitJSObject(void *ptr, int local_idx) noexcept; - /* LEPUSValue with tag -> end */ - // LEPUS_TAG_BIG_INT - // LEPUS_TAG_BIG_FLOAT - /* LEPUSObject with class_id -> begin */ - void VisitJSBoundFunction(void *ptr, - int local_idx) noexcept; // normal_free - void VisitJSCFunctionDataRecord(void *ptr, - int local_idx) noexcept; // normal_free - void VisitJSForInIterator(void *ptr, - int local_idx) noexcept; // normal_free - void VisitJSArrayBuffer(void *ptr, int local_idx) noexcept; - void VisitJSTypedArray(void *ptr, int local_idx) noexcept; - void VisitJSMapState(void *ptr, int local_idx) noexcept; - void VisitJSMapIteratorData(void *ptr, int local_idx) noexcept; - void VisitJSArrayIteratorData(void *ptr, - int local_idx) noexcept; // normal_free - void VisitJSRegExpStringIteratorData(void *ptr, - int local_idx) noexcept; // normal_free - void VisitJSGeneratorData(void *ptr, int local_idx) noexcept; - void VisitJSProxyData(void *ptr, int local_idx) noexcept; // normal_free - void VisitJSPromiseData(void *ptr, int local_idx) noexcept; // normal_free - void VisitJSPromiseReactionData(void *ptr, - int local_idx) noexcept; // normal_free - void VisitJSPromiseFunctionData(void *ptr, - int local_idx) noexcept; // normal_free - void VisitJSAsyncFunctionData(void *ptr, int local_idx) noexcept; - void VisitJSAsyncFromSyncIteratorData(void *ptr, - int local_idx) noexcept; // normal_free - void VisitJSAsyncGeneratorData(void *ptr, int local_idx) noexcept; - /* LEPUSObject with class_id -> end */ - // scan context -#ifdef ENABLE_QUICKJS_DEBUGGER - void VisitJSScriptSource(void *ptr, int local_idx) noexcept; -#endif - // other - void VisitJSPropertyEnum(void *ptr, - int local_idx) noexcept; // normal_free - void VisitJSModuleDef(void *ptr, int local_idx) noexcept; - void VisitJSFunctionDef(void *ptr, int local_idx) noexcept; - void VisitJSValueArray(void *ptr, int local_idx) noexcept; - void VisitValueSlot(void *ptr, int local_idx) noexcept; - void VisitJsonStrArray(void *ptr, int local_idx) noexcept; - - void VisitSeparableString(void *ptr, int local_idx) noexcept; - void VisitDebuggerInfo(void *, int32_t) noexcept; - void VisitFinalizationRegistryData(void *ptr, int local_idx) noexcept; - - // push ptr - void PushObjLEPUSValue(LEPUSValue &val, int local_idx) noexcept; - void PushObjLEPUSValue(LEPUSValue *val, int local_idx) noexcept; - void PushObjAtom(JSAtom atom, int local_idx) noexcept; - void PushObjJSAsyncFunctionState(JSAsyncFunctionState *s, - int local_idx) noexcept; - void PushObjJStackFrame(LEPUSStackFrame *sf, int local_idx) noexcept; - void PushBytecodeAtoms(const uint8_t *bc_buf, int bc_len, - int use_short_opcodes, int local_idx) noexcept; - void PushObjJSRegExp(JSRegExp *re, int local_idx) noexcept; - void PushObjFunc(LEPUSObject *obj, int local_idx) noexcept; - void PushObjArray(LEPUSObject *obj, int local_idx) noexcept; - void PushObjRegExp(LEPUSObject *obj, int local_idx) noexcept; - void PushObjProperty(JSProperty *pr, int prop_flags, int local_idx) noexcept; - - // tools - bool IsConstString(void *ptr) { - return get_alloc_tag(ptr) == ALLOC_TAG_JSConstString; - } - // field - LEPUSRuntime *rt_; - Queue *queue[THREAD_NUM]; // for visit - void **objs; - int objs_len; - int idx; -}; - -class Finalizer { - public: - Finalizer(LEPUSRuntime *rt) noexcept : rt_(rt) {} - void close_var_refs(LEPUSStackFrame *sf) noexcept; - void free_atom(LEPUSRuntime *rt, JSAtomStruct *p) noexcept; - // do finalizer - void DoFinalizer(void *ptr) noexcept; - void DoFinalizer2(void *ptr) noexcept; -#ifdef ENABLE_LEPUSNG - void JSLepusRefFinalizer(void *ptr) noexcept; -#endif -#ifdef CONFIG_BIGNUM - void JSBigFloatFinalizer(void *ptr) noexcept; -#endif - void JSObjectFinalizer(void *ptr) noexcept; - void JSObjectOnlyFinalizer(void *ptr) noexcept; - void JSStringFinalizer(void *ptr) noexcept; -#ifdef ENABLE_LEPUSNG - void JSStringOnlyFinalizer(void *ptr) noexcept; -#endif - void JSSymbolFinalizer(void *ptr) noexcept; - void JSShapeFinalizer(void *ptr) noexcept; - void JSVarRefFinalizer(void *ptr) noexcept; - void JSFunctionBytecodeFinalizer(void *ptr) noexcept; - void JSArrayBufferFinalizer(void *ptr) noexcept; - void JSTypedArrayFinalizer(void *ptr) noexcept; - void JSMapStateFinalizer(void *ptr) noexcept; - void JSMapIteratorDataFinalizer(void *ptr) noexcept; - void JSGeneratorDataFinalizer(void *ptr) noexcept; - void JSAsyncFunctionDataFinalizer(void *ptr) noexcept; - void JSAsyncGeneratorDataFinalizer(void *ptr) noexcept; - void JSModuleDefFinalizer(void *ptr) noexcept; - void JSFunctionDefFinalizer(void *ptr) noexcept; - void JSSeparableStringFinalizer(void *ptr) noexcept {} - void FinalizationRegistryDataFinalizer(void *ptr) noexcept; - void WeakRefDataFinalizer(void *ptr) noexcept; - - private: - LEPUSRuntime *rt_; -}; - -class MlockScope { - public: - MlockScope(Queue **q) : queue(q) { -#ifndef _WIN32 - for (int i = 0; i < THREAD_NUM; i++) { - SYSCALL_CHECK( - mlock(queue[i]->GetQueue(), queue[i]->GetSize() * sizeof(uintptr_t))) - } -#endif - } - ~MlockScope() { -#ifndef _WIN32 - for (int i = 0; i < THREAD_NUM; i++) { - SYSCALL_CHECK(munlock(queue[i]->GetQueue(), - queue[i]->GetSize() * sizeof(uintptr_t))); - } -#endif - } - - private: - Queue **queue; -}; -#endif // SRC_GC_COLLECTOR_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/qjsvaluevalue-space.h b/test-app/runtime/src/main/cpp/napi/primjs/include/gc/qjsvaluevalue-space.h deleted file mode 100644 index 09668f55..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/qjsvaluevalue-space.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2009 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -#ifndef SRC_GC_QJSVALUEVALUE_SPACE_H_ -#define SRC_GC_QJSVALUEVALUE_SPACE_H_ - -#include "gc/persistent-handle.h" -class QJSValueValueSpace final { - public: - QJSValueValueSpace(const QJSValueValueSpace&) = delete; - QJSValueValueSpace& operator=(const QJSValueValueSpace&) = delete; - - class NodeBlock; - class NodeIterator; - class NodeSpace; - - static void Destroy(void* location); - explicit QJSValueValueSpace(LEPUSRuntime* runtime); - ~QJSValueValueSpace(); - void* Create(); - void IterateAllRoots(int local_idx); - LEPUSRuntime* runtime() const { return runtime_; } - - private: - LEPUSRuntime* runtime_; - NodeSpace* regular_nodes_; -}; - -#endif // SRC_GC_QJSVALUEVALUE_SPACE_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/sweeper.h b/test-app/runtime/src/main/cpp/napi/primjs/include/gc/sweeper.h deleted file mode 100644 index df7dacab..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/sweeper.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -#ifndef SRC_GC_SWEEPER_H_ -#define SRC_GC_SWEEPER_H_ -#include - -#include "quickjs/include/quickjs-inner.h" - -class Sweeper { - public: - Sweeper(mstate state) : m(state) {} - void sweep_finalizer(); - void sweep_free(); - void traverse_finalizer(bool is_only, int64_t begin_time); - void traverse_chunk_for_finalizer(bool is_only = false); - void free_mmap_objects(); - void traverse_chunk_for_free(); - void reinit_freelist(); - int calculate_task_granularity(); - static void generate_freelist(mstate m, msegmentptr sp_begin, - msegmentptr sp_end); - - private: - mstate m; -}; - -void do_finalizer(void* runtime, void* ptr, bool is_only); - -void do_global_finalizer(void* rt); - -void merge_dead_objs(mstate m, msegmentptr sp_begin, msegmentptr sp_end); - -class AcquireIdxScope { - private: - int local_idx; - mstate m_; - - public: - AcquireIdxScope(mstate m) { - local_idx = atomic_acqurie_local_idx(m); - m_ = m; - while (local_idx == -1) { -#ifndef _WIN32 - sched_yield(); -#endif - local_idx = atomic_acqurie_local_idx(m); - } - } - ~AcquireIdxScope() { atomic_release_local_idx(m_, local_idx); } - operator int() { return local_idx; } -}; -void parallel_traverse_heap_segment( - mstate m, size_t segs_in_thread, ByteThreadPool* workerThreadPool, - std::function func); - -#endif // SRC_GC_SWEEPER_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/thread_pool.h b/test-app/runtime/src/main/cpp/napi/primjs/include/gc/thread_pool.h deleted file mode 100644 index b6b12c3b..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/thread_pool.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. - * - * OpenArkCompiler is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan - * PSL v2. You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY - * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO - * NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the - * Mulan PSL v2 for more details. - */ - -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -#ifndef SRC_GC_THREAD_POOL_H_ -#define SRC_GC_THREAD_POOL_H_ - -#ifndef _WIN32 -#include -#endif - -#include -#include -#include -#include -#include - -class ByteTask { - public: - ByteTask() = default; - virtual ~ByteTask() = default; - virtual void Execute(size_t threadId) = 0; -}; - -class ByteLambdaTask : public ByteTask { - public: - explicit ByteLambdaTask(const std::function &function) - : func(function) {} - ~ByteLambdaTask() = default; - void Execute(size_t threadId) override { func(threadId); } - - private: - std::function func; -}; - -class ByteThreadPool; - -class BytePoolThread { - public: - // use for profiling - std::vector *schedCores; - - BytePoolThread(ByteThreadPool *threadPool, const char *threadName, - size_t threadId, size_t stackSize); - ~BytePoolThread(); - - void SetPriority(int32_t prior); - -#ifndef _WIN32 - // get pthread of thread - pthread_t GetThread() const { return pthread; } - - // get thread id of thread - pid_t GetTid() const { return tid; } -#endif - - static void *WorkerFunc(void *param); - - private: - size_t id; -#ifndef _WIN32 - pthread_t pthread; - pid_t tid; -#endif - std::string name; - ByteThreadPool *pool; -}; - -// manual -// new (SetMaxActiveThreadNum(optional) addTask startPool waitFinish)^. Exit -// delete if need to change MaxActiveThreadNum, should waitFinish or stop pool -// at first -class ByteThreadPool { - public: - // Constructor for thread pool, 1) Create threads, 2) wait all thread created - // & sleep name is the thread pool name. thread name = - // Pool_$(poolname)_ThreadId_$(threadId) maxThreadNum is the max thread number - // in pool. prior is the priority of threads in pool. - ByteThreadPool(const char *name, int32_t maxThreadNum, int32_t prior); - - // Destructor for thread pool, 1) close pool 2) wait thread in pool to exit, - // 3) release resources of class - ~ByteThreadPool(); - - // Set priority of each thread in pool. - void SetPriority(int32_t prior); - - // Set max active thread number of pool, redundant thread hangup in sleep - // condition var. notify more waitting thread get to work when pool is - // running. Range [1 - maxThreadNum]. - void SetMaxActiveThreadNum(int32_t num); - - // Get max active thread number of pool. - int32_t GetMaxActiveThreadNum() const { return maxActiveThreadNum; } - - // Get max thread number of pool, defalut = maxThreadNum. - int32_t GetMaxThreadNum() const { return maxThreadNum; } - - // Add new task to task queue , task should inherit from ByteTask. - void AddTask(ByteTask *task); - - // Add task to thread , func indicate Lambda statement. - void AddTask(std::function func); - - // Start thread pool, notify all sleep threads to get to work - void Start(); - - // Wait all task in task queue finished, if pool stopped, only wait until - // current excuting task finish after all task finished, stop pool - // addToExecute indicate whether the caller thread excute task - void WaitFinish(bool addToExecute, - std::vector *schedCores = nullptr); - - // used in none-parallel concurrent mark - void DrainTaskQueue(); - - // Notify & Wait all thread waitting for task to sleep - void Stop(); - - // Notify all thread in pool to exit , notify all waitFinish thread to - // return,nonblock ^. - void Exit(); - - // Remove all task in task queue - void ClearAllTask(); - - // Get task count in queue - size_t GetTaskNumber() { - std::unique_lock taskLock(taskMutex); - return taskQueue.size(); - } - - // Get all BytePoolThread in pool - const std::vector &GetThreads() const { return threads; } - - private: - // thread default stack size 512 KB. - static const size_t kDefaultStackSize = (512 * 1024); - // int32_t priority; - - std::string name; - // pool stop or running state - std::atomic running; - // is pool exit - std::atomic exit; - // all task put in task queue - std::queue taskQueue; - - // active thread 0 ..... maxActiveThreadNum .....maxThreadNum - // max thread number in pool - int32_t maxThreadNum; - - // max active thread number, redundant thread hang up in threadSleepingCondVar - int32_t maxActiveThreadNum; - - // current active thread, when equals to zero, no thread running, all thread - // slept - std::atomic currActiveThreadNum; - - // current waitting thread, when equals to currActiveThreadNum - // no thread excuting, all task finished - std::atomic currWaittingThreadNum; - - // single lock - std::mutex taskMutex; - - // hangup when no task available - std::condition_variable taskEmptyCondVar; - - // hangup when to much active thread or pool stopped - std::condition_variable threadSleepingCondVar; - - // hangup when there is thread excuting - std::condition_variable allWorkDoneCondVar; - - // hangup when there is thread active - std::condition_variable allThreadStopped; - - // use for profiling - std::vector threads; - - // is pool running or stopped - bool IsRunning() const { return running.load(std::memory_order_relaxed); } - - bool IsExited() const { return exit.load(std::memory_order_relaxed); } - - friend class BytePoolThread; -}; - -#endif // SRC_GC_THREAD_POOL_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/global-handles.h b/test-app/runtime/src/main/cpp/napi/primjs/include/global-handles.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/primjs/include/gc/global-handles.h rename to test-app/runtime/src/main/cpp/napi/primjs/include/global-handles.h diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/libregexp.h b/test-app/runtime/src/main/cpp/napi/primjs/include/libregexp.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/libregexp.h rename to test-app/runtime/src/main/cpp/napi/primjs/include/libregexp.h diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/libunicode.h b/test-app/runtime/src/main/cpp/napi/primjs/include/libunicode.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/libunicode.h rename to test-app/runtime/src/main/cpp/napi/primjs/include/libunicode.h diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/list.h b/test-app/runtime/src/main/cpp/napi/primjs/include/list.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/list.h rename to test-app/runtime/src/main/cpp/napi/primjs/include/list.h diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/persistent-handle.h b/test-app/runtime/src/main/cpp/napi/primjs/include/persistent-handle.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/primjs/include/gc/persistent-handle.h rename to test-app/runtime/src/main/cpp/napi/primjs/include/persistent-handle.h diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs-libc.h b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs-libc.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs-libc.h rename to test-app/runtime/src/main/cpp/napi/primjs/include/quickjs-libc.h diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs-tag.h b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs-tag.h similarity index 100% rename from test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs-tag.h rename to test-app/runtime/src/main/cpp/napi/primjs/include/quickjs-tag.h diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs.h b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs.h similarity index 97% rename from test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs.h rename to test-app/runtime/src/main/cpp/napi/primjs/include/quickjs.h index 01f961f7..a728b35f 100644 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs.h +++ b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs.h @@ -36,6 +36,14 @@ #include "base_export.h" #include "list.h" + +// libquick.so exports these symbols with C linkage. Without this guard, C++ +// translation units (jsr.cpp, js_native_api_adapter.cc, ...) would mangle the +// LEPUS_* references and fail to link. Upstream QuickJS ships this guard; the +// vendored Lynx copy dropped it. +#ifdef __cplusplus +extern "C" { +#endif // #define DUMP_LEAKS 0 // for Debug // @@ -664,6 +672,9 @@ typedef struct LEPUSDebuggerCallbacks { uint8_t (*is_devtool_on)(LEPUSContext *ctx); } LEPUSDebuggerCallbacks; +typedef void LEPUS_MarkFunc(LEPUSRuntime *rt, LEPUSValueConst val, + uint64_t trace_tool); + typedef struct LEPUSLepusRefCallbacks { LEPUSValue (*free_value)(LEPUSRuntime *rt, LEPUSValue val); LEPUSValue (*get_property)(LEPUSContext *ctx, LEPUSValue thisObj, JSAtom prop, @@ -675,6 +686,9 @@ typedef struct LEPUSLepusRefCallbacks { void (*free_str_cache)(void *old_ptr, void *new_ptr); size_t (*lepus_ref_equal)(LEPUSValue val1, LEPUSValue val2); LEPUSValue (*lepus_ref_tostring)(LEPUSContext *ctx, LEPUSValue val); + void (*ref_counted_obj_visitor)(LEPUSRuntime *rt, void *ref_counted_obj, + uint64_t trace_tool, int tag, + LEPUS_MarkFunc *f); // void (*free_string_cache)(); } LEPUSLepusRefCallbacks; @@ -688,7 +702,8 @@ typedef struct LEPUSLepusRef { void RegisterLepusType(LEPUSRuntime *rt, int32_t array_typeid, int32_t table_typeid); -void RegisterGCInfoCallback(LEPUSRuntime *rt, void (*func)(const char *, int)); +void RegisterGCInfoCallback(LEPUSRuntime *rt, + void (*func)(LEPUSContext *, const char *, int)); void RegisterLepusRefCallbacks(LEPUSRuntime *rt, LEPUSLepusRefCallbacks *funcs); @@ -714,10 +729,8 @@ void LEPUS_SetGCThreshold(LEPUSRuntime *rt, size_t gc_threshold); LEPUSRuntime *LEPUS_NewRuntime2(const struct LEPUSMallocFunctions *mf, void *opaque, uint32_t mode); void LEPUS_FreeRuntime(LEPUSRuntime *rt); -typedef void LEPUS_MarkFunc(LEPUSRuntime *rt, LEPUSValueConst val, - int local_idx); void LEPUS_MarkValue(LEPUSRuntime *rt, LEPUSValueConst val, - LEPUS_MarkFunc *mark_func, int local_idx); + LEPUS_MarkFunc *mark_func, uint64_t trace_tool); void LEPUS_RunGC(LEPUSRuntime *rt); LEPUS_BOOL LEPUS_IsInGCSweep(LEPUSRuntime *rt); @@ -854,7 +867,7 @@ typedef struct LEPUSClassExoticMethods { typedef void LEPUSClassFinalizer(LEPUSRuntime *rt, LEPUSValue val); typedef void LEPUSClassGCMark(LEPUSRuntime *rt, LEPUSValueConst val, - LEPUS_MarkFunc *mark_func, int local_idx); + LEPUS_MarkFunc *mark_func, uint64_t trace_tool); #define LEPUS_CALL_FLAG_CONSTRUCTOR (1 << 0) typedef LEPUSValue LEPUSClassCall(LEPUSContext *ctx, LEPUSValueConst func_obj, LEPUSValueConst this_val, int argc, @@ -1004,10 +1017,14 @@ char *LEPUS_GetGCTimingInfo(LEPUSContext *ctx, bool is_start); void LEPUS_PushHandle(LEPUSContext *ctx, void *ptr, int type); void LEPUS_ResetHandle(LEPUSContext *ctx, void *ptr, int type); +void CheckObjectCtx(LEPUSContext *ctx, LEPUSValue obj); +void CheckObjectRt(LEPUSRuntime *rt, LEPUSValue obj); + static inline LEPUSValue LEPUS_DupValue(LEPUSContext *ctx, LEPUSValueConst v) { if (LEPUS_VALUE_HAS_REF_COUNT(v)) { LEPUSRefCountHeader *p = (LEPUSRefCountHeader *)LEPUS_VALUE_GET_PTR(v); p->ref_count++; + CheckObjectCtx(ctx, v); } return (LEPUSValue)v; } @@ -1028,6 +1045,7 @@ static inline LEPUSValue LEPUS_DupValueRT(LEPUSRuntime *rt, LEPUSValueConst v) { if (LEPUS_VALUE_HAS_REF_COUNT(v)) { LEPUSRefCountHeader *p = (LEPUSRefCountHeader *)LEPUS_VALUE_GET_PTR(v); p->ref_count++; + CheckObjectRt(rt, v); } return (LEPUSValue)v; } @@ -1137,6 +1155,9 @@ LEPUSValue LEPUS_CallConstructor2(LEPUSContext *ctx, LEPUSValueConst func_obj, LEPUSValueConst *argv); LEPUSValue LEPUS_Eval(LEPUSContext *ctx, const char *input, size_t input_len, const char *filename, int eval_flags); +LEPUSValue LEPUS_Eval2(LEPUSContext *ctx, const char *input, size_t input_len, + const char *filename, int eval_flags, + int start_line_number); #define LEPUS_EVAL_BINARY_LOAD_ONLY (1 << 0) /* only load the module */ LEPUSValue LEPUS_EvalBinary(LEPUSContext *ctx, const uint8_t *buf, size_t buf_len, int flags); @@ -1398,8 +1419,8 @@ static inline LEPUSValue LEPUS_NewCFunctionMagic(LEPUSContext *ctx, const char *name, int length, LEPUSCFunctionEnum cproto, int magic) { - return LEPUS_NewCFunction2(ctx, (LEPUSCFunction *)func, name, length, cproto, - magic); + LEPUSCFunctionType ft = {.generic_magic = func}; + return LEPUS_NewCFunction2(ctx, ft.generic, name, length, cproto, magic); } /* C property definition */ @@ -1603,9 +1624,21 @@ const char *LEPUS_GetStringUtf8(LEPUSContext *, const struct JSString *); void LEPUS_SetFuncFileName(LEPUSContext *, LEPUSValue, const char *); void InitLynxTraceEnv(void *(*)(const char *), void (*)(void *)); + +void SetObjectCtxCheckStatus(LEPUSContext *ctx, bool enable); +bool LEPUS_PushObjectCheckTid(LEPUSContext *ctx); + +void UpdateOuterObjSize(LEPUSRuntime *rt, int size); + +void LEPUS_SetGCObserver(LEPUSRuntime *rt, void *opaque); +void *LEPUS_GetGCObserver(LEPUSRuntime *rt); // #undef lepus_unlikely #undef lepus_force_inline +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif // SRC_INTERPRETER_QUICKJS_INCLUDE_QUICKJS_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/BUILD.gn b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/BUILD.gn deleted file mode 100644 index 0c3cb42c..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/BUILD.gn +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2024 The Lynx Authors. All rights reserved. -# Licensed under the Apache License Version 2.0 that can be found in the -# LICENSE file in the root directory of this source tree. -import("//Primjs.gni") -primjs_source_set("quickjs") { - sources = [ - "source/cutils.cc", - "source/libbf.cc", - "source/libregexp.cc", - "source/libunicode.cc", - "source/primjs_monitor.cc", - "source/quickjs-libc.cc", - "source/quickjs.cc", - "source/quickjs_gc.cc", - "source/quickjs_queue.cc", - "source/quickjs_version.cc", - ] - if (use_bignum) { - sources += [ "source/libbf.cc" ] - } -} diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/libbf.h b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/libbf.h deleted file mode 100644 index d1e4256e..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/libbf.h +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Tiny arbitrary precision floating point library - * - * Copyright (c) 2017-2018 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. -#ifndef SRC_INTERPRETER_QUICKJS_INCLUDE_LIBBF_H_ -#define SRC_INTERPRETER_QUICKJS_INCLUDE_LIBBF_H_ - -#include -#include - -#if defined(__x86_64__) -#define LIMB_LOG2_BITS 6 -#else -#define LIMB_LOG2_BITS 5 -#endif - -#define LIMB_BITS (1 << LIMB_LOG2_BITS) - -#if LIMB_BITS == 64 -typedef __int128 int128_t; -typedef unsigned __int128 uint128_t; -typedef int64_t slimb_t; -typedef uint64_t limb_t; -typedef uint128_t dlimb_t; -#define EXP_MIN INT64_MIN -#define EXP_MAX INT64_MAX - -#else - -typedef int32_t slimb_t; -typedef uint32_t limb_t; -typedef uint64_t dlimb_t; -#define EXP_MIN INT32_MIN -#define EXP_MAX INT32_MAX - -#endif - -/* in bits */ -#define BF_EXP_BITS_MIN 3 -#define BF_EXP_BITS_MAX (LIMB_BITS - 2) -#define BF_PREC_MIN 2 -#define BF_PREC_MAX (((limb_t)1 << BF_EXP_BITS_MAX) - 2) -#define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */ - -#if LIMB_BITS == 64 -#define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197)) -#else -#define BF_CHKSUM_MOD 975620677U -#endif - -#define BF_EXP_ZERO EXP_MIN -#define BF_EXP_INF (EXP_MAX - 1) -#define BF_EXP_NAN EXP_MAX - -/* +/-zero is represented with expn = BF_EXP_ZERO and len = 0, - +/-infinity is represented with expn = BF_EXP_INF and len = 0, - NaN is represented with expn = BF_EXP_NAN and len = 0 (sign is ignored) - */ -typedef struct { - struct bf_context_t *ctx; - int sign; - slimb_t expn; - limb_t len; - limb_t *tab; -} bf_t; - -typedef enum { - BF_RNDN, /* round to nearest, ties to even */ - BF_RNDZ, /* round to zero */ - BF_RNDD, /* round to -inf */ - BF_RNDU, /* round to +inf */ - BF_RNDNA, /* round to nearest, ties away from zero */ - BF_RNDNU, /* round to nearest, ties to +inf */ - BF_RNDF, /* faithful rounding (nondeterministic, either RNDD or RNDU, - inexact flag is always set) */ -} bf_rnd_t; - -/* allow subnormal numbers (only available if the number of exponent - bits is < BF_EXP_BITS_MAX and prec != BF_PREC_INF) */ -#define BF_FLAG_SUBNORMAL (1 << 3) - -#define BF_RND_MASK 0x7 -#define BF_EXP_BITS_SHIFT 4 -#define BF_EXP_BITS_MASK 0x3f - -/* contains the rounding mode and number of exponents bits */ -typedef uint32_t bf_flags_t; - -typedef void *bf_realloc_func_t(void *opaque, void *ptr, size_t size); - -typedef struct { - bf_t val; - limb_t prec; -} BFConstCache; - -typedef struct bf_context_t { - void *realloc_opaque; - bf_realloc_func_t *realloc_func; - BFConstCache log2_cache; - BFConstCache pi_cache; - struct BFNTTState *ntt_state; -} bf_context_t; - -static inline int bf_get_exp_bits(bf_flags_t flags) { - return BF_EXP_BITS_MAX - ((flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK); -} - -static inline bf_flags_t bf_set_exp_bits(int n) { - return (BF_EXP_BITS_MAX - n) << BF_EXP_BITS_SHIFT; -} - -/* returned status */ -#define BF_ST_INVALID_OP (1 << 0) -#define BF_ST_DIVIDE_ZERO (1 << 1) -#define BF_ST_OVERFLOW (1 << 2) -#define BF_ST_UNDERFLOW (1 << 3) -#define BF_ST_INEXACT (1 << 4) -/* not used yet, indicate that a memory allocation error occured. NaN - is returned */ -#define BF_ST_MEM_ERROR (1 << 5) - -#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */ - -static inline slimb_t bf_max(slimb_t a, slimb_t b) { - if (a > b) - return a; - else - return b; -} - -static inline slimb_t bf_min(slimb_t a, slimb_t b) { - if (a < b) - return a; - else - return b; -} - -void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func, - void *realloc_opaque); -void bf_context_end(bf_context_t *s); -/* free memory allocated for the bf cache data */ -void bf_clear_cache(bf_context_t *s); - -static inline void *bf_realloc(bf_context_t *s, void *ptr, size_t size) { - return realloc(ptr, size); -} - -void bf_init(bf_context_t *s, bf_t *r); - -static inline void bf_delete(bf_t *r) { - bf_context_t *s = r->ctx; - /* we accept to delete a zeroed bf_t structure */ - if (s) { - bf_realloc(s, r->tab, 0); - } -} - -static inline void bf_neg(bf_t *r) { r->sign ^= 1; } - -static inline int bf_is_finite(const bf_t *a) { return (a->expn < BF_EXP_INF); } - -static inline int bf_is_nan(const bf_t *a) { return (a->expn == BF_EXP_NAN); } - -static inline int bf_is_zero(const bf_t *a) { return (a->expn == BF_EXP_ZERO); } - -void bf_set_ui(bf_t *r, uint64_t a); -void bf_set_si(bf_t *r, int64_t a); -void bf_set_nan(bf_t *r); -void bf_set_zero(bf_t *r, int is_neg); -void bf_set_inf(bf_t *r, int is_neg); -void bf_set(bf_t *r, const bf_t *a); -void bf_move(bf_t *r, bf_t *a); -int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode); -void bf_set_float64(bf_t *a, double d); - -int bf_cmpu(const bf_t *a, const bf_t *b); -int bf_cmp_full(const bf_t *a, const bf_t *b); -int bf_cmp_eq(const bf_t *a, const bf_t *b); -int bf_cmp_le(const bf_t *a, const bf_t *b); -int bf_cmp_lt(const bf_t *a, const bf_t *b); -int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, - bf_flags_t flags); -int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, - bf_flags_t flags); -int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, - bf_flags_t flags); -int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, - bf_flags_t flags); -int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, - bf_flags_t flags); -int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, - bf_flags_t flags); -int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags); -int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, - bf_flags_t flags); -#define BF_DIVREM_EUCLIDIAN BF_RNDF -int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, - bf_flags_t flags, int rnd_mode); -int bf_fmod(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, - bf_flags_t flags); -int bf_remainder(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, - bf_flags_t flags); -int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, - bf_flags_t flags); -int bf_pow_ui(bf_t *r, const bf_t *a, limb_t b, limb_t prec, bf_flags_t flags); -int bf_pow_ui_ui(bf_t *r, limb_t a1, limb_t b, limb_t prec, bf_flags_t flags); -int bf_rint(bf_t *r, limb_t prec, bf_flags_t flags); -int bf_round(bf_t *r, limb_t prec, bf_flags_t flags); -int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a); -int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); -slimb_t bf_get_exp_min(const bf_t *a); -void bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b); -void bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b); -void bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b); - -/* additional flags for bf_atof */ -/* do not accept hex radix prefix (0x or 0X) if radix = 0 or radix = 16 */ -#define BF_ATOF_NO_HEX (1 << 16) -/* accept binary (0b or 0B) or octal (0o or 0O) radix prefix if radix = 0 */ -#define BF_ATOF_BIN_OCT (1 << 17) -/* Only accept integers (no decimal point, no exponent, no infinity nor NaN */ -#define BF_ATOF_INT_ONLY (1 << 18) -/* Do not accept radix prefix after sign */ -#define BF_ATOF_NO_PREFIX_AFTER_SIGN (1 << 19) -/* Do not parse NaN and parse case sensitive 'Infinity' */ -#define BF_ATOF_JS_QUIRKS (1 << 20) -/* Do not round integers to the indicated precision */ -#define BF_ATOF_INT_PREC_INF (1 << 21) -/* Support legacy octal syntax for well formed numbers */ -#define BF_ATOF_LEGACY_OCTAL (1 << 22) -/* accept _ between digits as a digit separator */ -#define BF_ATOF_UNDERSCORE_SEP (1 << 23) -/* if a 'n' suffix is present, force integer parsing (XXX: remove) */ -#define BF_ATOF_INT_N_SUFFIX (1 << 24) -/* if set return NaN if empty number string (instead of 0) */ -#define BF_ATOF_NAN_IF_EMPTY (1 << 25) -/* only accept decimal floating point if radix = 0 */ -#define BF_ATOF_ONLY_DEC_FLOAT (1 << 26) - -/* additional return flags */ -/* indicate that the parsed number is an integer (only set when the - flags BF_ATOF_INT_PREC_INF or BF_ATOF_INT_N_SUFFIX are used) */ -#define BF_ATOF_ST_INTEGER (1 << 5) -/* integer parsed as legacy octal */ -#define BF_ATOF_ST_LEGACY_OCTAL (1 << 6) - -int bf_atof(bf_t *a, const char *str, const char **pnext, int radix, - limb_t prec, bf_flags_t flags); -/* this version accepts prec = BF_PREC_INF and returns the radix - exponent */ -int bf_atof2(bf_t *r, slimb_t *pexponent, const char *str, const char **pnext, - int radix, limb_t prec, bf_flags_t flags); -int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix, slimb_t expn, - limb_t prec, bf_flags_t flags); - -#define BF_FTOA_FORMAT_MASK (3 << 16) -/* fixed format: prec significant digits rounded with (flags & - BF_RND_MASK). Exponential notation is used if too many zeros are - needed. */ -#define BF_FTOA_FORMAT_FIXED (0 << 16) -/* fractional format: prec digits after the decimal point rounded with - (flags & BF_RND_MASK) */ -#define BF_FTOA_FORMAT_FRAC (1 << 16) -/* free format: use as many digits as necessary so that bf_atof() - return the same number when using precision 'prec', rounding to - nearest and the subnormal+exponent configuration of 'flags'. The - result is meaningful only if 'a' is already rounded to the wanted - precision. - - Infinite precision (BF_PREC_INF) is supported when the radix is a - power of two. */ -#define BF_FTOA_FORMAT_FREE (2 << 16) -/* same as BF_FTOA_FORMAT_FREE but uses the minimum number of digits - (takes more computation time). */ -#define BF_FTOA_FORMAT_FREE_MIN (3 << 16) - -/* force exponential notation for fixed or free format */ -#define BF_FTOA_FORCE_EXP (1 << 20) -/* add 0x prefix for base 16, 0o prefix for base 8 or 0b prefix for - base 2 if non zero value */ -#define BF_FTOA_ADD_PREFIX (1 << 21) -#define BF_FTOA_JS_QUIRKS (1 << 22) - -size_t bf_ftoa(char **pbuf, const bf_t *a, int radix, limb_t prec, - bf_flags_t flags); - -/* modulo 2^n instead of saturation. NaN and infinity return 0 */ -#define BF_GET_INT_MOD (1 << 0) -int bf_get_int32(int *pres, const bf_t *a, int flags); -int bf_get_int64(int64_t *pres, const bf_t *a, int flags); - -/* the following functions are exported for testing only. */ -void bf_print_str(const char *str, const bf_t *a); -void bf_resize(bf_t *r, limb_t len); -int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len); -void bf_recip(bf_t *r, const bf_t *a, limb_t prec); -void bf_rsqrt(bf_t *a, const bf_t *x, limb_t prec); -int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags); -int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k); -slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv, - int is_ceil1); - -/* transcendental functions */ -int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags); -int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags); -int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); -int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); -#define BF_POW_JS_QUICKS (1 << 16) -int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, - bf_flags_t flags); -int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); -int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); -int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); -int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); -int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x, limb_t prec, - bf_flags_t flags); -int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); -int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); - -#endif // SRC_INTERPRETER_QUICKJS_INCLUDE_LIBBF_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/libregexp-opcode.h b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/libregexp-opcode.h deleted file mode 100644 index 480c23df..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/libregexp-opcode.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Regular Expression Engine - * - * Copyright (c) 2017-2018 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. -#ifdef DEF - -DEF(invalid, 1) /* never used */ -DEF(char, 3) -DEF(char32, 5) -DEF(dot, 1) -DEF(any, 1) /* same as dot but match any character including line terminator */ -DEF(line_start, 1) -DEF(line_end, 1) -DEF(goto, 5) -DEF(split_goto_first, 5) -DEF(split_next_first, 5) -DEF(match, 1) -DEF(save_start, 2) /* save start position */ -DEF(save_end, 2) /* save end position, must come after saved_start */ -DEF(save_reset, 3) /* reset save positions */ -DEF(loop, 5) /* decrement the top the stack and goto if != 0 */ -DEF(push_i32, 5) /* push integer on the stack */ -DEF(drop, 1) -DEF(word_boundary, 1) -DEF(not_word_boundary, 1) -DEF(back_reference, 2) -DEF(backward_back_reference, 2) /* must come after back_reference */ -DEF(range, 3) /* variable length */ -DEF(range32, 3) /* variable length */ -DEF(lookahead, 5) -DEF(negative_lookahead, 5) -DEF(push_char_pos, 1) /* push the character position on the stack */ -DEF(bne_char_pos, 5) /* pop one stack element and jump if equal to the character - position */ -DEF(prev, 1) /* go to the previous char */ -DEF(simple_greedy_quant, 17) - -#endif /* DEF */ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/libunicode-table.h b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/libunicode-table.h deleted file mode 100644 index 9b4a5b4b..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/libunicode-table.h +++ /dev/null @@ -1,3495 +0,0 @@ -/* - * Regular Expression Engine - * - * Copyright (c) 2017-2018 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -/* Compressed unicode tables */ -/* Automatically generated file - do not edit */ - -#include - -static const uint32_t case_conv_table1[359] = { - 0x00209a30, 0x00309a00, 0x005a8173, 0x00601730, 0x006c0730, 0x006f81b3, - 0x00701700, 0x007c0700, 0x007f8100, 0x00803040, 0x009801c3, 0x00988190, - 0x00990640, 0x009c9040, 0x00a481b4, 0x00a52e40, 0x00bc0130, 0x00bc8640, - 0x00bf8170, 0x00c00100, 0x00c08130, 0x00c10440, 0x00c30130, 0x00c38240, - 0x00c48230, 0x00c58240, 0x00c70130, 0x00c78130, 0x00c80130, 0x00c88240, - 0x00c98130, 0x00ca0130, 0x00ca8100, 0x00cb0130, 0x00cb8130, 0x00cc0240, - 0x00cd0100, 0x00ce0130, 0x00ce8130, 0x00cf0100, 0x00cf8130, 0x00d00640, - 0x00d30130, 0x00d38240, 0x00d48130, 0x00d60240, 0x00d70130, 0x00d78240, - 0x00d88230, 0x00d98440, 0x00db8130, 0x00dc0240, 0x00de0240, 0x00df8100, - 0x00e20350, 0x00e38350, 0x00e50350, 0x00e69040, 0x00ee8100, 0x00ef1240, - 0x00f801b4, 0x00f88350, 0x00fa0240, 0x00fb0130, 0x00fb8130, 0x00fc2840, - 0x01100130, 0x01111240, 0x011d0131, 0x011d8240, 0x011e8130, 0x011f0131, - 0x011f8201, 0x01208240, 0x01218130, 0x01220130, 0x01228130, 0x01230a40, - 0x01280101, 0x01288101, 0x01290101, 0x01298100, 0x012a0100, 0x012b0200, - 0x012c8100, 0x012d8100, 0x012e0101, 0x01300100, 0x01308101, 0x01318100, - 0x01328101, 0x01330101, 0x01340100, 0x01348100, 0x01350101, 0x01358101, - 0x01360101, 0x01378100, 0x01388101, 0x01390100, 0x013a8100, 0x013e8101, - 0x01400100, 0x01410101, 0x01418100, 0x01438101, 0x01440100, 0x01448100, - 0x01450200, 0x01460100, 0x01490100, 0x014e8101, 0x014f0101, 0x01a28173, - 0x01b80440, 0x01bb0240, 0x01bd8300, 0x01bf8130, 0x01c30130, 0x01c40330, - 0x01c60130, 0x01c70230, 0x01c801d0, 0x01c89130, 0x01d18930, 0x01d60100, - 0x01d68300, 0x01d801d3, 0x01d89100, 0x01e10173, 0x01e18900, 0x01e60100, - 0x01e68200, 0x01e78130, 0x01e80173, 0x01e88173, 0x01ea8173, 0x01eb0173, - 0x01eb8100, 0x01ec1840, 0x01f80173, 0x01f88173, 0x01f90100, 0x01f98100, - 0x01fa01a0, 0x01fa8173, 0x01fb8240, 0x01fc8130, 0x01fd0240, 0x01fe8330, - 0x02001030, 0x02082030, 0x02182000, 0x02281000, 0x02302240, 0x02453640, - 0x02600130, 0x02608e40, 0x02678100, 0x02686040, 0x0298a630, 0x02b0a600, - 0x02c381b5, 0x08502631, 0x08638131, 0x08668131, 0x08682b00, 0x087e8300, - 0x09d05011, 0x09f80610, 0x09fc0620, 0x0e400174, 0x0e408174, 0x0e410174, - 0x0e418174, 0x0e420174, 0x0e428174, 0x0e430174, 0x0e438180, 0x0e440180, - 0x0e482b30, 0x0e5e8330, 0x0ebc8101, 0x0ebe8101, 0x0ec70101, 0x0f007e40, - 0x0f3f1840, 0x0f4b01b5, 0x0f4b81b6, 0x0f4c01b6, 0x0f4c81b6, 0x0f4d01b7, - 0x0f4d8180, 0x0f4f0130, 0x0f506040, 0x0f800800, 0x0f840830, 0x0f880600, - 0x0f8c0630, 0x0f900800, 0x0f940830, 0x0f980800, 0x0f9c0830, 0x0fa00600, - 0x0fa40630, 0x0fa801b0, 0x0fa88100, 0x0fa901d3, 0x0fa98100, 0x0faa01d3, - 0x0faa8100, 0x0fab01d3, 0x0fab8100, 0x0fac8130, 0x0fad8130, 0x0fae8130, - 0x0faf8130, 0x0fb00800, 0x0fb40830, 0x0fb80200, 0x0fb90400, 0x0fbb0200, - 0x0fbc0201, 0x0fbd0201, 0x0fbe0201, 0x0fc008b7, 0x0fc40867, 0x0fc808b8, - 0x0fcc0868, 0x0fd008b8, 0x0fd40868, 0x0fd80200, 0x0fd901b9, 0x0fd981b1, - 0x0fda01b9, 0x0fdb01b1, 0x0fdb81d7, 0x0fdc0230, 0x0fdd0230, 0x0fde0161, - 0x0fdf0173, 0x0fe101b9, 0x0fe181b2, 0x0fe201ba, 0x0fe301b2, 0x0fe381d8, - 0x0fe40430, 0x0fe60162, 0x0fe80200, 0x0fe901d0, 0x0fe981d0, 0x0feb01b0, - 0x0feb81d0, 0x0fec0230, 0x0fed0230, 0x0ff00201, 0x0ff101d3, 0x0ff181d3, - 0x0ff201ba, 0x0ff28101, 0x0ff301b0, 0x0ff381d3, 0x0ff40230, 0x0ff50230, - 0x0ff60131, 0x0ff901ba, 0x0ff981b2, 0x0ffa01bb, 0x0ffb01b2, 0x0ffb81d9, - 0x0ffc0230, 0x0ffd0230, 0x0ffe0162, 0x109301a0, 0x109501a0, 0x109581a0, - 0x10990131, 0x10a70101, 0x10b01031, 0x10b81001, 0x10c18240, 0x125b1a31, - 0x12681a01, 0x16002f31, 0x16182f01, 0x16300240, 0x16310130, 0x16318130, - 0x16320130, 0x16328100, 0x16330100, 0x16338640, 0x16368130, 0x16370130, - 0x16378130, 0x16380130, 0x16390240, 0x163a8240, 0x163f0230, 0x16406440, - 0x16758440, 0x16790240, 0x16802600, 0x16938100, 0x16968100, 0x53202e40, - 0x53401c40, 0x53910e40, 0x53993e40, 0x53bc8440, 0x53be8130, 0x53bf0a40, - 0x53c58240, 0x53c68130, 0x53c80440, 0x53ca0101, 0x53cb1440, 0x53d50130, - 0x53d58130, 0x53d60130, 0x53d68130, 0x53d70130, 0x53d80130, 0x53d88130, - 0x53d90130, 0x53d98131, 0x53da0c40, 0x53e10240, 0x53e20131, 0x53e28130, - 0x53e30130, 0x55a98101, 0x55b85020, 0x7d8001b2, 0x7d8081b2, 0x7d8101b2, - 0x7d8181da, 0x7d8201da, 0x7d8281b3, 0x7d8301b3, 0x7d8981bb, 0x7d8a01bb, - 0x7d8a81bb, 0x7d8b01bc, 0x7d8b81bb, 0x7f909a31, 0x7fa09a01, 0x82002831, - 0x82142801, 0x82582431, 0x826c2401, 0x86403331, 0x86603301, 0x8c502031, - 0x8c602001, 0xb7202031, 0xb7302001, 0xf4802231, 0xf4912201, -}; - -static const uint8_t case_conv_table2[359] = { - 0x01, 0x00, 0x9c, 0x06, 0x07, 0x4d, 0x03, 0x04, 0x10, 0x00, 0x8f, 0x0b, - 0x00, 0x00, 0x11, 0x00, 0x08, 0x00, 0x53, 0x4a, 0x51, 0x00, 0x52, 0x00, - 0x53, 0x00, 0x3a, 0x54, 0x55, 0x00, 0x57, 0x59, 0x3f, 0x5d, 0x5c, 0x00, - 0x46, 0x61, 0x63, 0x42, 0x64, 0x00, 0x66, 0x00, 0x68, 0x00, 0x6a, 0x00, - 0x6c, 0x00, 0x6e, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x93, 0x00, 0x00, 0x20, 0x35, 0x00, 0x27, 0x00, 0x21, 0x00, 0x24, 0x22, - 0x2a, 0x00, 0x13, 0x6b, 0x6d, 0x00, 0x26, 0x24, 0x27, 0x14, 0x16, 0x18, - 0x1b, 0x1c, 0x3e, 0x1e, 0x3f, 0x1f, 0x39, 0x3d, 0x22, 0x21, 0x41, 0x1e, - 0x40, 0x25, 0x25, 0x26, 0x28, 0x20, 0x2a, 0x49, 0x2c, 0x43, 0x2e, 0x4b, - 0x30, 0x4c, 0x32, 0x44, 0x42, 0x99, 0x00, 0x00, 0x95, 0x8f, 0x7d, 0x7e, - 0x83, 0x84, 0x12, 0x80, 0x82, 0x76, 0x77, 0x12, 0x7b, 0xa3, 0x7c, 0x78, - 0x79, 0x8a, 0x92, 0x98, 0xa6, 0xa0, 0x85, 0x00, 0x9a, 0xa1, 0x93, 0x75, - 0x33, 0x95, 0x00, 0x8e, 0x00, 0x74, 0x99, 0x98, 0x97, 0x96, 0x00, 0x00, - 0x9e, 0x00, 0x9c, 0x00, 0xa1, 0xa0, 0x15, 0x2e, 0x2f, 0x30, 0xb4, 0xb5, - 0x4c, 0xaa, 0xa9, 0x12, 0x14, 0x1e, 0x21, 0x22, 0x22, 0x2a, 0x34, 0x35, - 0xa6, 0xa7, 0x36, 0x1f, 0x4a, 0x00, 0x00, 0x97, 0x01, 0x5a, 0xda, 0x1d, - 0x36, 0x05, 0x00, 0xc4, 0xc3, 0xc6, 0xc5, 0xc8, 0xc7, 0xca, 0xc9, 0xcc, - 0xcb, 0xc4, 0xd5, 0x45, 0xd6, 0x42, 0xd7, 0x46, 0xd8, 0xce, 0xd0, 0xd2, - 0xd4, 0xda, 0xd9, 0xee, 0xf6, 0xfe, 0x0e, 0x07, 0x0f, 0x80, 0x9f, 0x00, - 0x21, 0x80, 0xa3, 0xed, 0x00, 0xc0, 0x40, 0xc6, 0x60, 0xe7, 0xdb, 0xe6, - 0x99, 0xc0, 0x00, 0x00, 0x06, 0x60, 0xdc, 0x29, 0xfd, 0x15, 0x12, 0x06, - 0x16, 0xf8, 0xdd, 0x06, 0x15, 0x12, 0x84, 0x08, 0xc6, 0x16, 0xff, 0xdf, - 0x03, 0xc0, 0x40, 0x00, 0x46, 0x60, 0xde, 0xe0, 0x6d, 0x37, 0x38, 0x39, - 0x15, 0x14, 0x17, 0x16, 0x00, 0x1a, 0x19, 0x1c, 0x1b, 0x00, 0x5f, 0xb7, - 0x65, 0x44, 0x47, 0x00, 0x4f, 0x62, 0x4e, 0x50, 0x00, 0x00, 0x48, 0x00, - 0x00, 0x00, 0xa3, 0xa4, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, - 0x00, 0x5a, 0x00, 0x48, 0x00, 0x5b, 0x56, 0x58, 0x60, 0x5e, 0x70, 0x69, - 0x6f, 0x4b, 0x00, 0x00, 0x3b, 0x67, 0xb8, 0x45, 0xa8, 0x8a, 0x8b, 0x8c, - 0xab, 0xac, 0x58, 0x58, 0xaf, 0x94, 0xb0, 0x6f, 0xb2, 0x5a, 0x59, 0x5c, - 0x5b, 0x5e, 0x5d, 0x60, 0x5f, 0x62, 0x61, 0x64, 0x63, 0x66, 0x65, -}; - -static const uint16_t case_conv_ext[58] = { - 0x0399, 0x0308, 0x0301, 0x03a5, 0x0313, 0x0300, 0x0342, 0x0391, 0x0397, - 0x03a9, 0x0046, 0x0049, 0x004c, 0x0053, 0x0069, 0x0307, 0x02bc, 0x004e, - 0x004a, 0x030c, 0x0535, 0x0552, 0x0048, 0x0331, 0x0054, 0x0057, 0x030a, - 0x0059, 0x0041, 0x02be, 0x1f08, 0x1f80, 0x1f28, 0x1f90, 0x1f68, 0x1fa0, - 0x1fba, 0x0386, 0x1fb3, 0x1fca, 0x0389, 0x1fc3, 0x03a1, 0x1ffa, 0x038f, - 0x1ff3, 0x0544, 0x0546, 0x053b, 0x054e, 0x053d, 0x03b8, 0x0462, 0xa64a, - 0x1e60, 0x03c9, 0x006b, 0x00e5, -}; - -static const uint8_t unicode_prop_Cased1_table[172] = { - 0x40, 0xa9, 0x80, 0x8e, 0x80, 0xfc, 0x80, 0xd3, 0x80, 0x8c, 0x80, 0x8d, - 0x81, 0x8d, 0x02, 0x80, 0xe1, 0x80, 0x91, 0x85, 0x9a, 0x01, 0x00, 0x01, - 0x11, 0x00, 0x01, 0x04, 0x08, 0x01, 0x08, 0x30, 0x08, 0x01, 0x15, 0x20, - 0x00, 0x39, 0x99, 0x31, 0x9d, 0x84, 0x40, 0x94, 0x80, 0xd6, 0x82, 0xa6, - 0x80, 0x41, 0x62, 0x80, 0xa6, 0x80, 0x57, 0x76, 0xf8, 0x02, 0x80, 0x8f, - 0x80, 0xb0, 0x40, 0xdb, 0x08, 0x80, 0x41, 0xd0, 0x80, 0x8c, 0x80, 0x8f, - 0x8c, 0xe4, 0x03, 0x01, 0x89, 0x00, 0x14, 0x28, 0x10, 0x11, 0x02, 0x01, - 0x18, 0x0b, 0x24, 0x4b, 0x26, 0x01, 0x01, 0x86, 0xe5, 0x80, 0x60, 0x79, - 0xb6, 0x81, 0x40, 0x91, 0x81, 0xbd, 0x88, 0x94, 0x05, 0x80, 0x98, 0x80, - 0xc7, 0x82, 0x43, 0x34, 0xa2, 0x06, 0x80, 0x8b, 0x61, 0x28, 0x97, 0xd4, - 0x80, 0xc6, 0x01, 0x08, 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, - 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, 0x16, 0x80, 0x41, 0x53, - 0x81, 0x98, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, - 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x07, 0x59, 0x63, 0x99, - 0x85, 0x99, 0x85, 0x99, -}; - -static const uint8_t unicode_prop_Cased1_index[18] = { - 0xb9, 0x02, 0xe0, 0xa0, 0x1e, 0x40, 0x9e, 0xa6, 0x40, - 0xba, 0xd4, 0x01, 0x89, 0xd7, 0x01, 0x8a, 0xf1, 0x01, -}; - -static const uint8_t unicode_prop_Case_Ignorable_table[678] = { - 0xa6, 0x05, 0x80, 0x8a, 0x80, 0xa2, 0x00, 0x80, 0xc6, 0x03, 0x00, 0x03, - 0x01, 0x81, 0x41, 0xf6, 0x40, 0xbf, 0x19, 0x18, 0x88, 0x08, 0x80, 0x40, - 0xfa, 0x86, 0x40, 0xce, 0x80, 0xb6, 0xac, 0x00, 0x01, 0x01, 0x00, 0xab, - 0x80, 0x8a, 0x85, 0x89, 0x8a, 0x00, 0xa2, 0x80, 0x89, 0x94, 0x8f, 0x80, - 0xe4, 0x38, 0x89, 0x03, 0xa0, 0x00, 0x80, 0x9d, 0x9a, 0xda, 0x8a, 0xb9, - 0x8a, 0x18, 0x08, 0x97, 0x97, 0xaa, 0x82, 0xf6, 0xaf, 0xb6, 0x00, 0x03, - 0x3b, 0x02, 0x86, 0x89, 0x81, 0x8c, 0x80, 0x8e, 0x80, 0xb9, 0x03, 0x1f, - 0x80, 0x93, 0x81, 0x99, 0x01, 0x81, 0xb8, 0x03, 0x0b, 0x09, 0x12, 0x80, - 0x9d, 0x0a, 0x80, 0x8a, 0x81, 0xb8, 0x03, 0x20, 0x0b, 0x80, 0x93, 0x81, - 0x95, 0x28, 0x80, 0xb9, 0x01, 0x00, 0x1f, 0x07, 0x80, 0x8a, 0x81, 0x9d, - 0x80, 0xbc, 0x80, 0x8b, 0x80, 0xb1, 0x02, 0x80, 0xb8, 0x14, 0x10, 0x1e, - 0x81, 0x8a, 0x81, 0x9c, 0x80, 0xb9, 0x01, 0x05, 0x04, 0x81, 0x93, 0x81, - 0x9b, 0x81, 0xb8, 0x0b, 0x1f, 0x80, 0x93, 0x81, 0xe5, 0x06, 0x10, 0x80, - 0xd9, 0x01, 0x86, 0x8a, 0x88, 0xe1, 0x01, 0x88, 0x88, 0x00, 0x85, 0xc9, - 0x81, 0x9a, 0x00, 0x00, 0x80, 0xb6, 0x8d, 0x04, 0x01, 0x84, 0x8a, 0x80, - 0xa3, 0x88, 0x80, 0xe5, 0x18, 0x28, 0x09, 0x81, 0x98, 0x0b, 0x82, 0x8f, - 0x83, 0x8c, 0x01, 0x0d, 0x80, 0x8e, 0x80, 0xdd, 0x80, 0x42, 0x5f, 0x82, - 0x43, 0xb1, 0x82, 0x9c, 0x82, 0x9c, 0x81, 0x9d, 0x81, 0xbf, 0x08, 0x37, - 0x01, 0x8a, 0x10, 0x20, 0xac, 0x83, 0xb3, 0x80, 0xc0, 0x81, 0xa1, 0x80, - 0xf5, 0x13, 0x81, 0x88, 0x05, 0x82, 0x40, 0xda, 0x09, 0x80, 0xb9, 0x00, - 0x30, 0x00, 0x01, 0x3d, 0x89, 0x08, 0xa6, 0x07, 0x8e, 0xc0, 0x83, 0xaf, - 0x00, 0x20, 0x04, 0x80, 0xa7, 0x88, 0x8b, 0x81, 0x9f, 0x19, 0x08, 0x82, - 0xb7, 0x00, 0x0a, 0x00, 0x82, 0xb9, 0x39, 0x81, 0xbf, 0x85, 0xd1, 0x10, - 0x8c, 0x06, 0x18, 0x28, 0x11, 0xb1, 0xbe, 0x8c, 0x80, 0xa1, 0xde, 0x04, - 0x41, 0xbc, 0x00, 0x82, 0x8a, 0x82, 0x8c, 0x82, 0x8c, 0x82, 0x8c, 0x81, - 0x8b, 0x27, 0x81, 0x89, 0x01, 0x01, 0x84, 0xb0, 0x20, 0x89, 0x00, 0x8c, - 0x80, 0x8f, 0x8c, 0xb2, 0xa0, 0x4b, 0x8a, 0x81, 0xf0, 0x82, 0xfc, 0x80, - 0x8e, 0x80, 0xdf, 0x9f, 0xae, 0x80, 0x41, 0xd4, 0x80, 0xa3, 0x1a, 0x24, - 0x80, 0xdc, 0x85, 0xdc, 0x82, 0x60, 0x6f, 0x15, 0x80, 0x44, 0xe1, 0x85, - 0x41, 0x0d, 0x80, 0xe1, 0x18, 0x89, 0x00, 0x9b, 0x83, 0xcf, 0x81, 0x8d, - 0xa1, 0xcd, 0x80, 0x96, 0x82, 0xec, 0x0f, 0x02, 0x03, 0x80, 0x98, 0x81, - 0x40, 0x9c, 0x81, 0x99, 0x91, 0x8c, 0x80, 0xa5, 0x87, 0x98, 0x8a, 0xad, - 0x82, 0xaf, 0x01, 0x19, 0x81, 0x90, 0x80, 0x94, 0x81, 0xc1, 0x29, 0x09, - 0x81, 0x8b, 0x07, 0x80, 0xa2, 0x80, 0x8a, 0x80, 0xb2, 0x00, 0x11, 0x0c, - 0x08, 0x80, 0x9a, 0x80, 0x8d, 0x0c, 0x08, 0x80, 0xe3, 0x84, 0x40, 0x84, - 0x01, 0x03, 0x80, 0x60, 0x4f, 0x2f, 0x80, 0x40, 0x92, 0x8f, 0x42, 0x3d, - 0x8f, 0x10, 0x8b, 0x8f, 0xa1, 0x01, 0x80, 0x40, 0xa8, 0x06, 0x05, 0x80, - 0x8a, 0x80, 0xa2, 0x00, 0x80, 0xae, 0x80, 0xac, 0x81, 0xc2, 0x80, 0x94, - 0x82, 0x42, 0x00, 0x80, 0x40, 0xe1, 0x80, 0x40, 0x94, 0x84, 0x46, 0x85, - 0x10, 0x0c, 0x83, 0xa7, 0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x83, - 0x42, 0x1d, 0x8a, 0x40, 0xaf, 0x80, 0xb5, 0x8e, 0xb7, 0x82, 0xb0, 0x19, - 0x09, 0x80, 0x8e, 0x80, 0xb1, 0x82, 0xa3, 0x20, 0x87, 0xbd, 0x80, 0x8b, - 0x81, 0xb3, 0x88, 0x89, 0x83, 0xe1, 0x11, 0x00, 0x0d, 0x80, 0x40, 0x9f, - 0x02, 0x87, 0x94, 0x81, 0xb8, 0x0a, 0x80, 0xa4, 0x32, 0x84, 0x40, 0xc2, - 0x39, 0x10, 0x80, 0x96, 0x80, 0xd3, 0x28, 0x03, 0x08, 0x81, 0x40, 0xed, - 0x1d, 0x08, 0x81, 0x9a, 0x81, 0xd4, 0x39, 0x00, 0x81, 0xe9, 0x00, 0x01, - 0x28, 0x80, 0xe4, 0x11, 0x18, 0x84, 0x41, 0x02, 0x88, 0x01, 0x41, 0x98, - 0x19, 0x0b, 0x80, 0x9f, 0x89, 0xa7, 0x29, 0x1f, 0x80, 0x88, 0x29, 0x82, - 0xad, 0x8c, 0x01, 0x41, 0x95, 0x30, 0x28, 0x80, 0xd1, 0x95, 0x0e, 0x01, - 0x01, 0xf9, 0x2a, 0x00, 0x08, 0x30, 0x80, 0xc7, 0x0a, 0x00, 0x80, 0x41, - 0x5a, 0x81, 0x55, 0x3a, 0x88, 0x60, 0x36, 0xb6, 0x84, 0xba, 0x86, 0x88, - 0x83, 0x44, 0x0a, 0x80, 0xbe, 0x90, 0xbf, 0x08, 0x80, 0x60, 0x4c, 0xb8, - 0x08, 0x83, 0x54, 0xc2, 0x82, 0x88, 0x8f, 0x0e, 0x9d, 0x83, 0x40, 0x93, - 0x82, 0x47, 0xba, 0xb6, 0x83, 0xb1, 0x38, 0x8d, 0x80, 0x95, 0x20, 0x8e, - 0x45, 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04, 0x41, 0x04, 0x8d, 0x41, 0xad, - 0x83, 0x45, 0xdf, 0x86, 0xec, 0x87, 0x4a, 0xae, 0x84, 0x6c, 0x0c, 0x00, - 0x80, 0x9d, 0xdf, 0xff, 0x40, 0xef, -}; - -static const uint8_t unicode_prop_Case_Ignorable_index[66] = { - 0xc0, 0x05, 0x00, 0x2e, 0x08, 0x20, 0x52, 0x0a, 0x00, 0x05, 0x0c, - 0x00, 0x4f, 0x0e, 0x20, 0x75, 0x10, 0x20, 0x44, 0x18, 0x00, 0x43, - 0x1b, 0x00, 0x00, 0x1e, 0x00, 0x7e, 0x2c, 0x00, 0x7e, 0xa6, 0x40, - 0x83, 0xa9, 0x20, 0xf7, 0xaa, 0x00, 0x41, 0xff, 0x20, 0x28, 0x0d, - 0x01, 0x3f, 0x12, 0x41, 0xde, 0x15, 0x21, 0x5c, 0x1a, 0x01, 0xf5, - 0x6a, 0x21, 0x37, 0xda, 0x01, 0x02, 0x00, 0x2e, 0xf0, 0x01, 0x0e, -}; - -static const uint8_t unicode_prop_ID_Start_table[1024] = { - 0xc0, 0x99, 0x85, 0x99, 0xae, 0x80, 0x89, 0x03, 0x04, 0x96, 0x80, 0x9e, - 0x80, 0x41, 0xc9, 0x83, 0x8b, 0x8d, 0x26, 0x00, 0x80, 0x40, 0x80, 0x20, - 0x09, 0x18, 0x05, 0x00, 0x10, 0x00, 0x93, 0x80, 0xd2, 0x80, 0x40, 0x8a, - 0x87, 0x40, 0xa5, 0x80, 0xa5, 0x08, 0x85, 0xa8, 0xc6, 0x9a, 0x1b, 0xac, - 0xaa, 0xa2, 0x08, 0xe2, 0x00, 0x8e, 0x0e, 0x81, 0x89, 0x11, 0x80, 0x8f, - 0x00, 0x9d, 0x9c, 0xd8, 0x8a, 0x80, 0x97, 0xa0, 0x88, 0x0b, 0x04, 0x95, - 0x18, 0x88, 0x02, 0x80, 0x96, 0x98, 0x86, 0x8a, 0xb4, 0x94, 0x07, 0xc5, - 0xb5, 0x10, 0x91, 0x06, 0x89, 0x8e, 0x8f, 0x1f, 0x09, 0x81, 0x95, 0x06, - 0x00, 0x13, 0x10, 0x8f, 0x80, 0x8c, 0x08, 0x82, 0x8d, 0x81, 0x89, 0x07, - 0x2b, 0x09, 0x95, 0x06, 0x01, 0x01, 0x01, 0x9e, 0x18, 0x80, 0x92, 0x82, - 0x8f, 0x88, 0x02, 0x80, 0x95, 0x06, 0x01, 0x04, 0x10, 0x91, 0x80, 0x8e, - 0x81, 0x96, 0x80, 0x8a, 0x39, 0x09, 0x95, 0x06, 0x01, 0x04, 0x10, 0x9d, - 0x08, 0x82, 0x8e, 0x80, 0x90, 0x00, 0x2a, 0x10, 0x1a, 0x08, 0x00, 0x0a, - 0x0a, 0x12, 0x8b, 0x95, 0x80, 0xb3, 0x38, 0x10, 0x96, 0x80, 0x8f, 0x10, - 0x99, 0x14, 0x81, 0x9d, 0x03, 0x38, 0x10, 0x96, 0x80, 0x89, 0x04, 0x10, - 0x9f, 0x00, 0x81, 0x8e, 0x81, 0x91, 0x38, 0x10, 0xa8, 0x08, 0x8f, 0x04, - 0x17, 0x82, 0x97, 0x2c, 0x91, 0x82, 0x97, 0x80, 0x88, 0x00, 0x0e, 0xb9, - 0xaf, 0x01, 0x8b, 0x86, 0xb9, 0x08, 0x00, 0x20, 0x97, 0x00, 0x80, 0x89, - 0x01, 0x88, 0x01, 0x20, 0x80, 0x94, 0x83, 0x9f, 0x80, 0xbe, 0x38, 0xa3, - 0x9a, 0x84, 0xf2, 0xaa, 0x93, 0x80, 0x8f, 0x2b, 0x1a, 0x02, 0x0e, 0x13, - 0x8c, 0x8b, 0x80, 0x90, 0xa5, 0x00, 0x20, 0x81, 0xaa, 0x80, 0x41, 0x4c, - 0x03, 0x0e, 0x00, 0x03, 0x81, 0xa8, 0x03, 0x81, 0xa0, 0x03, 0x0e, 0x00, - 0x03, 0x81, 0x8e, 0x80, 0xb8, 0x03, 0x81, 0xc2, 0xa4, 0x8f, 0x8f, 0xd5, - 0x0d, 0x82, 0x42, 0x6b, 0x81, 0x90, 0x80, 0x99, 0x84, 0xca, 0x82, 0x8a, - 0x86, 0x8c, 0x03, 0x8d, 0x91, 0x8d, 0x91, 0x8d, 0x8c, 0x02, 0x8e, 0xb3, - 0xa2, 0x03, 0x80, 0xc2, 0xd8, 0x86, 0xa8, 0x00, 0x84, 0xc5, 0x89, 0x9e, - 0xb0, 0x9d, 0x0c, 0x8a, 0xab, 0x83, 0x99, 0xb5, 0x96, 0x88, 0xb4, 0xd1, - 0x80, 0xdc, 0xae, 0x90, 0x86, 0xb6, 0x9d, 0x8c, 0x81, 0x89, 0xab, 0x99, - 0xa3, 0xa8, 0x82, 0x89, 0xa3, 0x81, 0x88, 0x86, 0xaa, 0x0a, 0xa8, 0x18, - 0x28, 0x0a, 0x04, 0x40, 0xbf, 0xbf, 0x41, 0x15, 0x0d, 0x81, 0xa5, 0x0d, - 0x0f, 0x00, 0x00, 0x00, 0x80, 0x9e, 0x81, 0xb4, 0x06, 0x00, 0x12, 0x06, - 0x13, 0x0d, 0x83, 0x8c, 0x22, 0x06, 0xf3, 0x80, 0x8c, 0x80, 0x8f, 0x8c, - 0xe4, 0x03, 0x01, 0x89, 0x00, 0x0d, 0x28, 0x00, 0x00, 0x80, 0x8f, 0x0b, - 0x24, 0x18, 0x90, 0xa8, 0x4a, 0x76, 0xae, 0x80, 0xae, 0x80, 0x40, 0x84, - 0x2b, 0x11, 0x8b, 0xa5, 0x00, 0x20, 0x81, 0xb7, 0x30, 0x8f, 0x96, 0x88, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x86, 0x42, 0x25, 0x82, 0x98, - 0x88, 0x34, 0x0c, 0x83, 0xd5, 0x1c, 0x80, 0xd9, 0x03, 0x84, 0xaa, 0x80, - 0xdd, 0x90, 0x9a, 0xb4, 0x8f, 0x41, 0xff, 0x59, 0xb5, 0xc9, 0x60, 0x51, - 0xef, 0x8f, 0x44, 0x8c, 0xc2, 0xad, 0x81, 0x41, 0x0c, 0x82, 0x8f, 0x89, - 0x81, 0x93, 0xae, 0x8f, 0x9e, 0x81, 0xcf, 0xa6, 0x88, 0x81, 0xe6, 0x81, - 0xb4, 0x0c, 0xaf, 0x8a, 0x02, 0x03, 0x80, 0x96, 0x9c, 0xb3, 0x8d, 0xb1, - 0xbd, 0x2a, 0x00, 0x81, 0x8a, 0x9b, 0x89, 0x96, 0x98, 0x9c, 0x86, 0xae, - 0x9b, 0x80, 0x8f, 0x20, 0x89, 0x89, 0x20, 0xa8, 0x96, 0x10, 0x87, 0x93, - 0x96, 0x10, 0x82, 0xb1, 0x00, 0x11, 0x0c, 0x08, 0x00, 0x97, 0x11, 0x8a, - 0x32, 0x8b, 0x29, 0x29, 0x85, 0x88, 0x30, 0x30, 0xaa, 0x80, 0x8b, 0x87, - 0xf2, 0x9c, 0x60, 0x2b, 0xa3, 0x8b, 0x96, 0x83, 0xb0, 0x60, 0x21, 0x03, - 0x41, 0x6d, 0x81, 0xe9, 0xa5, 0x86, 0x8b, 0x24, 0x00, 0x89, 0x80, 0x8c, - 0x04, 0x00, 0x01, 0x01, 0x80, 0xeb, 0xa0, 0x41, 0x6a, 0x91, 0xbf, 0x81, - 0xb5, 0xa7, 0x8b, 0xf3, 0x20, 0x40, 0x86, 0xa3, 0x99, 0x85, 0x99, 0x8a, - 0xd8, 0x15, 0x0d, 0x0d, 0x0a, 0xa2, 0x8b, 0x80, 0x99, 0x80, 0x92, 0x01, - 0x80, 0x8e, 0x81, 0x8d, 0xa1, 0xfa, 0xc4, 0xb4, 0x41, 0x0a, 0x9c, 0x82, - 0xb0, 0xae, 0x9f, 0x8c, 0x9d, 0x84, 0xa5, 0x89, 0x9d, 0x81, 0xa3, 0x1f, - 0x04, 0xa9, 0x40, 0x9d, 0x91, 0xa3, 0x83, 0xa3, 0x83, 0xa7, 0x87, 0xb3, - 0x40, 0x9b, 0x41, 0x36, 0x88, 0x95, 0x89, 0x87, 0x40, 0x97, 0x29, 0x00, - 0xab, 0x01, 0x10, 0x81, 0x96, 0x89, 0x96, 0x88, 0x9e, 0xc0, 0x92, 0x01, - 0x89, 0x95, 0x89, 0x99, 0xc5, 0xb7, 0x29, 0xbf, 0x80, 0x8e, 0x18, 0x10, - 0x9c, 0xa9, 0x9c, 0x82, 0x9c, 0xa2, 0x38, 0x9b, 0x9a, 0xb5, 0x89, 0x95, - 0x89, 0x92, 0x8c, 0x91, 0xed, 0xc8, 0xb6, 0xb2, 0x8c, 0xb2, 0x8c, 0xa3, - 0x41, 0xdb, 0x9c, 0x89, 0x07, 0x95, 0x40, 0x99, 0x96, 0x8b, 0xb4, 0xca, - 0xac, 0x9f, 0x98, 0x99, 0xa3, 0x9c, 0x80, 0x8a, 0xa2, 0x10, 0x8b, 0xaf, - 0x8d, 0x83, 0x94, 0x00, 0x80, 0xa2, 0x91, 0x80, 0x98, 0xd3, 0x30, 0x00, - 0x18, 0x8e, 0x80, 0x89, 0x86, 0xae, 0xa5, 0x39, 0x09, 0x95, 0x06, 0x01, - 0x04, 0x10, 0x91, 0x80, 0x8b, 0x84, 0x40, 0x9d, 0xb4, 0x91, 0x83, 0x93, - 0x80, 0x9f, 0xaf, 0x93, 0x08, 0x80, 0x40, 0xb7, 0xae, 0xa8, 0x83, 0xa3, - 0xaf, 0x93, 0x80, 0xba, 0xaa, 0x8c, 0x80, 0xc6, 0x9a, 0x40, 0xe4, 0xab, - 0xf3, 0xbf, 0x9e, 0x80, 0x40, 0x9f, 0x39, 0xa6, 0x8f, 0x00, 0x80, 0x9b, - 0x80, 0x89, 0xa7, 0x30, 0x94, 0x80, 0x8a, 0xad, 0x92, 0x80, 0xa1, 0xb8, - 0x41, 0x06, 0x88, 0x80, 0xa4, 0x90, 0x80, 0xb0, 0x9d, 0xef, 0x30, 0x08, - 0xa5, 0x94, 0x80, 0x98, 0x28, 0x08, 0x9f, 0x8d, 0x80, 0x41, 0x46, 0x92, - 0x41, 0x0c, 0x43, 0x99, 0xe5, 0xee, 0x90, 0x40, 0xc3, 0x4a, 0xbb, 0x44, - 0x2e, 0x4f, 0xd0, 0x42, 0x46, 0x60, 0x21, 0xb8, 0x42, 0x38, 0x86, 0x9e, - 0xf0, 0x9d, 0x91, 0xaf, 0x8f, 0x83, 0x9e, 0x94, 0x84, 0x92, 0x42, 0xaf, - 0xbf, 0xff, 0xca, 0x20, 0xc1, 0x8c, 0xbf, 0x08, 0x80, 0x9b, 0x57, 0xf7, - 0x87, 0x42, 0xf2, 0x60, 0x25, 0x0c, 0x41, 0x1e, 0xb0, 0x82, 0x90, 0x1f, - 0x41, 0x8b, 0x49, 0x03, 0xea, 0x84, 0x8c, 0x82, 0x88, 0x86, 0x89, 0x57, - 0x65, 0xd4, 0x80, 0xc6, 0x01, 0x08, 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, - 0x80, 0xc0, 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, 0x16, 0x80, - 0x41, 0x53, 0x81, 0x98, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, - 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x07, 0x49, - 0x33, 0xac, 0x89, 0x86, 0x8f, 0x80, 0x41, 0x70, 0xab, 0x45, 0x13, 0x40, - 0xc4, 0xba, 0xc3, 0x30, 0x44, 0xb3, 0x18, 0x9a, 0x01, 0x00, 0x08, 0x80, - 0x89, 0x03, 0x00, 0x00, 0x28, 0x18, 0x00, 0x00, 0x02, 0x01, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00, 0x80, - 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, 0x51, 0x43, 0x60, 0xa6, 0xd6, - 0xa8, 0x50, 0x34, 0x8a, 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, - 0x4c, 0x1e, 0x42, 0x1d, -}; - -static const uint8_t unicode_prop_ID_Start_index[96] = { - 0xf6, 0x03, 0x20, 0xa6, 0x07, 0x00, 0xb1, 0x09, 0x00, 0xba, 0x0a, 0x00, - 0xd1, 0x0b, 0x20, 0x62, 0x0d, 0x40, 0x01, 0x0f, 0x20, 0x5e, 0x12, 0x00, - 0xf9, 0x16, 0x00, 0x17, 0x1a, 0x20, 0xc0, 0x1d, 0x20, 0x9d, 0x20, 0x00, - 0x68, 0x2d, 0x00, 0x00, 0x32, 0x20, 0xc0, 0xa7, 0x20, 0x29, 0xaa, 0x00, - 0xa4, 0xd7, 0x20, 0xc8, 0xfd, 0x20, 0x75, 0x01, 0x01, 0x37, 0x07, 0x01, - 0x36, 0x0a, 0x21, 0xf7, 0x0f, 0x21, 0xa9, 0x12, 0x01, 0x30, 0x16, 0x21, - 0x8a, 0x1a, 0x01, 0x9a, 0x23, 0x01, 0x80, 0x6e, 0x21, 0x89, 0xbc, 0x21, - 0xc1, 0xd6, 0x01, 0xc5, 0xe8, 0x21, 0x73, 0xee, 0x01, 0x1e, 0xfa, 0x02, -}; - -static const uint8_t unicode_prop_ID_Continue1_table[607] = { - 0xaf, 0x89, 0xa4, 0x80, 0xd6, 0x80, 0x42, 0x47, 0xef, 0x96, 0x80, 0x40, - 0xfa, 0x84, 0x41, 0x08, 0xac, 0x00, 0x01, 0x01, 0x00, 0xc7, 0x8a, 0xaf, - 0x9e, 0x28, 0xe4, 0x31, 0x29, 0x08, 0x19, 0x89, 0x96, 0x80, 0x9d, 0x9a, - 0xda, 0x8a, 0x8e, 0x89, 0xa0, 0x88, 0x88, 0x80, 0x97, 0x18, 0x88, 0x02, - 0x04, 0xaa, 0x82, 0xf6, 0x8e, 0x80, 0xa0, 0xb5, 0x10, 0x91, 0x06, 0x89, - 0x09, 0x89, 0x90, 0x82, 0xb7, 0x00, 0x31, 0x09, 0x82, 0x88, 0x80, 0x89, - 0x09, 0x89, 0x8d, 0x01, 0x82, 0xb7, 0x00, 0x23, 0x09, 0x12, 0x80, 0x93, - 0x8b, 0x10, 0x8a, 0x82, 0xb7, 0x00, 0x38, 0x10, 0x82, 0x93, 0x09, 0x89, - 0x89, 0x28, 0x82, 0xb7, 0x00, 0x31, 0x09, 0x17, 0x81, 0x89, 0x09, 0x89, - 0x91, 0x80, 0xba, 0x22, 0x10, 0x83, 0x88, 0x80, 0x8d, 0x89, 0x8f, 0x84, - 0xb8, 0x30, 0x10, 0x1e, 0x81, 0x8a, 0x09, 0x89, 0x90, 0x82, 0xb7, 0x00, - 0x30, 0x10, 0x1e, 0x81, 0x8a, 0x09, 0x89, 0x8f, 0x83, 0xb6, 0x08, 0x30, - 0x10, 0x83, 0x88, 0x80, 0x89, 0x09, 0x89, 0x91, 0x81, 0xc5, 0x03, 0x28, - 0x00, 0x3d, 0x89, 0x09, 0xbc, 0x01, 0x86, 0x8b, 0x38, 0x89, 0xd6, 0x01, - 0x88, 0x8a, 0x29, 0x89, 0xbd, 0x0d, 0x89, 0x8a, 0x00, 0x00, 0x03, 0x81, - 0xb0, 0x93, 0x01, 0x84, 0x8a, 0x80, 0xa3, 0x88, 0x80, 0xe3, 0x93, 0x80, - 0x89, 0x8b, 0x1b, 0x10, 0x11, 0x32, 0x83, 0x8c, 0x8b, 0x80, 0x8e, 0x42, - 0xbe, 0x82, 0x88, 0x88, 0x43, 0x9f, 0x82, 0x9c, 0x82, 0x9c, 0x81, 0x9d, - 0x81, 0xbf, 0x9f, 0x88, 0x01, 0x89, 0xa0, 0x11, 0x89, 0x40, 0x8e, 0x80, - 0xf5, 0x8b, 0x83, 0x8b, 0x89, 0x89, 0xff, 0x8a, 0xbb, 0x84, 0xb8, 0x89, - 0x80, 0x9c, 0x81, 0x8a, 0x85, 0x89, 0x95, 0x8d, 0xc1, 0x84, 0xae, 0x90, - 0x8a, 0x89, 0x90, 0x88, 0x8b, 0x82, 0x9d, 0x8c, 0x81, 0x89, 0xab, 0x8d, - 0xaf, 0x93, 0x87, 0x89, 0x85, 0x89, 0xf5, 0x10, 0x94, 0x18, 0x28, 0x0a, - 0x40, 0xc5, 0xb9, 0x04, 0x42, 0x3e, 0x81, 0x92, 0x80, 0xfa, 0x8c, 0x18, - 0x82, 0x8b, 0x4b, 0xfd, 0x82, 0x40, 0x8c, 0x80, 0xdf, 0x9f, 0x42, 0x29, - 0x85, 0xe8, 0x81, 0x60, 0x75, 0x84, 0x89, 0xc4, 0x03, 0x89, 0x9f, 0x81, - 0xcf, 0x81, 0x41, 0x0f, 0x02, 0x03, 0x80, 0x96, 0x84, 0xd7, 0x81, 0xb1, - 0x91, 0x89, 0x89, 0x85, 0x91, 0x8c, 0x8a, 0x9b, 0x87, 0x98, 0x8c, 0xab, - 0x83, 0xae, 0x8d, 0x8e, 0x89, 0x8a, 0x80, 0x89, 0x89, 0xae, 0x8d, 0x8b, - 0x07, 0x09, 0x89, 0xa0, 0x82, 0xb1, 0x00, 0x11, 0x0c, 0x08, 0x80, 0xa8, - 0x24, 0x81, 0x40, 0xeb, 0x38, 0x09, 0x89, 0x60, 0x4f, 0x23, 0x80, 0x42, - 0xe0, 0x8f, 0x8f, 0x8f, 0x11, 0x97, 0x82, 0x40, 0xbf, 0x89, 0xa4, 0x80, - 0x42, 0xbc, 0x80, 0x40, 0xe1, 0x80, 0x40, 0x94, 0x84, 0x41, 0x24, 0x89, - 0x45, 0x56, 0x10, 0x0c, 0x83, 0xa7, 0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, - 0x3c, 0x1f, 0x89, 0x42, 0x0b, 0x8a, 0x40, 0xae, 0x82, 0xb4, 0x8e, 0x9e, - 0x89, 0x8e, 0x83, 0xac, 0x8a, 0xb4, 0x89, 0x2a, 0xa3, 0x8d, 0x80, 0x89, - 0x21, 0xab, 0x80, 0x8b, 0x82, 0xaf, 0x8d, 0x3b, 0x82, 0x89, 0xd1, 0x8b, - 0x28, 0x40, 0x9f, 0x8b, 0x84, 0x89, 0x2b, 0xb6, 0x08, 0x31, 0x09, 0x82, - 0x88, 0x80, 0x89, 0x09, 0x32, 0x84, 0x40, 0xbf, 0x91, 0x88, 0x89, 0x18, - 0xd0, 0x93, 0x8b, 0x89, 0x40, 0xd4, 0x31, 0x88, 0x9a, 0x81, 0xd1, 0x90, - 0x8e, 0x89, 0xd0, 0x8c, 0x87, 0x89, 0xd2, 0x8e, 0x83, 0x89, 0x40, 0xf1, - 0x8e, 0x40, 0xa4, 0x89, 0x40, 0xe6, 0x31, 0x32, 0x80, 0x9b, 0x89, 0xa7, - 0x30, 0x1f, 0x80, 0x88, 0x8a, 0xad, 0x8f, 0x41, 0x94, 0x38, 0x87, 0x8f, - 0x89, 0xb7, 0x95, 0x80, 0x8d, 0xf9, 0x2a, 0x00, 0x08, 0x30, 0x07, 0x89, - 0xaf, 0x20, 0x08, 0x27, 0x89, 0x41, 0x48, 0x83, 0x60, 0x4b, 0x68, 0x89, - 0x40, 0x85, 0x84, 0xba, 0x86, 0x98, 0x89, 0x43, 0xf4, 0x00, 0xb6, 0x33, - 0x60, 0x4d, 0x09, 0x81, 0x54, 0xc5, 0x22, 0x2f, 0x39, 0x86, 0x9d, 0x83, - 0x40, 0x93, 0x82, 0x45, 0x88, 0xb1, 0x41, 0xff, 0xb6, 0x83, 0xb1, 0x38, - 0x8d, 0x80, 0x95, 0x20, 0x8e, 0x45, 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04, - 0x41, 0x04, 0x86, 0x88, 0x89, 0x41, 0xa1, 0x8d, 0x45, 0xd5, 0x86, 0xec, - 0x34, 0x89, 0x6c, 0x17, 0xa5, 0x40, 0xef, -}; - -static const uint8_t unicode_prop_ID_Continue1_index[57] = { - 0xfa, 0x06, 0x00, 0x84, 0x09, 0x00, 0xf0, 0x0a, 0x00, 0x70, 0x0c, 0x00, - 0xf4, 0x0d, 0x00, 0x4a, 0x10, 0x20, 0x1a, 0x18, 0x20, 0x74, 0x1b, 0x00, - 0xe2, 0x20, 0x00, 0x28, 0xa8, 0x20, 0x7e, 0xaa, 0x20, 0x40, 0xff, 0x00, - 0x03, 0x10, 0x21, 0xeb, 0x12, 0x01, 0x41, 0x16, 0x01, 0x40, 0x1c, 0x61, - 0x37, 0x6b, 0x21, 0x76, 0xda, 0x01, 0xf0, 0x01, 0x0e, -}; - -#ifdef CONFIG_ALL_UNICODE - -static const uint8_t unicode_cc_table[831] = { - 0xb2, 0xcf, 0xd4, 0x00, 0xe8, 0x03, 0xdc, 0x00, 0xe8, 0x00, 0xd8, 0x04, - 0xdc, 0x01, 0xca, 0x03, 0xdc, 0x01, 0xca, 0x0a, 0xdc, 0x04, 0x01, 0x03, - 0xdc, 0xc7, 0x00, 0xf0, 0xc0, 0x02, 0xdc, 0xc2, 0x01, 0xdc, 0x80, 0xc2, - 0x03, 0xdc, 0xc0, 0x00, 0xe8, 0x01, 0xdc, 0xc0, 0x41, 0xe9, 0x00, 0xea, - 0x41, 0xe9, 0x00, 0xea, 0x00, 0xe9, 0xcc, 0xb0, 0xe2, 0xc4, 0xb0, 0xd8, - 0x00, 0xdc, 0xc3, 0x00, 0xdc, 0xc2, 0x00, 0xde, 0x00, 0xdc, 0xc5, 0x05, - 0xdc, 0xc1, 0x00, 0xdc, 0xc1, 0x00, 0xde, 0x00, 0xe4, 0xc0, 0x49, 0x0a, - 0x43, 0x13, 0x80, 0x00, 0x17, 0x80, 0x41, 0x18, 0x80, 0xc0, 0x00, 0xdc, - 0x80, 0x00, 0x12, 0xb0, 0x17, 0xc7, 0x42, 0x1e, 0xaf, 0x47, 0x1b, 0xc1, - 0x01, 0xdc, 0xc4, 0x00, 0xdc, 0xc1, 0x00, 0xdc, 0x8f, 0x00, 0x23, 0xb0, - 0x34, 0xc6, 0x81, 0xc3, 0x00, 0xdc, 0xc0, 0x81, 0xc1, 0x80, 0x00, 0xdc, - 0xc1, 0x00, 0xdc, 0xa2, 0x00, 0x24, 0x9d, 0xc0, 0x00, 0xdc, 0xc1, 0x00, - 0xdc, 0xc1, 0x02, 0xdc, 0xc0, 0x01, 0xdc, 0xc0, 0x00, 0xdc, 0xc2, 0x00, - 0xdc, 0xc0, 0x00, 0xdc, 0xc0, 0x00, 0xdc, 0xc0, 0x00, 0xdc, 0xc1, 0xb0, - 0x6f, 0xc6, 0x00, 0xdc, 0xc0, 0x88, 0x00, 0xdc, 0x97, 0xc3, 0x80, 0xc8, - 0x80, 0xc2, 0x80, 0xc4, 0xaa, 0x02, 0xdc, 0xb0, 0x46, 0x00, 0xdc, 0xcd, - 0x80, 0x00, 0xdc, 0xc1, 0x00, 0xdc, 0xc1, 0x00, 0xdc, 0xc2, 0x02, 0xdc, - 0x42, 0x1b, 0xc2, 0x00, 0xdc, 0xc1, 0x01, 0xdc, 0xc4, 0xb0, 0x0b, 0x00, - 0x07, 0x8f, 0x00, 0x09, 0x82, 0xc0, 0x00, 0xdc, 0xc1, 0xb0, 0x36, 0x00, - 0x07, 0x8f, 0x00, 0x09, 0xaf, 0xc0, 0xb0, 0x0c, 0x00, 0x07, 0x8f, 0x00, - 0x09, 0xb0, 0x3d, 0x00, 0x07, 0x8f, 0x00, 0x09, 0xb0, 0x3d, 0x00, 0x07, - 0x8f, 0x00, 0x09, 0xb0, 0x4e, 0x00, 0x09, 0xb0, 0x4e, 0x00, 0x09, 0x86, - 0x00, 0x54, 0x00, 0x5b, 0xb0, 0x34, 0x00, 0x07, 0x8f, 0x00, 0x09, 0xb0, - 0x3c, 0x01, 0x09, 0x8f, 0x00, 0x09, 0xb0, 0x4b, 0x00, 0x09, 0xb0, 0x3c, - 0x01, 0x67, 0x00, 0x09, 0x8c, 0x03, 0x6b, 0xb0, 0x3b, 0x01, 0x76, 0x00, - 0x09, 0x8c, 0x03, 0x7a, 0xb0, 0x1b, 0x01, 0xdc, 0x9a, 0x00, 0xdc, 0x80, - 0x00, 0xdc, 0x80, 0x00, 0xd8, 0xb0, 0x06, 0x41, 0x81, 0x80, 0x00, 0x84, - 0x84, 0x03, 0x82, 0x81, 0x00, 0x82, 0x80, 0xc1, 0x00, 0x09, 0x80, 0xc1, - 0xb0, 0x0d, 0x00, 0xdc, 0xb0, 0x3f, 0x00, 0x07, 0x80, 0x01, 0x09, 0xb0, - 0x21, 0x00, 0xdc, 0xb2, 0x9e, 0xc2, 0xb3, 0x83, 0x00, 0x09, 0x9e, 0x00, - 0x09, 0xb0, 0x6c, 0x00, 0x09, 0x89, 0xc0, 0xb0, 0x9a, 0x00, 0xe4, 0xb0, - 0x5e, 0x00, 0xde, 0xc0, 0x00, 0xdc, 0xb0, 0xaa, 0xc0, 0x00, 0xdc, 0xb0, - 0x16, 0x00, 0x09, 0x93, 0xc7, 0x81, 0x00, 0xdc, 0xaf, 0xc4, 0x05, 0xdc, - 0xc1, 0x00, 0xdc, 0xb0, 0x45, 0x00, 0x07, 0x8e, 0x00, 0x09, 0xa5, 0xc0, - 0x00, 0xdc, 0xc6, 0xb0, 0x05, 0x01, 0x09, 0xb0, 0x09, 0x00, 0x07, 0x8a, - 0x01, 0x09, 0xb0, 0x12, 0x00, 0x07, 0xb0, 0x67, 0xc2, 0x41, 0x00, 0x04, - 0xdc, 0xc1, 0x03, 0xdc, 0xc0, 0x41, 0x00, 0x05, 0x01, 0x83, 0x00, 0xdc, - 0x85, 0xc0, 0x82, 0xc1, 0xb0, 0x95, 0xc1, 0x00, 0xdc, 0xc6, 0x00, 0xdc, - 0xc1, 0x00, 0xea, 0x00, 0xd6, 0x00, 0xdc, 0x00, 0xca, 0xe4, 0x00, 0xe8, - 0x01, 0xe4, 0x00, 0xdc, 0x80, 0xc0, 0x00, 0xe9, 0x00, 0xdc, 0xc0, 0x00, - 0xdc, 0xb2, 0x9f, 0xc1, 0x01, 0x01, 0xc3, 0x02, 0x01, 0xc1, 0x83, 0xc0, - 0x82, 0x01, 0x01, 0xc0, 0x00, 0xdc, 0xc0, 0x01, 0x01, 0x03, 0xdc, 0xc0, - 0xb8, 0x03, 0xcd, 0xc2, 0xb0, 0x5c, 0x00, 0x09, 0xb0, 0x2f, 0xdf, 0xb1, - 0xf9, 0x00, 0xda, 0x00, 0xe4, 0x00, 0xe8, 0x00, 0xde, 0x01, 0xe0, 0xb0, - 0x38, 0x01, 0x08, 0xb8, 0x6d, 0xa3, 0xc0, 0x83, 0xc9, 0x9f, 0xc1, 0xb0, - 0x1f, 0xc1, 0xb0, 0xe3, 0x00, 0x09, 0xb0, 0x8c, 0x00, 0x09, 0x9a, 0xd1, - 0xb0, 0x08, 0x02, 0xdc, 0xa4, 0x00, 0x09, 0xb0, 0x2e, 0x00, 0x07, 0x8b, - 0x00, 0x09, 0xb0, 0xbe, 0xc0, 0x80, 0xc1, 0x00, 0xdc, 0x81, 0xc1, 0x84, - 0xc1, 0x80, 0xc0, 0xb0, 0x03, 0x00, 0x09, 0xb0, 0xc5, 0x00, 0x09, 0xb8, - 0x46, 0xff, 0x00, 0x1a, 0xb2, 0xd0, 0xc6, 0x06, 0xdc, 0xc1, 0xb3, 0x9c, - 0x00, 0xdc, 0xb0, 0xb1, 0x00, 0xdc, 0xb0, 0x64, 0xc4, 0xb6, 0x61, 0x00, - 0xdc, 0x80, 0xc0, 0xa7, 0xc0, 0x00, 0x01, 0x00, 0xdc, 0x83, 0x00, 0x09, - 0xb0, 0x74, 0xc0, 0x00, 0xdc, 0xb2, 0x0c, 0xc3, 0xb1, 0xed, 0x01, 0xdc, - 0xc2, 0x00, 0xdc, 0xc0, 0x03, 0xdc, 0xb0, 0xc4, 0x00, 0x09, 0xb0, 0x07, - 0x00, 0x09, 0xb0, 0x08, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x14, 0xc2, 0xaf, - 0x01, 0x09, 0xb0, 0x0d, 0x00, 0x07, 0xb0, 0x1b, 0x00, 0x09, 0x88, 0x00, - 0x07, 0xb0, 0x39, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x81, 0x00, 0x07, 0x00, - 0x09, 0xb0, 0x1f, 0x01, 0x07, 0x8f, 0x00, 0x09, 0x97, 0xc6, 0x82, 0xc4, - 0xb0, 0x9c, 0x00, 0x09, 0x82, 0x00, 0x07, 0x96, 0xc0, 0xb0, 0x32, 0x00, - 0x09, 0x00, 0x07, 0xb0, 0xca, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x4d, 0x00, - 0x09, 0xb0, 0x45, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x42, 0x00, 0x09, 0xb0, - 0xdc, 0x00, 0x09, 0x00, 0x07, 0xb1, 0x74, 0x00, 0x09, 0xb0, 0x22, 0x00, - 0x09, 0x91, 0x00, 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb1, 0x74, 0x00, 0x09, - 0xb0, 0xd1, 0x00, 0x07, 0x80, 0x01, 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb8, - 0x45, 0x27, 0x04, 0x01, 0xb0, 0x0a, 0xc6, 0xb8, 0x49, 0x36, 0x00, 0x01, - 0xb8, 0x0c, 0x95, 0x01, 0xd8, 0x02, 0x01, 0x82, 0x00, 0xe2, 0x04, 0xd8, - 0x87, 0x07, 0xdc, 0x81, 0xc4, 0x01, 0xdc, 0x9d, 0xc3, 0xb0, 0x63, 0xc2, - 0xb8, 0x05, 0x8a, 0xc6, 0x80, 0xd0, 0x81, 0xc6, 0x80, 0xc1, 0x80, 0xc4, - 0xb0, 0xd4, 0xc6, 0xb1, 0x84, 0xc3, 0xb5, 0xaf, 0x06, 0xdc, 0xb0, 0x3c, - 0xc5, 0x00, 0x07, -}; - -static const uint8_t unicode_cc_index[78] = { - 0x4d, 0x03, 0x00, 0x97, 0x05, 0x20, 0xc6, 0x05, 0x00, 0xe7, 0x06, 0x00, - 0x45, 0x07, 0x00, 0xe2, 0x08, 0x00, 0x53, 0x09, 0x00, 0xcd, 0x0b, 0x20, - 0x38, 0x0e, 0x00, 0x73, 0x0f, 0x20, 0x5d, 0x13, 0x20, 0x60, 0x1a, 0x20, - 0xe6, 0x1b, 0x20, 0xfa, 0x1c, 0x00, 0x00, 0x1e, 0x20, 0x80, 0x2d, 0x00, - 0x06, 0xa8, 0x00, 0xbe, 0xaa, 0x00, 0x76, 0x03, 0x01, 0x4d, 0x0f, 0x01, - 0xcb, 0x11, 0x21, 0x5e, 0x14, 0x01, 0x3b, 0x18, 0x21, 0xf0, 0x6a, 0x41, - 0xaa, 0xd1, 0x01, 0x4b, 0xe9, 0x01, -}; - -static const uint32_t unicode_decomp_table1[687] = { - 0x00280081, 0x002a0097, 0x002a8081, 0x002bc097, 0x002c8115, 0x002d0097, - 0x002d4081, 0x002e0097, 0x002e4115, 0x002f0199, 0x00302016, 0x00400842, - 0x00448a42, 0x004a0442, 0x004c0096, 0x004c8117, 0x004d0242, 0x004e4342, - 0x004fc12f, 0x0050c342, 0x005240bf, 0x00530342, 0x00550942, 0x005a0842, - 0x005e0096, 0x005e4342, 0x005fc081, 0x00680142, 0x006bc142, 0x00710185, - 0x0071c317, 0x00734844, 0x00778344, 0x00798342, 0x007b02be, 0x007c4197, - 0x007d0142, 0x007e0444, 0x00800e42, 0x00878142, 0x00898744, 0x00ac0483, - 0x00b60317, 0x00b80283, 0x00d00214, 0x00d10096, 0x00dd0080, 0x00de8097, - 0x00df8080, 0x00e10097, 0x00e1413e, 0x00e1c080, 0x00e204be, 0x00ea83ae, - 0x00f282ae, 0x00f401ad, 0x00f4c12e, 0x00f54103, 0x00fc0303, 0x00fe4081, - 0x0100023e, 0x0101c0be, 0x010301be, 0x010640be, 0x010e40be, 0x0114023e, - 0x0115c0be, 0x011701be, 0x011d8144, 0x01304144, 0x01340244, 0x01358144, - 0x01368344, 0x01388344, 0x013a8644, 0x013e0144, 0x0161c085, 0x018882ae, - 0x019d422f, 0x01b00184, 0x01b4c084, 0x024a4084, 0x024c4084, 0x024d0084, - 0x0256042e, 0x0272c12e, 0x02770120, 0x0277c084, 0x028cc084, 0x028d8084, - 0x029641ae, 0x02978084, 0x02d20084, 0x02d2c12e, 0x02d70120, 0x02e50084, - 0x02f281ae, 0x03120084, 0x03300084, 0x0331c122, 0x0332812e, 0x035281ae, - 0x03768084, 0x037701ae, 0x038cc085, 0x03acc085, 0x03b7012f, 0x03c30081, - 0x03d0c084, 0x03d34084, 0x03d48084, 0x03d5c084, 0x03d70084, 0x03da4084, - 0x03dcc084, 0x03dd412e, 0x03ddc085, 0x03de0084, 0x03de4085, 0x03e04084, - 0x03e4c084, 0x03e74084, 0x03e88084, 0x03e9c084, 0x03eb0084, 0x03ee4084, - 0x04098084, 0x043f0081, 0x06c18484, 0x06c48084, 0x06cec184, 0x06d00120, - 0x06d0c084, 0x074b0383, 0x074cc41f, 0x074f1783, 0x075e0081, 0x0766d283, - 0x07801d44, 0x078e8942, 0x07931844, 0x079f0d42, 0x07a58216, 0x07a68085, - 0x07a6c0be, 0x07a80d44, 0x07aea044, 0x07c00122, 0x07c08344, 0x07c20122, - 0x07c28344, 0x07c40122, 0x07c48244, 0x07c60122, 0x07c68244, 0x07c8113e, - 0x07d08244, 0x07d20122, 0x07d28244, 0x07d40122, 0x07d48344, 0x07d64c3e, - 0x07dc4080, 0x07dc80be, 0x07dcc080, 0x07dd00be, 0x07dd4080, 0x07dd80be, - 0x07ddc080, 0x07de00be, 0x07de4080, 0x07de80be, 0x07dec080, 0x07df00be, - 0x07df4080, 0x07e00820, 0x07e40820, 0x07e80820, 0x07ec05be, 0x07eec080, - 0x07ef00be, 0x07ef4097, 0x07ef8080, 0x07efc117, 0x07f0443e, 0x07f24080, - 0x07f280be, 0x07f2c080, 0x07f303be, 0x07f4c080, 0x07f582ae, 0x07f6c080, - 0x07f7433e, 0x07f8c080, 0x07f903ae, 0x07fac080, 0x07fb013e, 0x07fb8102, - 0x07fc83be, 0x07fe4080, 0x07fe80be, 0x07fec080, 0x07ff00be, 0x07ff4080, - 0x07ff8097, 0x0800011e, 0x08008495, 0x08044081, 0x0805c097, 0x08090081, - 0x08094097, 0x08098099, 0x080bc081, 0x080cc085, 0x080d00b1, 0x080d8085, - 0x080dc0b1, 0x080f0197, 0x0811c197, 0x0815c0b3, 0x0817c081, 0x081c0595, - 0x081ec081, 0x081f0215, 0x0820051f, 0x08228583, 0x08254415, 0x082a0097, - 0x08400119, 0x08408081, 0x0840c0bf, 0x08414119, 0x0841c081, 0x084240bf, - 0x0842852d, 0x08454081, 0x08458097, 0x08464295, 0x08480097, 0x08484099, - 0x08488097, 0x08490081, 0x08498080, 0x084a0081, 0x084a8102, 0x084b0495, - 0x084d421f, 0x084e4081, 0x084ec099, 0x084f0283, 0x08514295, 0x08540119, - 0x0854809b, 0x0854c619, 0x0857c097, 0x08580081, 0x08584097, 0x08588099, - 0x0858c097, 0x08590081, 0x08594097, 0x08598099, 0x0859c09b, 0x085a0097, - 0x085a4081, 0x085a8097, 0x085ac099, 0x085b0295, 0x085c4097, 0x085c8099, - 0x085cc097, 0x085d0081, 0x085d4097, 0x085d8099, 0x085dc09b, 0x085e0097, - 0x085e4081, 0x085e8097, 0x085ec099, 0x085f0215, 0x08624099, 0x0866813e, - 0x086b80be, 0x087341be, 0x088100be, 0x088240be, 0x088300be, 0x088901be, - 0x088b0085, 0x088b40b1, 0x088bc085, 0x088c00b1, 0x089040be, 0x089100be, - 0x0891c1be, 0x089801be, 0x089b42be, 0x089d0144, 0x089e0144, 0x08a00144, - 0x08a10144, 0x08a20144, 0x08ab023e, 0x08b80244, 0x08ba8220, 0x08ca411e, - 0x0918049f, 0x091a4523, 0x091cc097, 0x091d04a5, 0x091f452b, 0x0921c09b, - 0x092204a1, 0x09244525, 0x0926c099, 0x09270d25, 0x092d8d1f, 0x09340d1f, - 0x093a8081, 0x0a8300b3, 0x0a9d0099, 0x0a9d4097, 0x0a9d8099, 0x0ab700be, - 0x0b1f0115, 0x0b5bc081, 0x0ba7c081, 0x0bbcc081, 0x0bc004ad, 0x0bc244ad, - 0x0bc484ad, 0x0bc6f383, 0x0be0852d, 0x0be31d03, 0x0bf1882d, 0x0c000081, - 0x0c0d8283, 0x0c130b84, 0x0c194284, 0x0c1c0122, 0x0c1cc122, 0x0c1d8122, - 0x0c1e4122, 0x0c1f0122, 0x0c250084, 0x0c26c123, 0x0c278084, 0x0c27c085, - 0x0c2b0b84, 0x0c314284, 0x0c340122, 0x0c34c122, 0x0c358122, 0x0c364122, - 0x0c370122, 0x0c3d0084, 0x0c3dc220, 0x0c3f8084, 0x0c3fc085, 0x0c4c4a2d, - 0x0c51451f, 0x0c53ca9f, 0x0c5915ad, 0x0c648703, 0x0c800741, 0x0c838089, - 0x0c83c129, 0x0c8441a9, 0x0c850089, 0x0c854129, 0x0c85c2a9, 0x0c870089, - 0x0c87408f, 0x0c87808d, 0x0c881241, 0x0c910203, 0x0c940099, 0x0c9444a3, - 0x0c968323, 0x0c98072d, 0x0c9b84af, 0x0c9dc2a1, 0x0c9f00b5, 0x0c9f40b3, - 0x0c9f8085, 0x0ca01883, 0x0cac4223, 0x0cad4523, 0x0cafc097, 0x0cb004a1, - 0x0cb241a5, 0x0cb30097, 0x0cb34099, 0x0cb38097, 0x0cb3c099, 0x0cb417ad, - 0x0cbfc085, 0x0cc001b3, 0x0cc0c0b1, 0x0cc100b3, 0x0cc14131, 0x0cc1c0b5, - 0x0cc200b3, 0x0cc241b1, 0x0cc30133, 0x0cc38131, 0x0cc40085, 0x0cc440b1, - 0x0cc48133, 0x0cc50085, 0x0cc540b5, 0x0cc580b7, 0x0cc5c0b5, 0x0cc600b1, - 0x0cc64135, 0x0cc6c0b3, 0x0cc701b1, 0x0cc7c0b3, 0x0cc800b5, 0x0cc840b3, - 0x0cc881b1, 0x0cc9422f, 0x0cca4131, 0x0ccac0b5, 0x0ccb00b1, 0x0ccb40b3, - 0x0ccb80b5, 0x0ccbc0b1, 0x0ccc012f, 0x0ccc80b5, 0x0cccc0b3, 0x0ccd00b5, - 0x0ccd40b1, 0x0ccd80b5, 0x0ccdc085, 0x0cce02b1, 0x0ccf40b3, 0x0ccf80b1, - 0x0ccfc085, 0x0cd001b1, 0x0cd0c0b3, 0x0cd101b1, 0x0cd1c0b5, 0x0cd200b3, - 0x0cd24085, 0x0cd280b5, 0x0cd2c085, 0x0cd30133, 0x0cd381b1, 0x0cd440b3, - 0x0cd48085, 0x0cd4c0b1, 0x0cd500b3, 0x0cd54085, 0x0cd580b5, 0x0cd5c0b1, - 0x0cd60521, 0x0cd88525, 0x0cdb02a5, 0x0cdc4099, 0x0cdc8117, 0x0cdd0099, - 0x0cdd4197, 0x0cde0127, 0x0cde8285, 0x0cdfc089, 0x0ce0043f, 0x0ce20099, - 0x0ce2409b, 0x0ce283bf, 0x0ce44219, 0x0ce54205, 0x0ce6433f, 0x0ce7c131, - 0x0ce84085, 0x0ce881b1, 0x0ce94085, 0x0ce98107, 0x0cea0089, 0x0cea4097, - 0x0cea8219, 0x0ceb809d, 0x0cebc08d, 0x0cec083f, 0x0cf00105, 0x0cf0809b, - 0x0cf0c197, 0x0cf1809b, 0x0cf1c099, 0x0cf20517, 0x0cf48099, 0x0cf4c117, - 0x0cf54119, 0x0cf5c097, 0x0cf6009b, 0x0cf64099, 0x0cf68217, 0x0cf78119, - 0x0cf804a1, 0x0cfa4525, 0x0cfcc525, 0x0cff4125, 0x0cffc099, 0x29a70103, - 0x29dc0081, 0x29fe0103, 0x2ad70203, 0x3e401482, 0x3e4a7f82, 0x3e6a3f82, - 0x3e8aa102, 0x3e9b0110, 0x3e9c2f82, 0x3eb3c590, 0x3ec00197, 0x3ec0c119, - 0x3ec1413f, 0x3ec4c2af, 0x3ec74184, 0x3ec804ad, 0x3eca4081, 0x3eca8304, - 0x3ecc03a0, 0x3ece02a0, 0x3ecf8084, 0x3ed00120, 0x3ed0c120, 0x3ed184ae, - 0x3ed3c085, 0x3ed4312d, 0x3ef4cbad, 0x3efa892f, 0x3eff022d, 0x3f002f2f, - 0x3f1782a5, 0x3f18c0b1, 0x3f1907af, 0x3f1cffaf, 0x3f3c81a5, 0x3f3d64af, - 0x3f542031, 0x3f649b31, 0x3f7c0131, 0x3f7c83b3, 0x3f7e40b1, 0x3f7e80bd, - 0x3f7ec0bb, 0x3f7f00b3, 0x3f840503, 0x3f8c01ad, 0x3f8cc315, 0x3f8e462d, - 0x3f91cc03, 0x3f97c695, 0x3f9c01af, 0x3f9d0085, 0x3f9d852f, 0x3fa03aad, - 0x3fbd442f, 0x3fc06f1f, 0x3fd7c11f, 0x3fd85fad, 0x3fe80081, 0x3fe84f1f, - 0x3ff0831f, 0x3ff2831f, 0x3ff4831f, 0x3ff6819f, 0x3ff80783, 0x44268192, - 0x442ac092, 0x444b8112, 0x44d2c112, 0x452ec212, 0x456e8112, 0x74578392, - 0x746ec312, 0x75000d1f, 0x75068d1f, 0x750d0d1f, 0x7513839f, 0x7515891f, - 0x751a0d1f, 0x75208d1f, 0x75271015, 0x752f439f, 0x7531459f, 0x75340d1f, - 0x753a8d1f, 0x75410395, 0x7543441f, 0x7545839f, 0x75478d1f, 0x754e0795, - 0x7552839f, 0x75548d1f, 0x755b0d1f, 0x75618d1f, 0x75680d1f, 0x756e8d1f, - 0x75750d1f, 0x757b8d1f, 0x75820d1f, 0x75888d1f, 0x758f0d1f, 0x75958d1f, - 0x759c0d1f, 0x75a28d1f, 0x75a90103, 0x75aa089f, 0x75ae4081, 0x75ae839f, - 0x75b04081, 0x75b08c9f, 0x75b6c081, 0x75b7032d, 0x75b8889f, 0x75bcc081, - 0x75bd039f, 0x75bec081, 0x75bf0c9f, 0x75c54081, 0x75c5832d, 0x75c7089f, - 0x75cb4081, 0x75cb839f, 0x75cd4081, 0x75cd8c9f, 0x75d3c081, 0x75d4032d, - 0x75d5889f, 0x75d9c081, 0x75da039f, 0x75dbc081, 0x75dc0c9f, 0x75e24081, - 0x75e2832d, 0x75e4089f, 0x75e84081, 0x75e8839f, 0x75ea4081, 0x75ea8c9f, - 0x75f0c081, 0x75f1042d, 0x75f3851f, 0x75f6051f, 0x75f8851f, 0x75fb051f, - 0x75fd851f, 0x7b80022d, 0x7b814dad, 0x7b884203, 0x7b89c081, 0x7b8a452d, - 0x7b8d0403, 0x7b908081, 0x7b91dc03, 0x7ba0052d, 0x7ba2c8ad, 0x7ba84483, - 0x7baac8ad, 0x7c400097, 0x7c404521, 0x7c440d25, 0x7c4a8087, 0x7c4ac115, - 0x7c4b4117, 0x7c4c0d1f, 0x7c528217, 0x7c538099, 0x7c53c097, 0x7c5a8197, - 0x7c640097, 0x7c80012f, 0x7c808081, 0x7c841603, 0x7c9004c1, 0x7c940103, - 0xbe0001ac, 0xbe00d110, 0xbe0947ac, 0xbe0d3910, 0xbe29872c, 0xbe2d022c, - 0xbe2e3790, 0xbe49ff90, 0xbe69bc10, -}; - -static const uint16_t unicode_decomp_table2[687] = { - 0x0020, 0x0000, 0x0061, 0x0002, 0x0004, 0x0006, 0x03bc, 0x0008, 0x000a, - 0x000c, 0x0015, 0x0095, 0x00a5, 0x00b9, 0x00c1, 0x00c3, 0x00c7, 0x00cb, - 0x00d1, 0x00d7, 0x00dd, 0x00e0, 0x00e6, 0x00f8, 0x0108, 0x010a, 0x0073, - 0x0110, 0x0112, 0x0114, 0x0120, 0x012c, 0x0144, 0x014d, 0x0153, 0x0162, - 0x0168, 0x016a, 0x0176, 0x0192, 0x0194, 0x01a9, 0x01bb, 0x01c7, 0x01d1, - 0x01d5, 0x02b9, 0x01d7, 0x003b, 0x01d9, 0x01db, 0x00b7, 0x01e1, 0x01fc, - 0x020c, 0x0218, 0x021d, 0x0223, 0x0227, 0x03a3, 0x0233, 0x023f, 0x0242, - 0x024b, 0x024e, 0x0251, 0x025d, 0x0260, 0x0269, 0x026c, 0x026f, 0x0275, - 0x0278, 0x0281, 0x028a, 0x029c, 0x029f, 0x02a3, 0x02af, 0x02b9, 0x02c5, - 0x02c9, 0x02cd, 0x02d1, 0x02d5, 0x02e7, 0x02ed, 0x02f1, 0x02f5, 0x02f9, - 0x02fd, 0x0305, 0x0309, 0x030d, 0x0313, 0x0317, 0x031b, 0x0323, 0x0327, - 0x032b, 0x032f, 0x0335, 0x033d, 0x0341, 0x0349, 0x034d, 0x0351, 0x0f0b, - 0x0357, 0x035b, 0x035f, 0x0363, 0x0367, 0x036b, 0x036f, 0x0373, 0x0379, - 0x037d, 0x0381, 0x0385, 0x0389, 0x038d, 0x0391, 0x0395, 0x0399, 0x039d, - 0x03a1, 0x10dc, 0x03a5, 0x03c9, 0x03cd, 0x03d9, 0x03dd, 0x03e1, 0x03ef, - 0x03f1, 0x043d, 0x044f, 0x0499, 0x04f0, 0x0502, 0x054a, 0x0564, 0x056c, - 0x0570, 0x0573, 0x059a, 0x05fa, 0x05fe, 0x0607, 0x060b, 0x0614, 0x0618, - 0x061e, 0x0622, 0x0628, 0x068e, 0x0694, 0x0698, 0x069e, 0x06a2, 0x06ab, - 0x03ac, 0x06f3, 0x03ad, 0x06f6, 0x03ae, 0x06f9, 0x03af, 0x06fc, 0x03cc, - 0x06ff, 0x03cd, 0x0702, 0x03ce, 0x0705, 0x0709, 0x070d, 0x0711, 0x0386, - 0x0732, 0x0735, 0x03b9, 0x0737, 0x073b, 0x0388, 0x0753, 0x0389, 0x0756, - 0x0390, 0x076b, 0x038a, 0x0777, 0x03b0, 0x0789, 0x038e, 0x0799, 0x079f, - 0x07a3, 0x038c, 0x07b8, 0x038f, 0x07bb, 0x00b4, 0x07be, 0x07c0, 0x07c2, - 0x2010, 0x07cb, 0x002e, 0x07cd, 0x07cf, 0x0020, 0x07d2, 0x07d6, 0x07db, - 0x07df, 0x07e4, 0x07ea, 0x07f0, 0x0020, 0x07f6, 0x2212, 0x0801, 0x0805, - 0x0807, 0x081d, 0x0825, 0x0827, 0x0043, 0x082d, 0x0830, 0x0190, 0x0836, - 0x0839, 0x004e, 0x0845, 0x0847, 0x084c, 0x084e, 0x0851, 0x005a, 0x03a9, - 0x005a, 0x0853, 0x0857, 0x0860, 0x0069, 0x0862, 0x0865, 0x086f, 0x0874, - 0x087a, 0x087e, 0x08a2, 0x0049, 0x08a4, 0x08a6, 0x08a9, 0x0056, 0x08ab, - 0x08ad, 0x08b0, 0x08b4, 0x0058, 0x08b6, 0x08b8, 0x08bb, 0x08c0, 0x08c2, - 0x08c5, 0x0076, 0x08c7, 0x08c9, 0x08cc, 0x08d0, 0x0078, 0x08d2, 0x08d4, - 0x08d7, 0x08db, 0x08de, 0x08e4, 0x08e7, 0x08f0, 0x08f3, 0x08f6, 0x08f9, - 0x0902, 0x0906, 0x090b, 0x090f, 0x0914, 0x0917, 0x091a, 0x0923, 0x092c, - 0x093b, 0x093e, 0x0941, 0x0944, 0x0947, 0x094a, 0x0956, 0x095c, 0x0960, - 0x0962, 0x0964, 0x0968, 0x096a, 0x0970, 0x0978, 0x097c, 0x0980, 0x0986, - 0x0989, 0x098f, 0x0991, 0x0030, 0x0993, 0x0999, 0x099c, 0x099e, 0x09a1, - 0x09a4, 0x2d61, 0x6bcd, 0x9f9f, 0x09a6, 0x09b1, 0x09bc, 0x09c7, 0x0a95, - 0x0aa1, 0x0b15, 0x0020, 0x0b27, 0x0b31, 0x0b8d, 0x0ba1, 0x0ba5, 0x0ba9, - 0x0bad, 0x0bb1, 0x0bb5, 0x0bb9, 0x0bbd, 0x0bc1, 0x0bc5, 0x0c21, 0x0c35, - 0x0c39, 0x0c3d, 0x0c41, 0x0c45, 0x0c49, 0x0c4d, 0x0c51, 0x0c55, 0x0c59, - 0x0c6f, 0x0c71, 0x0c73, 0x0ca0, 0x0cbc, 0x0cdc, 0x0ce4, 0x0cec, 0x0cf4, - 0x0cfc, 0x0d04, 0x0d0c, 0x0d14, 0x0d22, 0x0d2e, 0x0d7a, 0x0d82, 0x0d85, - 0x0d89, 0x0d8d, 0x0d9d, 0x0db1, 0x0db5, 0x0dbc, 0x0dc2, 0x0dc6, 0x0e28, - 0x0e2c, 0x0e30, 0x0e32, 0x0e36, 0x0e3c, 0x0e3e, 0x0e41, 0x0e43, 0x0e46, - 0x0e77, 0x0e7b, 0x0e89, 0x0e8e, 0x0e94, 0x0e9c, 0x0ea3, 0x0ea9, 0x0eb4, - 0x0ebe, 0x0ec6, 0x0eca, 0x0ecf, 0x0ed9, 0x0edd, 0x0ee4, 0x0eec, 0x0ef3, - 0x0ef8, 0x0f04, 0x0f0a, 0x0f15, 0x0f1b, 0x0f22, 0x0f28, 0x0f33, 0x0f3d, - 0x0f45, 0x0f4c, 0x0f51, 0x0f57, 0x0f5e, 0x0f63, 0x0f69, 0x0f70, 0x0f76, - 0x0f7d, 0x0f82, 0x0f89, 0x0f8d, 0x0f9e, 0x0fa4, 0x0fa9, 0x0fad, 0x0fb8, - 0x0fbe, 0x0fc9, 0x0fd0, 0x0fd6, 0x0fda, 0x0fe1, 0x0fe5, 0x0fef, 0x0ffa, - 0x1000, 0x1004, 0x1009, 0x100f, 0x1013, 0x101a, 0x101f, 0x1023, 0x1029, - 0x102f, 0x1032, 0x1036, 0x1039, 0x103f, 0x1045, 0x1059, 0x1061, 0x1079, - 0x107c, 0x1080, 0x1095, 0x10a1, 0x10b1, 0x10c3, 0x10cb, 0x10cf, 0x10da, - 0x10de, 0x10ea, 0x10f2, 0x10f4, 0x1100, 0x1105, 0x1111, 0x1141, 0x1149, - 0x114d, 0x1153, 0x1157, 0x115a, 0x116e, 0x1171, 0x1175, 0x117b, 0x117d, - 0x1181, 0x1184, 0x118c, 0x1192, 0x1196, 0x119c, 0x11a2, 0x11a8, 0x11ab, - 0xa76f, 0x11af, 0x11b3, 0x11bb, 0x120d, 0x130b, 0x1409, 0x148d, 0x1492, - 0x1550, 0x1569, 0x156f, 0x1575, 0x157b, 0x1587, 0x1593, 0x002b, 0x159e, - 0x15b6, 0x15ba, 0x15be, 0x15c2, 0x15c6, 0x15ca, 0x15de, 0x15e2, 0x1646, - 0x165f, 0x1685, 0x168b, 0x1749, 0x174f, 0x1754, 0x1774, 0x1874, 0x187a, - 0x190e, 0x19d0, 0x1a74, 0x1a7c, 0x1a9a, 0x1a9f, 0x1ab3, 0x1abd, 0x1ac3, - 0x1ad7, 0x1adc, 0x1ae2, 0x1af0, 0x1b20, 0x1b2d, 0x1b35, 0x1b39, 0x1b4f, - 0x1bc6, 0x1bd8, 0x1bda, 0x1bdc, 0x3164, 0x1c1d, 0x1c1f, 0x1c21, 0x1c23, - 0x1c25, 0x1c27, 0x1c45, 0x1c53, 0x1c58, 0x1c61, 0x1c6a, 0x1c7c, 0x1c85, - 0x1ca5, 0x1cc0, 0x1cc2, 0x1cc4, 0x1cc6, 0x1cc8, 0x1cca, 0x1ccc, 0x1cce, - 0x1cee, 0x1cf0, 0x1cf2, 0x1cf4, 0x1cf6, 0x1cfd, 0x1cff, 0x1d01, 0x1d03, - 0x1d12, 0x1d14, 0x1d16, 0x1d18, 0x1d1a, 0x1d1c, 0x1d1e, 0x1d20, 0x1d22, - 0x1d24, 0x1d26, 0x1d28, 0x1d2a, 0x1d2c, 0x1d2e, 0x1d32, 0x03f4, 0x1d34, - 0x2207, 0x1d36, 0x2202, 0x1d38, 0x1d40, 0x03f4, 0x1d42, 0x2207, 0x1d44, - 0x2202, 0x1d46, 0x1d4e, 0x03f4, 0x1d50, 0x2207, 0x1d52, 0x2202, 0x1d54, - 0x1d5c, 0x03f4, 0x1d5e, 0x2207, 0x1d60, 0x2202, 0x1d62, 0x1d6a, 0x03f4, - 0x1d6c, 0x2207, 0x1d6e, 0x2202, 0x1d70, 0x1d7a, 0x1d7c, 0x1d7e, 0x1d80, - 0x1d82, 0x1d84, 0x1d8a, 0x1da7, 0x062d, 0x1daf, 0x1dbb, 0x062c, 0x1dcb, - 0x1e3b, 0x1e47, 0x1e5a, 0x1e6c, 0x1e7f, 0x1e81, 0x1e85, 0x1e8b, 0x1e91, - 0x1e93, 0x1e97, 0x1e99, 0x1ea1, 0x1ea4, 0x1ea6, 0x1eac, 0x1eae, 0x30b5, - 0x1eb4, 0x1f0c, 0x1f22, 0x1f26, 0x1f2b, 0x1f78, 0x1f89, 0x208a, 0x209a, - 0x20a0, 0x219a, 0x22b8, -}; - -static const uint8_t unicode_decomp_data[9158] = { - 0x20, 0x88, 0x20, 0x84, 0x32, 0x33, 0x20, 0x81, 0x20, 0xa7, 0x31, 0x6f, - 0x31, 0xd0, 0x34, 0x31, 0xd0, 0x32, 0x33, 0xd0, 0x34, 0x41, 0x80, 0x41, - 0x81, 0x41, 0x82, 0x41, 0x83, 0x41, 0x88, 0x41, 0x8a, 0x00, 0x00, 0x43, - 0xa7, 0x45, 0x80, 0x45, 0x81, 0x45, 0x82, 0x45, 0x88, 0x49, 0x80, 0x49, - 0x81, 0x49, 0x82, 0x49, 0x88, 0x00, 0x00, 0x4e, 0x83, 0x4f, 0x80, 0x4f, - 0x81, 0x4f, 0x82, 0x4f, 0x83, 0x4f, 0x88, 0x00, 0x00, 0x00, 0x00, 0x55, - 0x80, 0x55, 0x81, 0x55, 0x82, 0x55, 0x88, 0x59, 0x81, 0x00, 0x00, 0x00, - 0x00, 0x61, 0x80, 0x61, 0x81, 0x61, 0x82, 0x61, 0x83, 0x61, 0x88, 0x61, - 0x8a, 0x00, 0x00, 0x63, 0xa7, 0x65, 0x80, 0x65, 0x81, 0x65, 0x82, 0x65, - 0x88, 0x69, 0x80, 0x69, 0x81, 0x69, 0x82, 0x69, 0x88, 0x00, 0x00, 0x6e, - 0x83, 0x6f, 0x80, 0x6f, 0x81, 0x6f, 0x82, 0x6f, 0x83, 0x6f, 0x88, 0x00, - 0x00, 0x00, 0x00, 0x75, 0x80, 0x75, 0x81, 0x75, 0x82, 0x75, 0x88, 0x79, - 0x81, 0x00, 0x00, 0x79, 0x88, 0x41, 0x84, 0x41, 0x86, 0x41, 0xa8, 0x43, - 0x81, 0x43, 0x82, 0x43, 0x87, 0x43, 0x8c, 0x44, 0x8c, 0x45, 0x84, 0x45, - 0x86, 0x45, 0x87, 0x45, 0xa8, 0x45, 0x8c, 0x47, 0x82, 0x47, 0x86, 0x47, - 0x87, 0x47, 0xa7, 0x48, 0x82, 0x49, 0x83, 0x49, 0x84, 0x49, 0x86, 0x49, - 0xa8, 0x49, 0x87, 0x49, 0x4a, 0x69, 0x6a, 0x4a, 0x82, 0x4b, 0xa7, 0x4c, - 0x81, 0x4c, 0xa7, 0x4c, 0x8c, 0x4c, 0x00, 0x00, 0x6b, 0x20, 0x6b, 0x4e, - 0x81, 0x4e, 0xa7, 0x4e, 0x8c, 0xbc, 0x02, 0x6e, 0x4f, 0x84, 0x4f, 0x86, - 0x4f, 0x8b, 0x52, 0x81, 0x52, 0xa7, 0x52, 0x8c, 0x53, 0x81, 0x53, 0x82, - 0x53, 0xa7, 0x53, 0x8c, 0x54, 0xa7, 0x54, 0x8c, 0x55, 0x83, 0x55, 0x84, - 0x55, 0x86, 0x55, 0x8a, 0x55, 0x8b, 0x55, 0xa8, 0x57, 0x82, 0x59, 0x82, - 0x59, 0x88, 0x5a, 0x81, 0x5a, 0x87, 0x5a, 0x8c, 0x4f, 0x9b, 0x55, 0x9b, - 0x44, 0x00, 0x7d, 0x01, 0x44, 0x00, 0x7e, 0x01, 0x64, 0x00, 0x7e, 0x01, - 0x4c, 0x4a, 0x4c, 0x6a, 0x6c, 0x6a, 0x4e, 0x4a, 0x4e, 0x6a, 0x6e, 0x6a, - 0x41, 0x00, 0x8c, 0x49, 0x00, 0x8c, 0x4f, 0x00, 0x8c, 0x55, 0x00, 0x8c, - 0xdc, 0x00, 0x84, 0xdc, 0x00, 0x81, 0xdc, 0x00, 0x8c, 0xdc, 0x00, 0x80, - 0xc4, 0x00, 0x84, 0x26, 0x02, 0x84, 0xc6, 0x00, 0x84, 0x47, 0x8c, 0x4b, - 0x8c, 0x4f, 0xa8, 0xea, 0x01, 0x84, 0xeb, 0x01, 0x84, 0xb7, 0x01, 0x8c, - 0x92, 0x02, 0x8c, 0x6a, 0x00, 0x8c, 0x44, 0x5a, 0x44, 0x7a, 0x64, 0x7a, - 0x47, 0x81, 0x4e, 0x00, 0x80, 0xc5, 0x00, 0x81, 0xc6, 0x00, 0x81, 0xd8, - 0x00, 0x81, 0x41, 0x8f, 0x41, 0x91, 0x45, 0x8f, 0x45, 0x91, 0x49, 0x8f, - 0x49, 0x91, 0x4f, 0x8f, 0x4f, 0x91, 0x52, 0x8f, 0x52, 0x91, 0x55, 0x8f, - 0x55, 0x91, 0x53, 0xa6, 0x54, 0xa6, 0x48, 0x8c, 0x41, 0x00, 0x87, 0x45, - 0x00, 0xa7, 0xd6, 0x00, 0x84, 0xd5, 0x00, 0x84, 0x4f, 0x00, 0x87, 0x2e, - 0x02, 0x84, 0x59, 0x00, 0x84, 0x68, 0x00, 0x66, 0x02, 0x6a, 0x00, 0x72, - 0x00, 0x79, 0x02, 0x7b, 0x02, 0x81, 0x02, 0x77, 0x00, 0x79, 0x00, 0x20, - 0x86, 0x20, 0x87, 0x20, 0x8a, 0x20, 0xa8, 0x20, 0x83, 0x20, 0x8b, 0x63, - 0x02, 0x6c, 0x00, 0x73, 0x00, 0x78, 0x00, 0x95, 0x02, 0x80, 0x81, 0x00, - 0x93, 0x88, 0x81, 0x20, 0xc5, 0x20, 0x81, 0xa8, 0x00, 0x81, 0x91, 0x03, - 0x81, 0x95, 0x03, 0x81, 0x97, 0x03, 0x81, 0x99, 0x03, 0x81, 0x00, 0x00, - 0x00, 0x9f, 0x03, 0x81, 0x00, 0x00, 0x00, 0xa5, 0x03, 0x81, 0xa9, 0x03, - 0x81, 0xca, 0x03, 0x81, 0x01, 0x03, 0x98, 0x07, 0xa4, 0x07, 0xb0, 0x00, - 0xb4, 0x00, 0xb6, 0x00, 0xb8, 0x00, 0xca, 0x00, 0x01, 0x03, 0xb8, 0x07, - 0xc4, 0x07, 0xbe, 0x00, 0xc4, 0x00, 0xc8, 0x00, 0xa5, 0x03, 0x0d, 0x13, - 0x00, 0x01, 0x03, 0xd1, 0x00, 0xd1, 0x07, 0xc6, 0x03, 0xc0, 0x03, 0xba, - 0x03, 0xc1, 0x03, 0xc2, 0x03, 0x00, 0x00, 0x98, 0x03, 0xb5, 0x03, 0x15, - 0x04, 0x80, 0x15, 0x04, 0x88, 0x00, 0x00, 0x00, 0x13, 0x04, 0x81, 0x06, - 0x04, 0x88, 0x1a, 0x04, 0x81, 0x18, 0x04, 0x80, 0x23, 0x04, 0x86, 0x18, - 0x04, 0x86, 0x38, 0x04, 0x86, 0x35, 0x04, 0x80, 0x35, 0x04, 0x88, 0x00, - 0x00, 0x00, 0x33, 0x04, 0x81, 0x56, 0x04, 0x88, 0x3a, 0x04, 0x81, 0x38, - 0x04, 0x80, 0x43, 0x04, 0x86, 0x74, 0x04, 0x8f, 0x16, 0x04, 0x86, 0x10, - 0x04, 0x86, 0x10, 0x04, 0x88, 0x15, 0x04, 0x86, 0xd8, 0x04, 0x88, 0x16, - 0x04, 0x88, 0x17, 0x04, 0x88, 0x18, 0x04, 0x84, 0x18, 0x04, 0x88, 0x1e, - 0x04, 0x88, 0xe8, 0x04, 0x88, 0x2d, 0x04, 0x88, 0x23, 0x04, 0x84, 0x23, - 0x04, 0x88, 0x23, 0x04, 0x8b, 0x27, 0x04, 0x88, 0x2b, 0x04, 0x88, 0x65, - 0x05, 0x82, 0x05, 0x27, 0x06, 0x00, 0x2c, 0x00, 0x2d, 0x21, 0x2d, 0x00, - 0x2e, 0x23, 0x2d, 0x27, 0x06, 0x00, 0x4d, 0x21, 0x4d, 0xa0, 0x4d, 0x23, - 0x4d, 0xd5, 0x06, 0x54, 0x06, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x06, 0x54, - 0x06, 0xd2, 0x06, 0x54, 0x06, 0x28, 0x09, 0x3c, 0x09, 0x30, 0x09, 0x3c, - 0x09, 0x33, 0x09, 0x3c, 0x09, 0x15, 0x09, 0x00, 0x27, 0x01, 0x27, 0x02, - 0x27, 0x07, 0x27, 0x0c, 0x27, 0x0d, 0x27, 0x16, 0x27, 0x1a, 0x27, 0xbe, - 0x09, 0x09, 0x00, 0x09, 0x19, 0xa1, 0x09, 0xbc, 0x09, 0xaf, 0x09, 0xbc, - 0x09, 0x32, 0x0a, 0x3c, 0x0a, 0x38, 0x0a, 0x3c, 0x0a, 0x16, 0x0a, 0x00, - 0x26, 0x01, 0x26, 0x06, 0x26, 0x2b, 0x0a, 0x3c, 0x0a, 0x47, 0x0b, 0x56, - 0x0b, 0x3e, 0x0b, 0x09, 0x00, 0x09, 0x19, 0x21, 0x0b, 0x3c, 0x0b, 0x92, - 0x0b, 0xd7, 0x0b, 0xbe, 0x0b, 0x08, 0x00, 0x09, 0x00, 0x08, 0x19, 0x46, - 0x0c, 0x56, 0x0c, 0xbf, 0x0c, 0xd5, 0x0c, 0xc6, 0x0c, 0xd5, 0x0c, 0xc2, - 0x0c, 0x04, 0x00, 0x08, 0x13, 0x3e, 0x0d, 0x08, 0x00, 0x09, 0x00, 0x08, - 0x19, 0xd9, 0x0d, 0xca, 0x0d, 0xca, 0x0d, 0x0f, 0x05, 0x12, 0x00, 0x0f, - 0x15, 0x4d, 0x0e, 0x32, 0x0e, 0xcd, 0x0e, 0xb2, 0x0e, 0x99, 0x0e, 0x12, - 0x00, 0x12, 0x08, 0x42, 0x0f, 0xb7, 0x0f, 0x4c, 0x0f, 0xb7, 0x0f, 0x51, - 0x0f, 0xb7, 0x0f, 0x56, 0x0f, 0xb7, 0x0f, 0x5b, 0x0f, 0xb7, 0x0f, 0x40, - 0x0f, 0xb5, 0x0f, 0x71, 0x0f, 0x72, 0x0f, 0x71, 0x0f, 0x00, 0x03, 0x41, - 0x0f, 0xb2, 0x0f, 0x81, 0x0f, 0xb3, 0x0f, 0x80, 0x0f, 0xb3, 0x0f, 0x81, - 0x0f, 0x71, 0x0f, 0x80, 0x0f, 0x92, 0x0f, 0xb7, 0x0f, 0x9c, 0x0f, 0xb7, - 0x0f, 0xa1, 0x0f, 0xb7, 0x0f, 0xa6, 0x0f, 0xb7, 0x0f, 0xab, 0x0f, 0xb7, - 0x0f, 0x90, 0x0f, 0xb5, 0x0f, 0x25, 0x10, 0x2e, 0x10, 0x05, 0x1b, 0x35, - 0x1b, 0x00, 0x00, 0x00, 0x00, 0x07, 0x1b, 0x35, 0x1b, 0x00, 0x00, 0x00, - 0x00, 0x09, 0x1b, 0x35, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0x35, - 0x1b, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x1b, 0x35, 0x1b, 0x11, 0x1b, 0x35, - 0x1b, 0x3a, 0x1b, 0x35, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x1b, 0x35, - 0x1b, 0x3e, 0x1b, 0x35, 0x1b, 0x42, 0x1b, 0x35, 0x1b, 0x41, 0x00, 0xc6, - 0x00, 0x42, 0x00, 0x00, 0x00, 0x44, 0x00, 0x45, 0x00, 0x8e, 0x01, 0x47, - 0x00, 0x4f, 0x00, 0x22, 0x02, 0x50, 0x00, 0x52, 0x00, 0x54, 0x00, 0x55, - 0x00, 0x57, 0x00, 0x61, 0x00, 0x50, 0x02, 0x51, 0x02, 0x02, 0x1d, 0x62, - 0x00, 0x64, 0x00, 0x65, 0x00, 0x59, 0x02, 0x5b, 0x02, 0x5c, 0x02, 0x67, - 0x00, 0x00, 0x00, 0x6b, 0x00, 0x6d, 0x00, 0x4b, 0x01, 0x6f, 0x00, 0x54, - 0x02, 0x16, 0x1d, 0x17, 0x1d, 0x70, 0x00, 0x74, 0x00, 0x75, 0x00, 0x1d, - 0x1d, 0x6f, 0x02, 0x76, 0x00, 0x25, 0x1d, 0xb2, 0x03, 0xb3, 0x03, 0xb4, - 0x03, 0xc6, 0x03, 0xc7, 0x03, 0x69, 0x00, 0x72, 0x00, 0x75, 0x00, 0x76, - 0x00, 0xb2, 0x03, 0xb3, 0x03, 0xc1, 0x03, 0xc6, 0x03, 0xc7, 0x03, 0x52, - 0x02, 0x63, 0x00, 0x55, 0x02, 0xf0, 0x00, 0x5c, 0x02, 0x66, 0x00, 0x5f, - 0x02, 0x61, 0x02, 0x65, 0x02, 0x68, 0x02, 0x69, 0x02, 0x6a, 0x02, 0x7b, - 0x1d, 0x9d, 0x02, 0x6d, 0x02, 0x85, 0x1d, 0x9f, 0x02, 0x71, 0x02, 0x70, - 0x02, 0x72, 0x02, 0x73, 0x02, 0x74, 0x02, 0x75, 0x02, 0x78, 0x02, 0x82, - 0x02, 0x83, 0x02, 0xab, 0x01, 0x89, 0x02, 0x8a, 0x02, 0x1c, 0x1d, 0x8b, - 0x02, 0x8c, 0x02, 0x7a, 0x00, 0x90, 0x02, 0x91, 0x02, 0x92, 0x02, 0xb8, - 0x03, 0x41, 0x00, 0xa5, 0x42, 0x00, 0x87, 0x42, 0x00, 0xa3, 0x42, 0x00, - 0xb1, 0xc7, 0x00, 0x81, 0x44, 0x00, 0x87, 0x44, 0x00, 0xa3, 0x44, 0x00, - 0xb1, 0x44, 0x00, 0xa7, 0x44, 0x00, 0xad, 0x12, 0x01, 0x80, 0x12, 0x01, - 0x81, 0x45, 0x00, 0xad, 0x45, 0x00, 0xb0, 0x28, 0x02, 0x86, 0x46, 0x00, - 0x87, 0x47, 0x00, 0x84, 0x48, 0x00, 0x87, 0x48, 0x00, 0xa3, 0x48, 0x00, - 0x88, 0x48, 0x00, 0xa7, 0x48, 0x00, 0xae, 0x49, 0x00, 0xb0, 0xcf, 0x00, - 0x81, 0x4b, 0x00, 0x81, 0x4b, 0x00, 0xa3, 0x4b, 0x00, 0xb1, 0x4c, 0x00, - 0xa3, 0x36, 0x1e, 0x84, 0x4c, 0xb1, 0x4c, 0xad, 0x4d, 0x81, 0x4d, 0x87, - 0x4d, 0xa3, 0x4e, 0x87, 0x4e, 0xa3, 0x4e, 0xb1, 0x4e, 0xad, 0xd5, 0x00, - 0x81, 0xd5, 0x00, 0x88, 0x4c, 0x01, 0x80, 0x4c, 0x01, 0x81, 0x50, 0x00, - 0x81, 0x50, 0x00, 0x87, 0x52, 0x00, 0x87, 0x52, 0x00, 0xa3, 0x5a, 0x1e, - 0x84, 0x52, 0x00, 0xb1, 0x53, 0x00, 0x87, 0x53, 0x00, 0xa3, 0x5a, 0x01, - 0x87, 0x60, 0x01, 0x87, 0x62, 0x1e, 0x87, 0x54, 0x00, 0x87, 0x54, 0x00, - 0xa3, 0x54, 0x00, 0xb1, 0x54, 0x00, 0xad, 0x55, 0x00, 0xa4, 0x55, 0x00, - 0xb0, 0x55, 0x00, 0xad, 0x68, 0x01, 0x81, 0x6a, 0x01, 0x88, 0x56, 0x83, - 0x56, 0xa3, 0x57, 0x80, 0x57, 0x81, 0x57, 0x88, 0x57, 0x87, 0x57, 0xa3, - 0x58, 0x87, 0x58, 0x88, 0x59, 0x87, 0x5a, 0x82, 0x5a, 0xa3, 0x5a, 0xb1, - 0x68, 0xb1, 0x74, 0x88, 0x77, 0x8a, 0x79, 0x8a, 0x61, 0x00, 0xbe, 0x02, - 0x7f, 0x01, 0x87, 0x41, 0x00, 0xa3, 0x41, 0x00, 0x89, 0xc2, 0x00, 0x81, - 0xc2, 0x00, 0x80, 0xc2, 0x00, 0x89, 0xc2, 0x00, 0x83, 0xa0, 0x1e, 0x82, - 0x02, 0x01, 0x81, 0x02, 0x01, 0x80, 0x02, 0x01, 0x89, 0x02, 0x01, 0x83, - 0xa0, 0x1e, 0x86, 0x45, 0x00, 0xa3, 0x45, 0x00, 0x89, 0x45, 0x00, 0x83, - 0xca, 0x00, 0x81, 0xca, 0x00, 0x80, 0xca, 0x00, 0x89, 0xca, 0x00, 0x83, - 0xb8, 0x1e, 0x82, 0x49, 0x00, 0x89, 0x49, 0x00, 0xa3, 0x4f, 0x00, 0xa3, - 0x4f, 0x00, 0x89, 0xd4, 0x00, 0x81, 0xd4, 0x00, 0x80, 0xd4, 0x00, 0x89, - 0xd4, 0x00, 0x83, 0xcc, 0x1e, 0x82, 0xa0, 0x01, 0x81, 0xa0, 0x01, 0x80, - 0xa0, 0x01, 0x89, 0xa0, 0x01, 0x83, 0xa0, 0x01, 0xa3, 0x55, 0x00, 0xa3, - 0x55, 0x00, 0x89, 0xaf, 0x01, 0x81, 0xaf, 0x01, 0x80, 0xaf, 0x01, 0x89, - 0xaf, 0x01, 0x83, 0xaf, 0x01, 0xa3, 0x59, 0x00, 0x80, 0x59, 0x00, 0xa3, - 0x59, 0x00, 0x89, 0x59, 0x00, 0x83, 0xb1, 0x03, 0x13, 0x03, 0x00, 0x1f, - 0x80, 0x00, 0x1f, 0x81, 0x00, 0x1f, 0xc2, 0x91, 0x03, 0x13, 0x03, 0x08, - 0x1f, 0x80, 0x08, 0x1f, 0x81, 0x08, 0x1f, 0xc2, 0xb5, 0x03, 0x13, 0x03, - 0x10, 0x1f, 0x80, 0x10, 0x1f, 0x81, 0x95, 0x03, 0x13, 0x03, 0x18, 0x1f, - 0x80, 0x18, 0x1f, 0x81, 0xb7, 0x03, 0x93, 0xb7, 0x03, 0x94, 0x20, 0x1f, - 0x80, 0x21, 0x1f, 0x80, 0x20, 0x1f, 0x81, 0x21, 0x1f, 0x81, 0x20, 0x1f, - 0xc2, 0x21, 0x1f, 0xc2, 0x97, 0x03, 0x93, 0x97, 0x03, 0x94, 0x28, 0x1f, - 0x80, 0x29, 0x1f, 0x80, 0x28, 0x1f, 0x81, 0x29, 0x1f, 0x81, 0x28, 0x1f, - 0xc2, 0x29, 0x1f, 0xc2, 0xb9, 0x03, 0x93, 0xb9, 0x03, 0x94, 0x30, 0x1f, - 0x80, 0x31, 0x1f, 0x80, 0x30, 0x1f, 0x81, 0x31, 0x1f, 0x81, 0x30, 0x1f, - 0xc2, 0x31, 0x1f, 0xc2, 0x99, 0x03, 0x93, 0x99, 0x03, 0x94, 0x38, 0x1f, - 0x80, 0x39, 0x1f, 0x80, 0x38, 0x1f, 0x81, 0x39, 0x1f, 0x81, 0x38, 0x1f, - 0xc2, 0x39, 0x1f, 0xc2, 0xbf, 0x03, 0x93, 0xbf, 0x03, 0x94, 0x40, 0x1f, - 0x80, 0x40, 0x1f, 0x81, 0x9f, 0x03, 0x13, 0x03, 0x48, 0x1f, 0x80, 0x48, - 0x1f, 0x81, 0xc5, 0x03, 0x13, 0x03, 0x50, 0x1f, 0x80, 0x50, 0x1f, 0x81, - 0x50, 0x1f, 0xc2, 0xa5, 0x03, 0x94, 0x00, 0x00, 0x00, 0x59, 0x1f, 0x80, - 0x00, 0x00, 0x00, 0x59, 0x1f, 0x81, 0x00, 0x00, 0x00, 0x59, 0x1f, 0xc2, - 0xc9, 0x03, 0x93, 0xc9, 0x03, 0x94, 0x60, 0x1f, 0x80, 0x61, 0x1f, 0x80, - 0x60, 0x1f, 0x81, 0x61, 0x1f, 0x81, 0x60, 0x1f, 0xc2, 0x61, 0x1f, 0xc2, - 0xa9, 0x03, 0x93, 0xa9, 0x03, 0x94, 0x68, 0x1f, 0x80, 0x69, 0x1f, 0x80, - 0x68, 0x1f, 0x81, 0x69, 0x1f, 0x81, 0x68, 0x1f, 0xc2, 0x69, 0x1f, 0xc2, - 0xb1, 0x03, 0x80, 0xb5, 0x03, 0x80, 0xb7, 0x03, 0x80, 0xb9, 0x03, 0x80, - 0xbf, 0x03, 0x80, 0xc5, 0x03, 0x80, 0xc9, 0x03, 0x80, 0x00, 0x1f, 0x45, - 0x03, 0x20, 0x1f, 0x45, 0x03, 0x60, 0x1f, 0x45, 0x03, 0xb1, 0x03, 0x86, - 0xb1, 0x03, 0x84, 0x70, 0x1f, 0xc5, 0xb1, 0x03, 0xc5, 0xac, 0x03, 0xc5, - 0x00, 0x00, 0x00, 0xb1, 0x03, 0xc2, 0xb6, 0x1f, 0xc5, 0x91, 0x03, 0x86, - 0x91, 0x03, 0x84, 0x91, 0x03, 0x80, 0x91, 0x03, 0xc5, 0x20, 0x93, 0x20, - 0x93, 0x20, 0xc2, 0xa8, 0x00, 0xc2, 0x74, 0x1f, 0xc5, 0xb7, 0x03, 0xc5, - 0xae, 0x03, 0xc5, 0x00, 0x00, 0x00, 0xb7, 0x03, 0xc2, 0xc6, 0x1f, 0xc5, - 0x95, 0x03, 0x80, 0x97, 0x03, 0x80, 0x97, 0x03, 0xc5, 0xbf, 0x1f, 0x80, - 0xbf, 0x1f, 0x81, 0xbf, 0x1f, 0xc2, 0xb9, 0x03, 0x86, 0xb9, 0x03, 0x84, - 0xca, 0x03, 0x80, 0x00, 0x03, 0xb9, 0x42, 0xca, 0x42, 0x99, 0x06, 0x99, - 0x04, 0x99, 0x00, 0xfe, 0x1f, 0x80, 0xfe, 0x1f, 0x81, 0xfe, 0x1f, 0xc2, - 0xc5, 0x03, 0x86, 0xc5, 0x03, 0x84, 0xcb, 0x03, 0x80, 0x00, 0x03, 0xc1, - 0x13, 0xc1, 0x14, 0xc5, 0x42, 0xcb, 0x42, 0xa5, 0x06, 0xa5, 0x04, 0xa5, - 0x00, 0xa1, 0x03, 0x94, 0xa8, 0x00, 0x80, 0x85, 0x03, 0x60, 0x00, 0x7c, - 0x1f, 0xc5, 0xc9, 0x03, 0xc5, 0xce, 0x03, 0xc5, 0x00, 0x00, 0x00, 0xc9, - 0x03, 0xc2, 0xf6, 0x1f, 0xc5, 0x9f, 0x03, 0x80, 0xa9, 0x03, 0x80, 0xa9, - 0x03, 0xc5, 0x20, 0x94, 0x02, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0xb3, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x32, 0x20, - 0x32, 0x20, 0x32, 0x20, 0x00, 0x00, 0x00, 0x35, 0x20, 0x35, 0x20, 0x35, - 0x20, 0x00, 0x00, 0x00, 0x21, 0x21, 0x00, 0x00, 0x20, 0x85, 0x3f, 0x3f, - 0x3f, 0x21, 0x21, 0x3f, 0x32, 0x20, 0x00, 0x00, 0x00, 0x00, 0x30, 0x69, - 0x00, 0x00, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x3d, 0x28, 0x29, - 0x6e, 0x30, 0x00, 0x2b, 0x00, 0x12, 0x22, 0x3d, 0x00, 0x28, 0x00, 0x29, - 0x00, 0x00, 0x00, 0x61, 0x00, 0x65, 0x00, 0x6f, 0x00, 0x78, 0x00, 0x59, - 0x02, 0x68, 0x6b, 0x6c, 0x6d, 0x6e, 0x70, 0x73, 0x74, 0x52, 0x73, 0x61, - 0x2f, 0x63, 0x61, 0x2f, 0x73, 0xb0, 0x00, 0x43, 0x63, 0x2f, 0x6f, 0x63, - 0x2f, 0x75, 0xb0, 0x00, 0x46, 0x48, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, - 0xdf, 0x01, 0x01, 0x04, 0x24, 0x4e, 0x6f, 0x50, 0x51, 0x52, 0x52, 0x52, - 0x53, 0x4d, 0x54, 0x45, 0x4c, 0x54, 0x4d, 0x4b, 0x00, 0xc5, 0x00, 0x42, - 0x43, 0x00, 0x65, 0x45, 0x46, 0x00, 0x4d, 0x6f, 0xd0, 0x05, 0x46, 0x41, - 0x58, 0xc0, 0x03, 0xb3, 0x03, 0x93, 0x03, 0xa0, 0x03, 0x11, 0x22, 0x44, - 0x64, 0x65, 0x69, 0x6a, 0x31, 0xd0, 0x37, 0x31, 0xd0, 0x39, 0x31, 0xd0, - 0x31, 0x30, 0x31, 0xd0, 0x33, 0x32, 0xd0, 0x33, 0x31, 0xd0, 0x35, 0x32, - 0xd0, 0x35, 0x33, 0xd0, 0x35, 0x34, 0xd0, 0x35, 0x31, 0xd0, 0x36, 0x35, - 0xd0, 0x36, 0x31, 0xd0, 0x38, 0x33, 0xd0, 0x38, 0x35, 0xd0, 0x38, 0x37, - 0xd0, 0x38, 0x31, 0xd0, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x56, 0x56, - 0x49, 0x56, 0x49, 0x49, 0x56, 0x49, 0x49, 0x49, 0x49, 0x58, 0x58, 0x49, - 0x58, 0x49, 0x49, 0x4c, 0x43, 0x44, 0x4d, 0x69, 0x69, 0x69, 0x69, 0x69, - 0x69, 0x69, 0x76, 0x76, 0x69, 0x76, 0x69, 0x69, 0x76, 0x69, 0x69, 0x69, - 0x69, 0x78, 0x78, 0x69, 0x78, 0x69, 0x69, 0x6c, 0x63, 0x64, 0x6d, 0x30, - 0xd0, 0x33, 0x90, 0x21, 0xb8, 0x92, 0x21, 0xb8, 0x94, 0x21, 0xb8, 0xd0, - 0x21, 0xb8, 0xd4, 0x21, 0xb8, 0xd2, 0x21, 0xb8, 0x03, 0x22, 0xb8, 0x08, - 0x22, 0xb8, 0x0b, 0x22, 0xb8, 0x23, 0x22, 0xb8, 0x00, 0x00, 0x00, 0x25, - 0x22, 0xb8, 0x2b, 0x22, 0x2b, 0x22, 0x2b, 0x22, 0x00, 0x00, 0x00, 0x2e, - 0x22, 0x2e, 0x22, 0x2e, 0x22, 0x00, 0x00, 0x00, 0x3c, 0x22, 0xb8, 0x43, - 0x22, 0xb8, 0x45, 0x22, 0xb8, 0x00, 0x00, 0x00, 0x48, 0x22, 0xb8, 0x3d, - 0x00, 0xb8, 0x00, 0x00, 0x00, 0x61, 0x22, 0xb8, 0x4d, 0x22, 0xb8, 0x3c, - 0x00, 0xb8, 0x3e, 0x00, 0xb8, 0x64, 0x22, 0xb8, 0x65, 0x22, 0xb8, 0x72, - 0x22, 0xb8, 0x76, 0x22, 0xb8, 0x7a, 0x22, 0xb8, 0x82, 0x22, 0xb8, 0x86, - 0x22, 0xb8, 0xa2, 0x22, 0xb8, 0xa8, 0x22, 0xb8, 0xa9, 0x22, 0xb8, 0xab, - 0x22, 0xb8, 0x7c, 0x22, 0xb8, 0x91, 0x22, 0xb8, 0xb2, 0x22, 0x38, 0x03, - 0x08, 0x30, 0x31, 0x00, 0x31, 0x00, 0x30, 0x00, 0x32, 0x30, 0x28, 0x00, - 0x31, 0x00, 0x29, 0x00, 0x28, 0x00, 0x31, 0x00, 0x30, 0x00, 0x29, 0x00, - 0x28, 0x32, 0x30, 0x29, 0x31, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x30, 0x00, - 0x2e, 0x00, 0x32, 0x30, 0x2e, 0x28, 0x00, 0x61, 0x00, 0x29, 0x00, 0x41, - 0x00, 0x61, 0x00, 0x2b, 0x22, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x3a, 0x3d, - 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0xdd, 0x2a, 0xb8, 0x6a, 0x56, 0x00, 0x4e, - 0x00, 0x28, 0x36, 0x3f, 0x59, 0x85, 0x8c, 0xa0, 0xba, 0x3f, 0x51, 0x00, - 0x26, 0x2c, 0x43, 0x57, 0x6c, 0xa1, 0xb6, 0xc1, 0x9b, 0x52, 0x00, 0x5e, - 0x7a, 0x7f, 0x9d, 0xa6, 0xc1, 0xce, 0xe7, 0xb6, 0x53, 0xc8, 0x53, 0xe3, - 0x53, 0xd7, 0x56, 0x1f, 0x57, 0xeb, 0x58, 0x02, 0x59, 0x0a, 0x59, 0x15, - 0x59, 0x27, 0x59, 0x73, 0x59, 0x50, 0x5b, 0x80, 0x5b, 0xf8, 0x5b, 0x0f, - 0x5c, 0x22, 0x5c, 0x38, 0x5c, 0x6e, 0x5c, 0x71, 0x5c, 0xdb, 0x5d, 0xe5, - 0x5d, 0xf1, 0x5d, 0xfe, 0x5d, 0x72, 0x5e, 0x7a, 0x5e, 0x7f, 0x5e, 0xf4, - 0x5e, 0xfe, 0x5e, 0x0b, 0x5f, 0x13, 0x5f, 0x50, 0x5f, 0x61, 0x5f, 0x73, - 0x5f, 0xc3, 0x5f, 0x08, 0x62, 0x36, 0x62, 0x4b, 0x62, 0x2f, 0x65, 0x34, - 0x65, 0x87, 0x65, 0x97, 0x65, 0xa4, 0x65, 0xb9, 0x65, 0xe0, 0x65, 0xe5, - 0x65, 0xf0, 0x66, 0x08, 0x67, 0x28, 0x67, 0x20, 0x6b, 0x62, 0x6b, 0x79, - 0x6b, 0xb3, 0x6b, 0xcb, 0x6b, 0xd4, 0x6b, 0xdb, 0x6b, 0x0f, 0x6c, 0x14, - 0x6c, 0x34, 0x6c, 0x6b, 0x70, 0x2a, 0x72, 0x36, 0x72, 0x3b, 0x72, 0x3f, - 0x72, 0x47, 0x72, 0x59, 0x72, 0x5b, 0x72, 0xac, 0x72, 0x84, 0x73, 0x89, - 0x73, 0xdc, 0x74, 0xe6, 0x74, 0x18, 0x75, 0x1f, 0x75, 0x28, 0x75, 0x30, - 0x75, 0x8b, 0x75, 0x92, 0x75, 0x76, 0x76, 0x7d, 0x76, 0xae, 0x76, 0xbf, - 0x76, 0xee, 0x76, 0xdb, 0x77, 0xe2, 0x77, 0xf3, 0x77, 0x3a, 0x79, 0xb8, - 0x79, 0xbe, 0x79, 0x74, 0x7a, 0xcb, 0x7a, 0xf9, 0x7a, 0x73, 0x7c, 0xf8, - 0x7c, 0x36, 0x7f, 0x51, 0x7f, 0x8a, 0x7f, 0xbd, 0x7f, 0x01, 0x80, 0x0c, - 0x80, 0x12, 0x80, 0x33, 0x80, 0x7f, 0x80, 0x89, 0x80, 0xe3, 0x81, 0x00, - 0x07, 0x10, 0x19, 0x29, 0x38, 0x3c, 0x8b, 0x8f, 0x95, 0x4d, 0x86, 0x6b, - 0x86, 0x40, 0x88, 0x4c, 0x88, 0x63, 0x88, 0x7e, 0x89, 0x8b, 0x89, 0xd2, - 0x89, 0x00, 0x8a, 0x37, 0x8c, 0x46, 0x8c, 0x55, 0x8c, 0x78, 0x8c, 0x9d, - 0x8c, 0x64, 0x8d, 0x70, 0x8d, 0xb3, 0x8d, 0xab, 0x8e, 0xca, 0x8e, 0x9b, - 0x8f, 0xb0, 0x8f, 0xb5, 0x8f, 0x91, 0x90, 0x49, 0x91, 0xc6, 0x91, 0xcc, - 0x91, 0xd1, 0x91, 0x77, 0x95, 0x80, 0x95, 0x1c, 0x96, 0xb6, 0x96, 0xb9, - 0x96, 0xe8, 0x96, 0x51, 0x97, 0x5e, 0x97, 0x62, 0x97, 0x69, 0x97, 0xcb, - 0x97, 0xed, 0x97, 0xf3, 0x97, 0x01, 0x98, 0xa8, 0x98, 0xdb, 0x98, 0xdf, - 0x98, 0x96, 0x99, 0x99, 0x99, 0xac, 0x99, 0xa8, 0x9a, 0xd8, 0x9a, 0xdf, - 0x9a, 0x25, 0x9b, 0x2f, 0x9b, 0x32, 0x9b, 0x3c, 0x9b, 0x5a, 0x9b, 0xe5, - 0x9c, 0x75, 0x9e, 0x7f, 0x9e, 0xa5, 0x9e, 0x00, 0x16, 0x1e, 0x28, 0x2c, - 0x54, 0x58, 0x69, 0x6e, 0x7b, 0x96, 0xa5, 0xad, 0xe8, 0xf7, 0xfb, 0x12, - 0x30, 0x00, 0x00, 0x41, 0x53, 0x44, 0x53, 0x45, 0x53, 0x4b, 0x30, 0x99, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x4f, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, 0x00, 0x51, 0x30, 0x99, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x53, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x55, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, 0x00, 0x57, 0x30, 0x99, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x59, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x5b, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x30, 0x99, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x61, 0x30, 0x99, 0x30, 0x64, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x66, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, 0x00, 0x68, 0x30, 0x99, - 0x30, 0x6f, 0x30, 0x99, 0x30, 0x72, 0x30, 0x99, 0x30, 0x75, 0x30, 0x99, - 0x30, 0x78, 0x30, 0x99, 0x30, 0x7b, 0x30, 0x99, 0x30, 0x46, 0x30, 0x99, - 0x30, 0x20, 0x00, 0x99, 0x30, 0x9d, 0x30, 0x99, 0x30, 0x88, 0x30, 0x8a, - 0x30, 0xab, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, 0x00, 0xad, 0x30, 0x99, - 0x30, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, - 0x00, 0xb1, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x30, 0x99, - 0x30, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, - 0x00, 0xb7, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x30, 0x99, - 0x30, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, - 0x00, 0xbd, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x30, 0x99, - 0x30, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x30, 0x99, 0x30, 0xc4, 0x30, 0x99, - 0x30, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x30, 0x99, 0x30, 0x00, 0x00, 0x00, - 0x00, 0xc8, 0x30, 0x99, 0x30, 0xcf, 0x30, 0x99, 0x30, 0xd2, 0x30, 0x99, - 0x30, 0xd5, 0x30, 0x99, 0x30, 0xd8, 0x30, 0x99, 0x30, 0xdb, 0x30, 0x99, - 0x30, 0xa6, 0x30, 0x99, 0x30, 0xef, 0x30, 0x99, 0x30, 0xfd, 0x30, 0x99, - 0x30, 0xb3, 0x30, 0xc8, 0x30, 0x00, 0x11, 0x00, 0x01, 0xaa, 0x02, 0xac, - 0xad, 0x03, 0x04, 0x05, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0x1a, 0x06, - 0x07, 0x08, 0x21, 0x09, 0x11, 0x61, 0x11, 0x14, 0x11, 0x4c, 0x00, 0x01, - 0xb3, 0xb4, 0xb8, 0xba, 0xbf, 0xc3, 0xc5, 0x08, 0xc9, 0xcb, 0x09, 0x0a, - 0x0c, 0x0e, 0x0f, 0x13, 0x15, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x22, - 0x2c, 0x33, 0x38, 0xdd, 0xde, 0x43, 0x44, 0x45, 0x70, 0x71, 0x74, 0x7d, - 0x7e, 0x80, 0x8a, 0x8d, 0x00, 0x4e, 0x8c, 0x4e, 0x09, 0x4e, 0xdb, 0x56, - 0x0a, 0x4e, 0x2d, 0x4e, 0x0b, 0x4e, 0x32, 0x75, 0x59, 0x4e, 0x19, 0x4e, - 0x01, 0x4e, 0x29, 0x59, 0x30, 0x57, 0xba, 0x4e, 0x28, 0x00, 0x29, 0x00, - 0x00, 0x11, 0x02, 0x11, 0x03, 0x11, 0x05, 0x11, 0x06, 0x11, 0x07, 0x11, - 0x09, 0x11, 0x0b, 0x11, 0x0c, 0x11, 0x0e, 0x11, 0x0f, 0x11, 0x10, 0x11, - 0x11, 0x11, 0x12, 0x11, 0x28, 0x00, 0x00, 0x11, 0x61, 0x11, 0x29, 0x00, - 0x28, 0x00, 0x02, 0x11, 0x61, 0x11, 0x29, 0x00, 0x28, 0x00, 0x05, 0x11, - 0x61, 0x11, 0x29, 0x00, 0x28, 0x00, 0x09, 0x11, 0x61, 0x11, 0x29, 0x00, - 0x28, 0x00, 0x0b, 0x11, 0x61, 0x11, 0x29, 0x00, 0x28, 0x00, 0x0e, 0x11, - 0x61, 0x11, 0x29, 0x00, 0x28, 0x00, 0x0c, 0x11, 0x6e, 0x11, 0x29, 0x00, - 0x28, 0x00, 0x0b, 0x11, 0x69, 0x11, 0x0c, 0x11, 0x65, 0x11, 0xab, 0x11, - 0x29, 0x00, 0x28, 0x00, 0x0b, 0x11, 0x69, 0x11, 0x12, 0x11, 0x6e, 0x11, - 0x29, 0x00, 0x28, 0x00, 0x29, 0x00, 0x00, 0x4e, 0x8c, 0x4e, 0x09, 0x4e, - 0xdb, 0x56, 0x94, 0x4e, 0x6d, 0x51, 0x03, 0x4e, 0x6b, 0x51, 0x5d, 0x4e, - 0x41, 0x53, 0x08, 0x67, 0x6b, 0x70, 0x34, 0x6c, 0x28, 0x67, 0xd1, 0x91, - 0x1f, 0x57, 0xe5, 0x65, 0x2a, 0x68, 0x09, 0x67, 0x3e, 0x79, 0x0d, 0x54, - 0x79, 0x72, 0xa1, 0x8c, 0x5d, 0x79, 0xb4, 0x52, 0xe3, 0x4e, 0x7c, 0x54, - 0x66, 0x5b, 0xe3, 0x76, 0x01, 0x4f, 0xc7, 0x8c, 0x54, 0x53, 0x6d, 0x79, - 0x11, 0x4f, 0xea, 0x81, 0xf3, 0x81, 0x4f, 0x55, 0x7c, 0x5e, 0x87, 0x65, - 0x8f, 0x7b, 0x50, 0x54, 0x45, 0x32, 0x00, 0x31, 0x00, 0x33, 0x00, 0x30, - 0x00, 0x00, 0x11, 0x00, 0x02, 0x03, 0x05, 0x06, 0x07, 0x09, 0x0b, 0x0c, - 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x00, 0x11, 0x00, 0x61, 0x02, 0x61, 0x03, - 0x61, 0x05, 0x61, 0x06, 0x61, 0x07, 0x61, 0x09, 0x61, 0x0b, 0x61, 0x0c, - 0x61, 0x0e, 0x11, 0x61, 0x11, 0x00, 0x11, 0x0e, 0x61, 0xb7, 0x00, 0x69, - 0x0b, 0x11, 0x01, 0x63, 0x00, 0x69, 0x0b, 0x11, 0x6e, 0x11, 0x00, 0x4e, - 0x8c, 0x4e, 0x09, 0x4e, 0xdb, 0x56, 0x94, 0x4e, 0x6d, 0x51, 0x03, 0x4e, - 0x6b, 0x51, 0x5d, 0x4e, 0x41, 0x53, 0x08, 0x67, 0x6b, 0x70, 0x34, 0x6c, - 0x28, 0x67, 0xd1, 0x91, 0x1f, 0x57, 0xe5, 0x65, 0x2a, 0x68, 0x09, 0x67, - 0x3e, 0x79, 0x0d, 0x54, 0x79, 0x72, 0xa1, 0x8c, 0x5d, 0x79, 0xb4, 0x52, - 0xd8, 0x79, 0x37, 0x75, 0x73, 0x59, 0x69, 0x90, 0x2a, 0x51, 0x70, 0x53, - 0xe8, 0x6c, 0x05, 0x98, 0x11, 0x4f, 0x99, 0x51, 0x63, 0x6b, 0x0a, 0x4e, - 0x2d, 0x4e, 0x0b, 0x4e, 0xe6, 0x5d, 0xf3, 0x53, 0x3b, 0x53, 0x97, 0x5b, - 0x66, 0x5b, 0xe3, 0x76, 0x01, 0x4f, 0xc7, 0x8c, 0x54, 0x53, 0x1c, 0x59, - 0x33, 0x00, 0x36, 0x00, 0x34, 0x00, 0x30, 0x00, 0x35, 0x30, 0x31, 0x00, - 0x08, 0x67, 0x31, 0x00, 0x30, 0x00, 0x08, 0x67, 0x48, 0x67, 0x65, 0x72, - 0x67, 0x65, 0x56, 0x4c, 0x54, 0x44, 0xa2, 0x30, 0x00, 0x02, 0x04, 0x06, - 0x08, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, - 0x1f, 0x22, 0x24, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x30, 0x33, - 0x36, 0x39, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x42, 0x44, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x4b, 0x4d, 0x4e, 0x4f, 0x50, 0xe4, 0x4e, 0x8c, 0x54, 0xa1, - 0x30, 0x01, 0x30, 0x5b, 0x27, 0x01, 0x4a, 0x34, 0x00, 0x01, 0x52, 0x39, - 0x01, 0xa2, 0x30, 0x00, 0x5a, 0x49, 0xa4, 0x30, 0x00, 0x27, 0x4f, 0x0c, - 0xa4, 0x30, 0x00, 0x4f, 0x1d, 0x02, 0x05, 0x4f, 0xa8, 0x30, 0x00, 0x11, - 0x07, 0x54, 0x21, 0xa8, 0x30, 0x00, 0x54, 0x03, 0x54, 0xa4, 0x30, 0x06, - 0x4f, 0x15, 0x06, 0x58, 0x3c, 0x07, 0x00, 0x46, 0xab, 0x30, 0x00, 0x3e, - 0x18, 0x1d, 0x00, 0x42, 0x3f, 0x51, 0xac, 0x30, 0x00, 0x41, 0x47, 0x00, - 0x47, 0x32, 0xae, 0x30, 0xac, 0x30, 0xae, 0x30, 0x00, 0x1d, 0x4e, 0xad, - 0x30, 0x00, 0x38, 0x3d, 0x4f, 0x01, 0x3e, 0x13, 0x4f, 0xad, 0x30, 0xed, - 0x30, 0xad, 0x30, 0x00, 0x40, 0x03, 0x3c, 0x33, 0xad, 0x30, 0x00, 0x40, - 0x34, 0x4f, 0x1b, 0x3e, 0xad, 0x30, 0x00, 0x40, 0x42, 0x16, 0x1b, 0xb0, - 0x30, 0x00, 0x39, 0x30, 0xa4, 0x30, 0x0c, 0x45, 0x3c, 0x24, 0x4f, 0x0b, - 0x47, 0x18, 0x00, 0x49, 0xaf, 0x30, 0x00, 0x3e, 0x4d, 0x1e, 0xb1, 0x30, - 0x00, 0x4b, 0x08, 0x02, 0x3a, 0x19, 0x02, 0x4b, 0x2c, 0xa4, 0x30, 0x11, - 0x00, 0x0b, 0x47, 0xb5, 0x30, 0x00, 0x3e, 0x0c, 0x47, 0x2b, 0xb0, 0x30, - 0x07, 0x3a, 0x43, 0x00, 0xb9, 0x30, 0x02, 0x3a, 0x08, 0x02, 0x3a, 0x0f, - 0x07, 0x43, 0x00, 0xb7, 0x30, 0x10, 0x00, 0x12, 0x34, 0x11, 0x3c, 0x13, - 0x17, 0xa4, 0x30, 0x2a, 0x1f, 0x24, 0x2b, 0x00, 0x20, 0xbb, 0x30, 0x16, - 0x41, 0x00, 0x38, 0x0d, 0xc4, 0x30, 0x0d, 0x38, 0x00, 0xd0, 0x30, 0x00, - 0x2c, 0x1c, 0x1b, 0xa2, 0x30, 0x32, 0x00, 0x17, 0x26, 0x49, 0xaf, 0x30, - 0x25, 0x00, 0x3c, 0xb3, 0x30, 0x21, 0x00, 0x20, 0x38, 0xa1, 0x30, 0x34, - 0x00, 0x48, 0x22, 0x28, 0xa3, 0x30, 0x32, 0x00, 0x59, 0x25, 0xa7, 0x30, - 0x2f, 0x1c, 0x10, 0x00, 0x44, 0xd5, 0x30, 0x00, 0x14, 0x1e, 0xaf, 0x30, - 0x29, 0x00, 0x10, 0x4d, 0x3c, 0xda, 0x30, 0xbd, 0x30, 0xb8, 0x30, 0x22, - 0x13, 0x1a, 0x20, 0x33, 0x0c, 0x22, 0x3b, 0x01, 0x22, 0x44, 0x00, 0x21, - 0x44, 0x07, 0xa4, 0x30, 0x39, 0x00, 0x4f, 0x24, 0xc8, 0x30, 0x14, 0x23, - 0x00, 0xdb, 0x30, 0xf3, 0x30, 0xc9, 0x30, 0x14, 0x2a, 0x00, 0x12, 0x33, - 0x22, 0x12, 0x33, 0x2a, 0xa4, 0x30, 0x3a, 0x00, 0x0b, 0x49, 0xa4, 0x30, - 0x3a, 0x00, 0x47, 0x3a, 0x1f, 0x2b, 0x3a, 0x47, 0x0b, 0xb7, 0x30, 0x27, - 0x3c, 0x00, 0x30, 0x3c, 0xaf, 0x30, 0x30, 0x00, 0x3e, 0x44, 0xdf, 0x30, - 0xea, 0x30, 0xd0, 0x30, 0x0f, 0x1a, 0x00, 0x2c, 0x1b, 0xe1, 0x30, 0xac, - 0x30, 0xac, 0x30, 0x35, 0x00, 0x1c, 0x47, 0x35, 0x50, 0x1c, 0x3f, 0xa2, - 0x30, 0x42, 0x5a, 0x27, 0x42, 0x5a, 0x49, 0x44, 0x00, 0x51, 0xc3, 0x30, - 0x27, 0x00, 0x05, 0x28, 0xea, 0x30, 0xe9, 0x30, 0xd4, 0x30, 0x17, 0x00, - 0x28, 0xd6, 0x30, 0x15, 0x26, 0x00, 0x15, 0xec, 0x30, 0xe0, 0x30, 0xb2, - 0x30, 0x3a, 0x41, 0x16, 0x00, 0x41, 0xc3, 0x30, 0x2c, 0x00, 0x05, 0x30, - 0x00, 0xb9, 0x70, 0x31, 0x00, 0x30, 0x00, 0xb9, 0x70, 0x32, 0x00, 0x30, - 0x00, 0xb9, 0x70, 0x68, 0x50, 0x61, 0x64, 0x61, 0x41, 0x55, 0x62, 0x61, - 0x72, 0x6f, 0x56, 0x70, 0x63, 0x64, 0x6d, 0x64, 0x00, 0x6d, 0x00, 0xb2, - 0x00, 0x49, 0x00, 0x55, 0x00, 0x73, 0x5e, 0x10, 0x62, 0x2d, 0x66, 0x8c, - 0x54, 0x27, 0x59, 0x63, 0x6b, 0x0e, 0x66, 0xbb, 0x6c, 0x2a, 0x68, 0x0f, - 0x5f, 0x1a, 0x4f, 0x3e, 0x79, 0x70, 0x00, 0x41, 0x6e, 0x00, 0x41, 0xbc, - 0x03, 0x41, 0x6d, 0x00, 0x41, 0x6b, 0x00, 0x41, 0x4b, 0x00, 0x42, 0x4d, - 0x00, 0x42, 0x47, 0x00, 0x42, 0x63, 0x61, 0x6c, 0x6b, 0x63, 0x61, 0x6c, - 0x70, 0x00, 0x46, 0x6e, 0x00, 0x46, 0xbc, 0x03, 0x46, 0xbc, 0x03, 0x67, - 0x6d, 0x00, 0x67, 0x6b, 0x00, 0x67, 0x48, 0x00, 0x7a, 0x6b, 0x48, 0x7a, - 0x4d, 0x48, 0x7a, 0x47, 0x48, 0x7a, 0x54, 0x48, 0x7a, 0xbc, 0x03, 0x13, - 0x21, 0x6d, 0x00, 0x13, 0x21, 0x64, 0x00, 0x13, 0x21, 0x6b, 0x00, 0x13, - 0x21, 0x66, 0x00, 0x6d, 0x6e, 0x00, 0x6d, 0xbc, 0x03, 0x6d, 0x6d, 0x00, - 0x6d, 0x63, 0x00, 0x6d, 0x6b, 0x00, 0x6d, 0x63, 0x00, 0x0a, 0x0a, 0x4f, - 0x00, 0x0a, 0x4f, 0x6d, 0x00, 0xb2, 0x00, 0x63, 0x00, 0x08, 0x0a, 0x4f, - 0x0a, 0x0a, 0x50, 0x00, 0x0a, 0x50, 0x6d, 0x00, 0xb3, 0x00, 0x6b, 0x00, - 0x6d, 0x00, 0xb3, 0x00, 0x6d, 0x00, 0x15, 0x22, 0x73, 0x00, 0x6d, 0x00, - 0x15, 0x22, 0x73, 0x00, 0xb2, 0x00, 0x50, 0x61, 0x6b, 0x50, 0x61, 0x4d, - 0x50, 0x61, 0x47, 0x50, 0x61, 0x72, 0x61, 0x64, 0x72, 0x61, 0x64, 0xd1, - 0x73, 0x72, 0x00, 0x61, 0x00, 0x64, 0x00, 0x15, 0x22, 0x73, 0x00, 0xb2, - 0x00, 0x70, 0x00, 0x73, 0x6e, 0x00, 0x73, 0xbc, 0x03, 0x73, 0x6d, 0x00, - 0x73, 0x70, 0x00, 0x56, 0x6e, 0x00, 0x56, 0xbc, 0x03, 0x56, 0x6d, 0x00, - 0x56, 0x6b, 0x00, 0x56, 0x4d, 0x00, 0x56, 0x70, 0x00, 0x57, 0x6e, 0x00, - 0x57, 0xbc, 0x03, 0x57, 0x6d, 0x00, 0x57, 0x6b, 0x00, 0x57, 0x4d, 0x00, - 0x57, 0x6b, 0x00, 0xa9, 0x03, 0x4d, 0x00, 0xa9, 0x03, 0x61, 0x2e, 0x6d, - 0x2e, 0x42, 0x71, 0x63, 0x63, 0x63, 0x64, 0x43, 0xd1, 0x6b, 0x67, 0x43, - 0x6f, 0x2e, 0x64, 0x42, 0x47, 0x79, 0x68, 0x61, 0x48, 0x50, 0x69, 0x6e, - 0x4b, 0x4b, 0x4b, 0x4d, 0x6b, 0x74, 0x6c, 0x6d, 0x6c, 0x6e, 0x6c, 0x6f, - 0x67, 0x6c, 0x78, 0x6d, 0x62, 0x6d, 0x69, 0x6c, 0x6d, 0x6f, 0x6c, 0x50, - 0x48, 0x70, 0x2e, 0x6d, 0x2e, 0x50, 0x50, 0x4d, 0x50, 0x52, 0x73, 0x72, - 0x53, 0x76, 0x57, 0x62, 0x56, 0xd1, 0x6d, 0x41, 0xd1, 0x6d, 0x31, 0x00, - 0xe5, 0x65, 0x31, 0x00, 0x30, 0x00, 0xe5, 0x65, 0x32, 0x00, 0x30, 0x00, - 0xe5, 0x65, 0x33, 0x00, 0x30, 0x00, 0xe5, 0x65, 0x67, 0x61, 0x6c, 0x4a, - 0x04, 0x4c, 0x04, 0x26, 0x01, 0x53, 0x01, 0x27, 0xa7, 0x37, 0xab, 0x6b, - 0x02, 0x52, 0xab, 0x48, 0x8c, 0xf4, 0x66, 0xca, 0x8e, 0xc8, 0x8c, 0xd1, - 0x6e, 0x32, 0x4e, 0xe5, 0x53, 0x9c, 0x9f, 0x9c, 0x9f, 0x51, 0x59, 0xd1, - 0x91, 0x87, 0x55, 0x48, 0x59, 0xf6, 0x61, 0x69, 0x76, 0x85, 0x7f, 0x3f, - 0x86, 0xba, 0x87, 0xf8, 0x88, 0x8f, 0x90, 0x02, 0x6a, 0x1b, 0x6d, 0xd9, - 0x70, 0xde, 0x73, 0x3d, 0x84, 0x6a, 0x91, 0xf1, 0x99, 0x82, 0x4e, 0x75, - 0x53, 0x04, 0x6b, 0x1b, 0x72, 0x2d, 0x86, 0x1e, 0x9e, 0x50, 0x5d, 0xeb, - 0x6f, 0xcd, 0x85, 0x64, 0x89, 0xc9, 0x62, 0xd8, 0x81, 0x1f, 0x88, 0xca, - 0x5e, 0x17, 0x67, 0x6a, 0x6d, 0xfc, 0x72, 0xce, 0x90, 0x86, 0x4f, 0xb7, - 0x51, 0xde, 0x52, 0xc4, 0x64, 0xd3, 0x6a, 0x10, 0x72, 0xe7, 0x76, 0x01, - 0x80, 0x06, 0x86, 0x5c, 0x86, 0xef, 0x8d, 0x32, 0x97, 0x6f, 0x9b, 0xfa, - 0x9d, 0x8c, 0x78, 0x7f, 0x79, 0xa0, 0x7d, 0xc9, 0x83, 0x04, 0x93, 0x7f, - 0x9e, 0xd6, 0x8a, 0xdf, 0x58, 0x04, 0x5f, 0x60, 0x7c, 0x7e, 0x80, 0x62, - 0x72, 0xca, 0x78, 0xc2, 0x8c, 0xf7, 0x96, 0xd8, 0x58, 0x62, 0x5c, 0x13, - 0x6a, 0xda, 0x6d, 0x0f, 0x6f, 0x2f, 0x7d, 0x37, 0x7e, 0x4b, 0x96, 0xd2, - 0x52, 0x8b, 0x80, 0xdc, 0x51, 0xcc, 0x51, 0x1c, 0x7a, 0xbe, 0x7d, 0xf1, - 0x83, 0x75, 0x96, 0x80, 0x8b, 0xcf, 0x62, 0x02, 0x6a, 0xfe, 0x8a, 0x39, - 0x4e, 0xe7, 0x5b, 0x12, 0x60, 0x87, 0x73, 0x70, 0x75, 0x17, 0x53, 0xfb, - 0x78, 0xbf, 0x4f, 0xa9, 0x5f, 0x0d, 0x4e, 0xcc, 0x6c, 0x78, 0x65, 0x22, - 0x7d, 0xc3, 0x53, 0x5e, 0x58, 0x01, 0x77, 0x49, 0x84, 0xaa, 0x8a, 0xba, - 0x6b, 0xb0, 0x8f, 0x88, 0x6c, 0xfe, 0x62, 0xe5, 0x82, 0xa0, 0x63, 0x65, - 0x75, 0xae, 0x4e, 0x69, 0x51, 0xc9, 0x51, 0x81, 0x68, 0xe7, 0x7c, 0x6f, - 0x82, 0xd2, 0x8a, 0xcf, 0x91, 0xf5, 0x52, 0x42, 0x54, 0x73, 0x59, 0xec, - 0x5e, 0xc5, 0x65, 0xfe, 0x6f, 0x2a, 0x79, 0xad, 0x95, 0x6a, 0x9a, 0x97, - 0x9e, 0xce, 0x9e, 0x9b, 0x52, 0xc6, 0x66, 0x77, 0x6b, 0x62, 0x8f, 0x74, - 0x5e, 0x90, 0x61, 0x00, 0x62, 0x9a, 0x64, 0x23, 0x6f, 0x49, 0x71, 0x89, - 0x74, 0xca, 0x79, 0xf4, 0x7d, 0x6f, 0x80, 0x26, 0x8f, 0xee, 0x84, 0x23, - 0x90, 0x4a, 0x93, 0x17, 0x52, 0xa3, 0x52, 0xbd, 0x54, 0xc8, 0x70, 0xc2, - 0x88, 0xaa, 0x8a, 0xc9, 0x5e, 0xf5, 0x5f, 0x7b, 0x63, 0xae, 0x6b, 0x3e, - 0x7c, 0x75, 0x73, 0xe4, 0x4e, 0xf9, 0x56, 0xe7, 0x5b, 0xba, 0x5d, 0x1c, - 0x60, 0xb2, 0x73, 0x69, 0x74, 0x9a, 0x7f, 0x46, 0x80, 0x34, 0x92, 0xf6, - 0x96, 0x48, 0x97, 0x18, 0x98, 0x8b, 0x4f, 0xae, 0x79, 0xb4, 0x91, 0xb8, - 0x96, 0xe1, 0x60, 0x86, 0x4e, 0xda, 0x50, 0xee, 0x5b, 0x3f, 0x5c, 0x99, - 0x65, 0x02, 0x6a, 0xce, 0x71, 0x42, 0x76, 0xfc, 0x84, 0x7c, 0x90, 0x8d, - 0x9f, 0x88, 0x66, 0x2e, 0x96, 0x89, 0x52, 0x7b, 0x67, 0xf3, 0x67, 0x41, - 0x6d, 0x9c, 0x6e, 0x09, 0x74, 0x59, 0x75, 0x6b, 0x78, 0x10, 0x7d, 0x5e, - 0x98, 0x6d, 0x51, 0x2e, 0x62, 0x78, 0x96, 0x2b, 0x50, 0x19, 0x5d, 0xea, - 0x6d, 0x2a, 0x8f, 0x8b, 0x5f, 0x44, 0x61, 0x17, 0x68, 0x87, 0x73, 0x86, - 0x96, 0x29, 0x52, 0x0f, 0x54, 0x65, 0x5c, 0x13, 0x66, 0x4e, 0x67, 0xa8, - 0x68, 0xe5, 0x6c, 0x06, 0x74, 0xe2, 0x75, 0x79, 0x7f, 0xcf, 0x88, 0xe1, - 0x88, 0xcc, 0x91, 0xe2, 0x96, 0x3f, 0x53, 0xba, 0x6e, 0x1d, 0x54, 0xd0, - 0x71, 0x98, 0x74, 0xfa, 0x85, 0xa3, 0x96, 0x57, 0x9c, 0x9f, 0x9e, 0x97, - 0x67, 0xcb, 0x6d, 0xe8, 0x81, 0xcb, 0x7a, 0x20, 0x7b, 0x92, 0x7c, 0xc0, - 0x72, 0x99, 0x70, 0x58, 0x8b, 0xc0, 0x4e, 0x36, 0x83, 0x3a, 0x52, 0x07, - 0x52, 0xa6, 0x5e, 0xd3, 0x62, 0xd6, 0x7c, 0x85, 0x5b, 0x1e, 0x6d, 0xb4, - 0x66, 0x3b, 0x8f, 0x4c, 0x88, 0x4d, 0x96, 0x8b, 0x89, 0xd3, 0x5e, 0x40, - 0x51, 0xc0, 0x55, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x58, 0x00, 0x00, 0x74, - 0x66, 0x00, 0x00, 0x00, 0x00, 0xde, 0x51, 0x2a, 0x73, 0xca, 0x76, 0x3c, - 0x79, 0x5e, 0x79, 0x65, 0x79, 0x8f, 0x79, 0x56, 0x97, 0xbe, 0x7c, 0xbd, - 0x7f, 0x00, 0x00, 0x12, 0x86, 0x00, 0x00, 0xf8, 0x8a, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x90, 0xfd, 0x90, 0xef, 0x98, 0xfc, 0x98, 0x28, 0x99, 0xb4, - 0x9d, 0xde, 0x90, 0xb7, 0x96, 0xae, 0x4f, 0xe7, 0x50, 0x4d, 0x51, 0xc9, - 0x52, 0xe4, 0x52, 0x51, 0x53, 0x9d, 0x55, 0x06, 0x56, 0x68, 0x56, 0x40, - 0x58, 0xa8, 0x58, 0x64, 0x5c, 0x6e, 0x5c, 0x94, 0x60, 0x68, 0x61, 0x8e, - 0x61, 0xf2, 0x61, 0x4f, 0x65, 0xe2, 0x65, 0x91, 0x66, 0x85, 0x68, 0x77, - 0x6d, 0x1a, 0x6e, 0x22, 0x6f, 0x6e, 0x71, 0x2b, 0x72, 0x22, 0x74, 0x91, - 0x78, 0x3e, 0x79, 0x49, 0x79, 0x48, 0x79, 0x50, 0x79, 0x56, 0x79, 0x5d, - 0x79, 0x8d, 0x79, 0x8e, 0x79, 0x40, 0x7a, 0x81, 0x7a, 0xc0, 0x7b, 0xf4, - 0x7d, 0x09, 0x7e, 0x41, 0x7e, 0x72, 0x7f, 0x05, 0x80, 0xed, 0x81, 0x79, - 0x82, 0x79, 0x82, 0x57, 0x84, 0x10, 0x89, 0x96, 0x89, 0x01, 0x8b, 0x39, - 0x8b, 0xd3, 0x8c, 0x08, 0x8d, 0xb6, 0x8f, 0x38, 0x90, 0xe3, 0x96, 0xff, - 0x97, 0x3b, 0x98, 0x75, 0x60, 0xee, 0x42, 0x18, 0x82, 0x02, 0x26, 0x4e, - 0xb5, 0x51, 0x68, 0x51, 0x80, 0x4f, 0x45, 0x51, 0x80, 0x51, 0xc7, 0x52, - 0xfa, 0x52, 0x9d, 0x55, 0x55, 0x55, 0x99, 0x55, 0xe2, 0x55, 0x5a, 0x58, - 0xb3, 0x58, 0x44, 0x59, 0x54, 0x59, 0x62, 0x5a, 0x28, 0x5b, 0xd2, 0x5e, - 0xd9, 0x5e, 0x69, 0x5f, 0xad, 0x5f, 0xd8, 0x60, 0x4e, 0x61, 0x08, 0x61, - 0x8e, 0x61, 0x60, 0x61, 0xf2, 0x61, 0x34, 0x62, 0xc4, 0x63, 0x1c, 0x64, - 0x52, 0x64, 0x56, 0x65, 0x74, 0x66, 0x17, 0x67, 0x1b, 0x67, 0x56, 0x67, - 0x79, 0x6b, 0xba, 0x6b, 0x41, 0x6d, 0xdb, 0x6e, 0xcb, 0x6e, 0x22, 0x6f, - 0x1e, 0x70, 0x6e, 0x71, 0xa7, 0x77, 0x35, 0x72, 0xaf, 0x72, 0x2a, 0x73, - 0x71, 0x74, 0x06, 0x75, 0x3b, 0x75, 0x1d, 0x76, 0x1f, 0x76, 0xca, 0x76, - 0xdb, 0x76, 0xf4, 0x76, 0x4a, 0x77, 0x40, 0x77, 0xcc, 0x78, 0xb1, 0x7a, - 0xc0, 0x7b, 0x7b, 0x7c, 0x5b, 0x7d, 0xf4, 0x7d, 0x3e, 0x7f, 0x05, 0x80, - 0x52, 0x83, 0xef, 0x83, 0x79, 0x87, 0x41, 0x89, 0x86, 0x89, 0x96, 0x89, - 0xbf, 0x8a, 0xf8, 0x8a, 0xcb, 0x8a, 0x01, 0x8b, 0xfe, 0x8a, 0xed, 0x8a, - 0x39, 0x8b, 0x8a, 0x8b, 0x08, 0x8d, 0x38, 0x8f, 0x72, 0x90, 0x99, 0x91, - 0x76, 0x92, 0x7c, 0x96, 0xe3, 0x96, 0x56, 0x97, 0xdb, 0x97, 0xff, 0x97, - 0x0b, 0x98, 0x3b, 0x98, 0x12, 0x9b, 0x9c, 0x9f, 0x4a, 0x28, 0x44, 0x28, - 0xd5, 0x33, 0x9d, 0x3b, 0x18, 0x40, 0x39, 0x40, 0x49, 0x52, 0xd0, 0x5c, - 0xd3, 0x7e, 0x43, 0x9f, 0x8e, 0x9f, 0x2a, 0xa0, 0x02, 0x66, 0x66, 0x66, - 0x69, 0x66, 0x6c, 0x66, 0x66, 0x69, 0x66, 0x66, 0x6c, 0x7f, 0x01, 0x74, - 0x73, 0x00, 0x74, 0x65, 0x05, 0x0f, 0x11, 0x0f, 0x00, 0x0f, 0x06, 0x19, - 0x11, 0x0f, 0x08, 0xd9, 0x05, 0xb4, 0x05, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0x05, 0xb7, 0x05, 0xd0, 0x05, 0x12, 0x00, 0x03, 0x04, 0x0b, 0x0c, 0x0d, - 0x18, 0x1a, 0xe9, 0x05, 0xc1, 0x05, 0xe9, 0x05, 0xc2, 0x05, 0x49, 0xfb, - 0xc1, 0x05, 0x49, 0xfb, 0xc2, 0x05, 0xd0, 0x05, 0xb7, 0x05, 0xd0, 0x05, - 0xb8, 0x05, 0xd0, 0x05, 0xbc, 0x05, 0xd8, 0x05, 0xbc, 0x05, 0xde, 0x05, - 0xbc, 0x05, 0xe0, 0x05, 0xbc, 0x05, 0xe3, 0x05, 0xbc, 0x05, 0xb9, 0x05, - 0x2d, 0x03, 0x2e, 0x03, 0x2f, 0x03, 0x30, 0x03, 0x31, 0x03, 0x1c, 0x00, - 0x18, 0x06, 0x22, 0x06, 0x2b, 0x06, 0xd0, 0x05, 0xdc, 0x05, 0x71, 0x06, - 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0d, 0x0d, 0x0d, 0x0d, 0x0f, 0x0f, - 0x0f, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x0e, 0x0e, 0x0e, 0x0e, 0x08, 0x08, - 0x08, 0x08, 0x33, 0x33, 0x33, 0x33, 0x35, 0x35, 0x35, 0x35, 0x13, 0x13, - 0x13, 0x13, 0x12, 0x12, 0x12, 0x12, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, - 0x16, 0x16, 0x1c, 0x1c, 0x1b, 0x1b, 0x1d, 0x1d, 0x17, 0x17, 0x27, 0x27, - 0x20, 0x20, 0x38, 0x38, 0x38, 0x38, 0x3e, 0x3e, 0x3e, 0x3e, 0x42, 0x42, - 0x42, 0x42, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x4a, 0x4a, 0x4a, 0x4a, - 0x4f, 0x4f, 0x50, 0x50, 0x50, 0x50, 0x4d, 0x4d, 0x4d, 0x4d, 0x61, 0x61, - 0x62, 0x62, 0x49, 0x06, 0x64, 0x64, 0x64, 0x64, 0x7e, 0x7e, 0x7d, 0x7d, - 0x7f, 0x7f, 0x2e, 0x82, 0x82, 0x7c, 0x7c, 0x80, 0x80, 0x87, 0x87, 0x87, - 0x87, 0x00, 0x00, 0x26, 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0xaf, 0x00, - 0xaf, 0x00, 0x22, 0x00, 0x22, 0x00, 0xa1, 0x00, 0xa1, 0x00, 0xa0, 0x00, - 0xa0, 0x00, 0xa2, 0x00, 0xa2, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, - 0x23, 0x00, 0x23, 0x00, 0x23, 0xcc, 0x06, 0x00, 0x00, 0x00, 0x00, 0x26, - 0x06, 0x00, 0x06, 0x00, 0x07, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x24, 0x02, - 0x06, 0x02, 0x07, 0x02, 0x08, 0x02, 0x1f, 0x02, 0x23, 0x02, 0x24, 0x04, - 0x06, 0x04, 0x07, 0x04, 0x08, 0x04, 0x1f, 0x04, 0x23, 0x04, 0x24, 0x05, - 0x06, 0x05, 0x1f, 0x05, 0x23, 0x05, 0x24, 0x06, 0x07, 0x06, 0x1f, 0x07, - 0x06, 0x07, 0x1f, 0x08, 0x06, 0x08, 0x07, 0x08, 0x1f, 0x0d, 0x06, 0x0d, - 0x07, 0x0d, 0x08, 0x0d, 0x1f, 0x0f, 0x07, 0x0f, 0x1f, 0x10, 0x06, 0x10, - 0x07, 0x10, 0x08, 0x10, 0x1f, 0x11, 0x07, 0x11, 0x1f, 0x12, 0x1f, 0x13, - 0x06, 0x13, 0x1f, 0x14, 0x06, 0x14, 0x1f, 0x1b, 0x06, 0x1b, 0x07, 0x1b, - 0x08, 0x1b, 0x1f, 0x1b, 0x23, 0x1b, 0x24, 0x1c, 0x07, 0x1c, 0x1f, 0x1c, - 0x23, 0x1c, 0x24, 0x1d, 0x01, 0x1d, 0x06, 0x1d, 0x07, 0x1d, 0x08, 0x1d, - 0x1e, 0x1d, 0x1f, 0x1d, 0x23, 0x1d, 0x24, 0x1e, 0x06, 0x1e, 0x07, 0x1e, - 0x08, 0x1e, 0x1f, 0x1e, 0x23, 0x1e, 0x24, 0x1f, 0x06, 0x1f, 0x07, 0x1f, - 0x08, 0x1f, 0x1f, 0x1f, 0x23, 0x1f, 0x24, 0x20, 0x06, 0x20, 0x07, 0x20, - 0x08, 0x20, 0x1f, 0x20, 0x23, 0x20, 0x24, 0x21, 0x06, 0x21, 0x1f, 0x21, - 0x23, 0x21, 0x24, 0x24, 0x06, 0x24, 0x07, 0x24, 0x08, 0x24, 0x1f, 0x24, - 0x23, 0x24, 0x24, 0x0a, 0x4a, 0x0b, 0x4a, 0x23, 0x4a, 0x20, 0x00, 0x4c, - 0x06, 0x51, 0x06, 0x51, 0x06, 0xff, 0x00, 0x1f, 0x26, 0x06, 0x00, 0x0b, - 0x00, 0x0c, 0x00, 0x1f, 0x00, 0x20, 0x00, 0x23, 0x00, 0x24, 0x02, 0x0b, - 0x02, 0x0c, 0x02, 0x1f, 0x02, 0x20, 0x02, 0x23, 0x02, 0x24, 0x04, 0x0b, - 0x04, 0x0c, 0x04, 0x1f, 0x26, 0x06, 0x04, 0x20, 0x04, 0x23, 0x04, 0x24, - 0x05, 0x0b, 0x05, 0x0c, 0x05, 0x1f, 0x05, 0x20, 0x05, 0x23, 0x05, 0x24, - 0x1b, 0x23, 0x1b, 0x24, 0x1c, 0x23, 0x1c, 0x24, 0x1d, 0x01, 0x1d, 0x1e, - 0x1d, 0x1f, 0x1d, 0x23, 0x1d, 0x24, 0x1e, 0x1f, 0x1e, 0x23, 0x1e, 0x24, - 0x1f, 0x01, 0x1f, 0x1f, 0x20, 0x0b, 0x20, 0x0c, 0x20, 0x1f, 0x20, 0x20, - 0x20, 0x23, 0x20, 0x24, 0x23, 0x4a, 0x24, 0x0b, 0x24, 0x0c, 0x24, 0x1f, - 0x24, 0x20, 0x24, 0x23, 0x24, 0x24, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, - 0x00, 0x1f, 0x00, 0x21, 0x02, 0x06, 0x02, 0x07, 0x02, 0x08, 0x02, 0x1f, - 0x02, 0x21, 0x04, 0x06, 0x04, 0x07, 0x04, 0x08, 0x04, 0x1f, 0x04, 0x21, - 0x05, 0x1f, 0x06, 0x07, 0x06, 0x1f, 0x07, 0x06, 0x07, 0x1f, 0x08, 0x06, - 0x08, 0x1f, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x08, 0x0d, 0x1f, 0x0f, 0x07, - 0x0f, 0x08, 0x0f, 0x1f, 0x10, 0x06, 0x10, 0x07, 0x10, 0x08, 0x10, 0x1f, - 0x11, 0x07, 0x12, 0x1f, 0x13, 0x06, 0x13, 0x1f, 0x14, 0x06, 0x14, 0x1f, - 0x1b, 0x06, 0x1b, 0x07, 0x1b, 0x08, 0x1b, 0x1f, 0x1c, 0x07, 0x1c, 0x1f, - 0x1d, 0x06, 0x1d, 0x07, 0x1d, 0x08, 0x1d, 0x1e, 0x1d, 0x1f, 0x1e, 0x06, - 0x1e, 0x07, 0x1e, 0x08, 0x1e, 0x1f, 0x1e, 0x21, 0x1f, 0x06, 0x1f, 0x07, - 0x1f, 0x08, 0x1f, 0x1f, 0x20, 0x06, 0x20, 0x07, 0x20, 0x08, 0x20, 0x1f, - 0x20, 0x21, 0x21, 0x06, 0x21, 0x1f, 0x21, 0x4a, 0x24, 0x06, 0x24, 0x07, - 0x24, 0x08, 0x24, 0x1f, 0x24, 0x21, 0x00, 0x1f, 0x00, 0x21, 0x02, 0x1f, - 0x02, 0x21, 0x04, 0x1f, 0x04, 0x21, 0x05, 0x1f, 0x05, 0x21, 0x0d, 0x1f, - 0x0d, 0x21, 0x0e, 0x1f, 0x0e, 0x21, 0x1d, 0x1e, 0x1d, 0x1f, 0x1e, 0x1f, - 0x20, 0x1f, 0x20, 0x21, 0x24, 0x1f, 0x24, 0x21, 0x40, 0x06, 0x4e, 0x06, - 0x51, 0x06, 0x27, 0x06, 0x10, 0x22, 0x10, 0x23, 0x12, 0x22, 0x12, 0x23, - 0x13, 0x22, 0x13, 0x23, 0x0c, 0x22, 0x0c, 0x23, 0x0d, 0x22, 0x0d, 0x23, - 0x06, 0x22, 0x06, 0x23, 0x05, 0x22, 0x05, 0x23, 0x07, 0x22, 0x07, 0x23, - 0x0e, 0x22, 0x0e, 0x23, 0x0f, 0x22, 0x0f, 0x23, 0x0d, 0x05, 0x0d, 0x06, - 0x0d, 0x07, 0x0d, 0x1e, 0x0d, 0x0a, 0x0c, 0x0a, 0x0e, 0x0a, 0x0f, 0x0a, - 0x10, 0x22, 0x10, 0x23, 0x12, 0x22, 0x12, 0x23, 0x13, 0x22, 0x13, 0x23, - 0x0c, 0x22, 0x0c, 0x23, 0x0d, 0x22, 0x0d, 0x23, 0x06, 0x22, 0x06, 0x23, - 0x05, 0x22, 0x05, 0x23, 0x07, 0x22, 0x07, 0x23, 0x0e, 0x22, 0x0e, 0x23, - 0x0f, 0x22, 0x0f, 0x23, 0x0d, 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x1e, - 0x0d, 0x0a, 0x0c, 0x0a, 0x0e, 0x0a, 0x0f, 0x0a, 0x0d, 0x05, 0x0d, 0x06, - 0x0d, 0x07, 0x0d, 0x1e, 0x0c, 0x20, 0x0d, 0x20, 0x10, 0x1e, 0x0c, 0x05, - 0x0c, 0x06, 0x0c, 0x07, 0x0d, 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x10, 0x1e, - 0x11, 0x1e, 0x00, 0x24, 0x00, 0x24, 0x2a, 0x06, 0x00, 0x02, 0x1b, 0x00, - 0x03, 0x02, 0x00, 0x03, 0x02, 0x00, 0x03, 0x1b, 0x00, 0x04, 0x1b, 0x00, - 0x1b, 0x02, 0x00, 0x1b, 0x03, 0x00, 0x1b, 0x04, 0x02, 0x1b, 0x03, 0x02, - 0x1b, 0x03, 0x03, 0x1b, 0x20, 0x03, 0x1b, 0x1f, 0x09, 0x03, 0x02, 0x09, - 0x02, 0x03, 0x09, 0x02, 0x1f, 0x09, 0x1b, 0x03, 0x09, 0x1b, 0x03, 0x09, - 0x1b, 0x02, 0x09, 0x1b, 0x1b, 0x09, 0x1b, 0x1b, 0x0b, 0x03, 0x03, 0x0b, - 0x03, 0x03, 0x0b, 0x1b, 0x1b, 0x0a, 0x03, 0x1b, 0x0a, 0x03, 0x1b, 0x0a, - 0x02, 0x20, 0x0a, 0x1b, 0x04, 0x0a, 0x1b, 0x04, 0x0a, 0x1b, 0x1b, 0x0a, - 0x1b, 0x1b, 0x0c, 0x03, 0x1f, 0x0c, 0x04, 0x1b, 0x0c, 0x04, 0x1b, 0x0d, - 0x1b, 0x03, 0x0d, 0x1b, 0x03, 0x0d, 0x1b, 0x1b, 0x0d, 0x1b, 0x20, 0x0f, - 0x02, 0x1b, 0x0f, 0x1b, 0x1b, 0x0f, 0x1b, 0x1b, 0x0f, 0x1b, 0x1f, 0x10, - 0x1b, 0x1b, 0x10, 0x1b, 0x20, 0x10, 0x1b, 0x1f, 0x17, 0x04, 0x1b, 0x17, - 0x04, 0x1b, 0x18, 0x1b, 0x03, 0x18, 0x1b, 0x1b, 0x1a, 0x03, 0x1b, 0x1a, - 0x03, 0x20, 0x1a, 0x03, 0x1f, 0x1a, 0x02, 0x02, 0x1a, 0x02, 0x02, 0x1a, - 0x04, 0x1b, 0x1a, 0x04, 0x1b, 0x1a, 0x1b, 0x03, 0x1a, 0x1b, 0x03, 0x1b, - 0x03, 0x02, 0x1b, 0x03, 0x1b, 0x1b, 0x03, 0x20, 0x1b, 0x02, 0x03, 0x1b, - 0x02, 0x1b, 0x1b, 0x04, 0x02, 0x1b, 0x04, 0x1b, 0x28, 0x06, 0x1d, 0x04, - 0x06, 0x1f, 0x1d, 0x04, 0x1f, 0x1d, 0x1d, 0x1e, 0x05, 0x1d, 0x1e, 0x05, - 0x21, 0x1e, 0x04, 0x1d, 0x1e, 0x04, 0x1d, 0x1e, 0x04, 0x21, 0x1e, 0x1d, - 0x22, 0x1e, 0x1d, 0x21, 0x22, 0x1d, 0x1d, 0x22, 0x1d, 0x1d, 0x00, 0x06, - 0x22, 0x02, 0x04, 0x22, 0x02, 0x04, 0x21, 0x02, 0x06, 0x22, 0x02, 0x06, - 0x21, 0x02, 0x1d, 0x22, 0x02, 0x1d, 0x21, 0x04, 0x1d, 0x22, 0x04, 0x05, - 0x21, 0x04, 0x1d, 0x21, 0x0b, 0x06, 0x21, 0x0d, 0x05, 0x22, 0x0c, 0x05, - 0x22, 0x0e, 0x05, 0x22, 0x1c, 0x04, 0x22, 0x1c, 0x1d, 0x22, 0x22, 0x05, - 0x22, 0x22, 0x04, 0x22, 0x22, 0x1d, 0x22, 0x1d, 0x1d, 0x22, 0x1a, 0x1d, - 0x22, 0x1e, 0x05, 0x22, 0x1a, 0x1d, 0x05, 0x1c, 0x05, 0x1d, 0x11, 0x1d, - 0x22, 0x1b, 0x1d, 0x22, 0x1e, 0x04, 0x05, 0x1d, 0x06, 0x22, 0x1c, 0x04, - 0x1d, 0x1b, 0x1d, 0x1d, 0x1c, 0x04, 0x1d, 0x1e, 0x04, 0x05, 0x04, 0x05, - 0x22, 0x05, 0x04, 0x22, 0x1d, 0x04, 0x22, 0x19, 0x1d, 0x22, 0x00, 0x05, - 0x22, 0x1b, 0x1d, 0x1d, 0x11, 0x04, 0x1d, 0x0d, 0x1d, 0x1d, 0x0b, 0x06, - 0x22, 0x1e, 0x04, 0x22, 0x35, 0x06, 0x00, 0x0f, 0x9d, 0x0d, 0x0f, 0x9d, - 0x27, 0x06, 0x00, 0x1d, 0x1d, 0x20, 0x00, 0x1c, 0x01, 0x0a, 0x1e, 0x06, - 0x1e, 0x08, 0x0e, 0x1d, 0x12, 0x1e, 0x0a, 0x0c, 0x21, 0x1d, 0x12, 0x1d, - 0x23, 0x20, 0x21, 0x0c, 0x1d, 0x1e, 0x35, 0x06, 0x00, 0x0f, 0x14, 0x27, - 0x06, 0x0e, 0x1d, 0x22, 0xff, 0x00, 0x1d, 0x1d, 0x20, 0xff, 0x12, 0x1d, - 0x23, 0x20, 0xff, 0x21, 0x0c, 0x1d, 0x1e, 0x27, 0x06, 0x05, 0x1d, 0xff, - 0x05, 0x1d, 0x00, 0x1d, 0x20, 0x27, 0x06, 0x0a, 0xa5, 0x00, 0x1d, 0x2c, - 0x00, 0x01, 0x30, 0x02, 0x30, 0x3a, 0x00, 0x3b, 0x00, 0x21, 0x00, 0x3f, - 0x00, 0x16, 0x30, 0x17, 0x30, 0x26, 0x20, 0x13, 0x20, 0x12, 0x01, 0x00, - 0x5f, 0x5f, 0x28, 0x29, 0x7b, 0x7d, 0x08, 0x30, 0x0c, 0x0d, 0x08, 0x09, - 0x02, 0x03, 0x00, 0x01, 0x04, 0x05, 0x06, 0x07, 0x5b, 0x00, 0x5d, 0x00, - 0x3e, 0x20, 0x3e, 0x20, 0x3e, 0x20, 0x3e, 0x20, 0x5f, 0x00, 0x5f, 0x00, - 0x5f, 0x00, 0x2c, 0x00, 0x01, 0x30, 0x2e, 0x00, 0x00, 0x00, 0x3b, 0x00, - 0x3a, 0x00, 0x3f, 0x00, 0x21, 0x00, 0x14, 0x20, 0x28, 0x00, 0x29, 0x00, - 0x7b, 0x00, 0x7d, 0x00, 0x14, 0x30, 0x15, 0x30, 0x23, 0x26, 0x2a, 0x2b, - 0x2d, 0x3c, 0x3e, 0x3d, 0x00, 0x5c, 0x24, 0x25, 0x40, 0x40, 0x06, 0xff, - 0x0b, 0x00, 0x0b, 0xff, 0x0c, 0x20, 0x00, 0x4d, 0x06, 0x40, 0x06, 0xff, - 0x0e, 0x00, 0x0e, 0xff, 0x0f, 0x00, 0x0f, 0xff, 0x10, 0x00, 0x10, 0xff, - 0x11, 0x00, 0x11, 0xff, 0x12, 0x00, 0x12, 0x21, 0x06, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, - 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, - 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, - 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, - 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, - 0x21, 0x21, 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x23, 0x24, 0x24, - 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26, 0x26, 0x27, 0x27, - 0x28, 0x28, 0x29, 0x29, 0x29, 0x29, 0x22, 0x06, 0x22, 0x00, 0x22, 0x00, - 0x22, 0x01, 0x22, 0x01, 0x22, 0x03, 0x22, 0x03, 0x22, 0x05, 0x22, 0x05, - 0x21, 0x00, 0x85, 0x29, 0x01, 0x30, 0x01, 0x0b, 0x0c, 0x00, 0xfa, 0xf1, - 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xe2, 0xe4, 0xe6, 0xc2, 0xfb, 0xa1, 0xa3, - 0xa5, 0xa7, 0xa9, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, - 0xbc, 0xbe, 0xc0, 0xc3, 0xc5, 0xc7, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, - 0xd1, 0xd4, 0xd7, 0xda, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe3, 0xe5, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xee, 0xf2, 0x98, 0x99, 0x31, 0x31, 0x4f, - 0x31, 0x55, 0x31, 0x5b, 0x31, 0x61, 0x31, 0xa2, 0x00, 0xa3, 0x00, 0xac, - 0x00, 0xaf, 0x00, 0xa6, 0x00, 0xa5, 0x00, 0xa9, 0x20, 0x00, 0x00, 0x02, - 0x25, 0x90, 0x21, 0x91, 0x21, 0x92, 0x21, 0x93, 0x21, 0xa0, 0x25, 0xcb, - 0x25, 0x99, 0x10, 0xba, 0x10, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x10, 0xba, - 0x10, 0x05, 0x05, 0xa5, 0x10, 0xba, 0x10, 0x05, 0x31, 0x11, 0x27, 0x11, - 0x32, 0x11, 0x27, 0x11, 0x55, 0x47, 0x13, 0x3e, 0x13, 0x47, 0x13, 0x57, - 0x13, 0x55, 0xb9, 0x14, 0xba, 0x14, 0xb9, 0x14, 0xb0, 0x14, 0x00, 0x00, - 0x00, 0x00, 0xb9, 0x14, 0xbd, 0x14, 0x55, 0x50, 0xb8, 0x15, 0xaf, 0x15, - 0xb9, 0x15, 0xaf, 0x15, 0x55, 0x57, 0xd1, 0x65, 0xd1, 0x58, 0xd1, 0x65, - 0xd1, 0x5f, 0xd1, 0x6e, 0xd1, 0x5f, 0xd1, 0x6f, 0xd1, 0x5f, 0xd1, 0x70, - 0xd1, 0x5f, 0xd1, 0x71, 0xd1, 0x5f, 0xd1, 0x72, 0xd1, 0x55, 0x55, 0x55, - 0x05, 0xb9, 0xd1, 0x65, 0xd1, 0xba, 0xd1, 0x65, 0xd1, 0xbb, 0xd1, 0x6e, - 0xd1, 0xbc, 0xd1, 0x6e, 0xd1, 0xbb, 0xd1, 0x6f, 0xd1, 0xbc, 0xd1, 0x6f, - 0xd1, 0x55, 0x55, 0x55, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, - 0x69, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x43, 0x44, 0x00, 0x00, - 0x47, 0x00, 0x00, 0x4a, 0x4b, 0x00, 0x00, 0x4e, 0x4f, 0x50, 0x51, 0x00, - 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, - 0x00, 0x66, 0x68, 0x00, 0x70, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x42, - 0x00, 0x44, 0x45, 0x46, 0x47, 0x4a, 0x00, 0x53, 0x00, 0x61, 0x00, 0x41, - 0x42, 0x00, 0x44, 0x45, 0x46, 0x47, 0x00, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, - 0x00, 0x4f, 0x53, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, - 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, - 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x31, 0x01, 0x37, 0x02, 0x91, 0x03, - 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, - 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, - 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, - 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, - 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, - 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x0b, 0x0c, 0x30, 0x00, - 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x27, 0x06, 0x00, 0x01, - 0x05, 0x08, 0x2a, 0x06, 0x1e, 0x08, 0x03, 0x0d, 0x20, 0x19, 0x1a, 0x1b, - 0x1c, 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00, 0x01, 0x04, 0x06, - 0x0c, 0x0e, 0x10, 0x44, 0x90, 0x77, 0x45, 0x28, 0x06, 0x2c, 0x06, 0x00, - 0x00, 0x47, 0x06, 0x33, 0x06, 0x17, 0x10, 0x11, 0x12, 0x13, 0x00, 0x06, - 0x0e, 0x02, 0x0f, 0x34, 0x06, 0x2a, 0x06, 0x2b, 0x06, 0x2e, 0x06, 0x00, - 0x00, 0x36, 0x06, 0x00, 0x00, 0x3a, 0x06, 0x2d, 0x06, 0x00, 0x00, 0x4a, - 0x06, 0x00, 0x00, 0x44, 0x06, 0x00, 0x00, 0x46, 0x06, 0x33, 0x06, 0x39, - 0x06, 0x00, 0x00, 0x35, 0x06, 0x42, 0x06, 0x00, 0x00, 0x34, 0x06, 0x00, - 0x00, 0x00, 0x00, 0x2e, 0x06, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x3a, - 0x06, 0x00, 0x00, 0xba, 0x06, 0x00, 0x00, 0x6f, 0x06, 0x00, 0x00, 0x28, - 0x06, 0x2c, 0x06, 0x00, 0x00, 0x47, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2d, - 0x06, 0x37, 0x06, 0x4a, 0x06, 0x43, 0x06, 0x00, 0x00, 0x45, 0x06, 0x46, - 0x06, 0x33, 0x06, 0x39, 0x06, 0x41, 0x06, 0x35, 0x06, 0x42, 0x06, 0x00, - 0x00, 0x34, 0x06, 0x2a, 0x06, 0x2b, 0x06, 0x2e, 0x06, 0x00, 0x00, 0x36, - 0x06, 0x38, 0x06, 0x3a, 0x06, 0x6e, 0x06, 0x00, 0x00, 0xa1, 0x06, 0x27, - 0x06, 0x00, 0x01, 0x05, 0x08, 0x20, 0x21, 0x0b, 0x06, 0x10, 0x23, 0x2a, - 0x06, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00, - 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x28, 0x06, 0x2c, 0x06, 0x2f, 0x06, - 0x00, 0x00, 0x48, 0x06, 0x32, 0x06, 0x2d, 0x06, 0x37, 0x06, 0x4a, 0x06, - 0x2a, 0x06, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, - 0x00, 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x30, 0x2e, 0x30, 0x00, 0x2c, - 0x00, 0x28, 0x00, 0x41, 0x00, 0x29, 0x00, 0x14, 0x30, 0x53, 0x00, 0x15, - 0x30, 0x43, 0x52, 0x43, 0x44, 0x57, 0x5a, 0x41, 0x00, 0x48, 0x56, 0x4d, - 0x56, 0x53, 0x44, 0x53, 0x53, 0x50, 0x50, 0x56, 0x57, 0x43, 0x4d, 0x43, - 0x4d, 0x44, 0x4d, 0x52, 0x44, 0x4a, 0x4b, 0x30, 0x30, 0x00, 0x68, 0x68, - 0x4b, 0x62, 0x57, 0x5b, 0xcc, 0x53, 0xc7, 0x30, 0x8c, 0x4e, 0x1a, 0x59, - 0xe3, 0x89, 0x29, 0x59, 0xa4, 0x4e, 0x20, 0x66, 0x21, 0x71, 0x99, 0x65, - 0x4d, 0x52, 0x8c, 0x5f, 0x8d, 0x51, 0xb0, 0x65, 0x1d, 0x52, 0x42, 0x7d, - 0x1f, 0x75, 0xa9, 0x8c, 0xf0, 0x58, 0x39, 0x54, 0x14, 0x6f, 0x95, 0x62, - 0x55, 0x63, 0x00, 0x4e, 0x09, 0x4e, 0x4a, 0x90, 0xe6, 0x5d, 0x2d, 0x4e, - 0xf3, 0x53, 0x07, 0x63, 0x70, 0x8d, 0x53, 0x62, 0x81, 0x79, 0x7a, 0x7a, - 0x08, 0x54, 0x80, 0x6e, 0x09, 0x67, 0x08, 0x67, 0x33, 0x75, 0x72, 0x52, - 0xb6, 0x55, 0x4d, 0x91, 0x14, 0x30, 0x15, 0x30, 0x2c, 0x67, 0x09, 0x4e, - 0x8c, 0x4e, 0x89, 0x5b, 0xb9, 0x70, 0x53, 0x62, 0xd7, 0x76, 0xdd, 0x52, - 0x57, 0x65, 0x97, 0x5f, 0xef, 0x53, 0x38, 0x4e, 0x05, 0x00, 0x09, 0x22, - 0x01, 0x60, 0x4f, 0xae, 0x4f, 0xbb, 0x4f, 0x02, 0x50, 0x7a, 0x50, 0x99, - 0x50, 0xe7, 0x50, 0xcf, 0x50, 0x9e, 0x34, 0x3a, 0x06, 0x4d, 0x51, 0x54, - 0x51, 0x64, 0x51, 0x77, 0x51, 0x1c, 0x05, 0xb9, 0x34, 0x67, 0x51, 0x8d, - 0x51, 0x4b, 0x05, 0x97, 0x51, 0xa4, 0x51, 0xcc, 0x4e, 0xac, 0x51, 0xb5, - 0x51, 0xdf, 0x91, 0xf5, 0x51, 0x03, 0x52, 0xdf, 0x34, 0x3b, 0x52, 0x46, - 0x52, 0x72, 0x52, 0x77, 0x52, 0x15, 0x35, 0x02, 0x00, 0x20, 0x80, 0x80, - 0x00, 0x08, 0x00, 0x00, 0xc7, 0x52, 0x00, 0x02, 0x1d, 0x33, 0x3e, 0x3f, - 0x50, 0x82, 0x8a, 0x93, 0xac, 0xb6, 0xb8, 0xb8, 0xb8, 0x2c, 0x0a, 0x70, - 0x70, 0xca, 0x53, 0xdf, 0x53, 0x63, 0x0b, 0xeb, 0x53, 0xf1, 0x53, 0x06, - 0x54, 0x9e, 0x54, 0x38, 0x54, 0x48, 0x54, 0x68, 0x54, 0xa2, 0x54, 0xf6, - 0x54, 0x10, 0x55, 0x53, 0x55, 0x63, 0x55, 0x84, 0x55, 0x84, 0x55, 0x99, - 0x55, 0xab, 0x55, 0xb3, 0x55, 0xc2, 0x55, 0x16, 0x57, 0x06, 0x56, 0x17, - 0x57, 0x51, 0x56, 0x74, 0x56, 0x07, 0x52, 0xee, 0x58, 0xce, 0x57, 0xf4, - 0x57, 0x0d, 0x58, 0x8b, 0x57, 0x32, 0x58, 0x31, 0x58, 0xac, 0x58, 0xe4, - 0x14, 0xf2, 0x58, 0xf7, 0x58, 0x06, 0x59, 0x1a, 0x59, 0x22, 0x59, 0x62, - 0x59, 0xa8, 0x16, 0xea, 0x16, 0xec, 0x59, 0x1b, 0x5a, 0x27, 0x5a, 0xd8, - 0x59, 0x66, 0x5a, 0xee, 0x36, 0xfc, 0x36, 0x08, 0x5b, 0x3e, 0x5b, 0x3e, - 0x5b, 0xc8, 0x19, 0xc3, 0x5b, 0xd8, 0x5b, 0xe7, 0x5b, 0xf3, 0x5b, 0x18, - 0x1b, 0xff, 0x5b, 0x06, 0x5c, 0x53, 0x5f, 0x22, 0x5c, 0x81, 0x37, 0x60, - 0x5c, 0x6e, 0x5c, 0xc0, 0x5c, 0x8d, 0x5c, 0xe4, 0x1d, 0x43, 0x5d, 0xe6, - 0x1d, 0x6e, 0x5d, 0x6b, 0x5d, 0x7c, 0x5d, 0xe1, 0x5d, 0xe2, 0x5d, 0x2f, - 0x38, 0xfd, 0x5d, 0x28, 0x5e, 0x3d, 0x5e, 0x69, 0x5e, 0x62, 0x38, 0x83, - 0x21, 0x7c, 0x38, 0xb0, 0x5e, 0xb3, 0x5e, 0xb6, 0x5e, 0xca, 0x5e, 0x92, - 0xa3, 0xfe, 0x5e, 0x31, 0x23, 0x31, 0x23, 0x01, 0x82, 0x22, 0x5f, 0x22, - 0x5f, 0xc7, 0x38, 0xb8, 0x32, 0xda, 0x61, 0x62, 0x5f, 0x6b, 0x5f, 0xe3, - 0x38, 0x9a, 0x5f, 0xcd, 0x5f, 0xd7, 0x5f, 0xf9, 0x5f, 0x81, 0x60, 0x3a, - 0x39, 0x1c, 0x39, 0x94, 0x60, 0xd4, 0x26, 0xc7, 0x60, 0x02, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x02, - 0x08, 0x00, 0x80, 0x08, 0x00, 0x00, 0x08, 0x80, 0x28, 0x80, 0x02, 0x00, - 0x00, 0x02, 0x48, 0x61, 0x00, 0x04, 0x06, 0x04, 0x32, 0x46, 0x6a, 0x5c, - 0x67, 0x96, 0xaa, 0xae, 0xc8, 0xd3, 0x5d, 0x62, 0x00, 0x54, 0x77, 0xf3, - 0x0c, 0x2b, 0x3d, 0x63, 0xfc, 0x62, 0x68, 0x63, 0x83, 0x63, 0xe4, 0x63, - 0xf1, 0x2b, 0x22, 0x64, 0xc5, 0x63, 0xa9, 0x63, 0x2e, 0x3a, 0x69, 0x64, - 0x7e, 0x64, 0x9d, 0x64, 0x77, 0x64, 0x6c, 0x3a, 0x4f, 0x65, 0x6c, 0x65, - 0x0a, 0x30, 0xe3, 0x65, 0xf8, 0x66, 0x49, 0x66, 0x19, 0x3b, 0x91, 0x66, - 0x08, 0x3b, 0xe4, 0x3a, 0x92, 0x51, 0x95, 0x51, 0x00, 0x67, 0x9c, 0x66, - 0xad, 0x80, 0xd9, 0x43, 0x17, 0x67, 0x1b, 0x67, 0x21, 0x67, 0x5e, 0x67, - 0x53, 0x67, 0xc3, 0x33, 0x49, 0x3b, 0xfa, 0x67, 0x85, 0x67, 0x52, 0x68, - 0x85, 0x68, 0x6d, 0x34, 0x8e, 0x68, 0x1f, 0x68, 0x14, 0x69, 0x9d, 0x3b, - 0x42, 0x69, 0xa3, 0x69, 0xea, 0x69, 0xa8, 0x6a, 0xa3, 0x36, 0xdb, 0x6a, - 0x18, 0x3c, 0x21, 0x6b, 0xa7, 0x38, 0x54, 0x6b, 0x4e, 0x3c, 0x72, 0x6b, - 0x9f, 0x6b, 0xba, 0x6b, 0xbb, 0x6b, 0x8d, 0x3a, 0x0b, 0x1d, 0xfa, 0x3a, - 0x4e, 0x6c, 0xbc, 0x3c, 0xbf, 0x6c, 0xcd, 0x6c, 0x67, 0x6c, 0x16, 0x6d, - 0x3e, 0x6d, 0x77, 0x6d, 0x41, 0x6d, 0x69, 0x6d, 0x78, 0x6d, 0x85, 0x6d, - 0x1e, 0x3d, 0x34, 0x6d, 0x2f, 0x6e, 0x6e, 0x6e, 0x33, 0x3d, 0xcb, 0x6e, - 0xc7, 0x6e, 0xd1, 0x3e, 0xf9, 0x6d, 0x6e, 0x6f, 0x5e, 0x3f, 0x8e, 0x3f, - 0xc6, 0x6f, 0x39, 0x70, 0x1e, 0x70, 0x1b, 0x70, 0x96, 0x3d, 0x4a, 0x70, - 0x7d, 0x70, 0x77, 0x70, 0xad, 0x70, 0x25, 0x05, 0x45, 0x71, 0x63, 0x42, - 0x9c, 0x71, 0xab, 0x43, 0x28, 0x72, 0x35, 0x72, 0x50, 0x72, 0x08, 0x46, - 0x80, 0x72, 0x95, 0x72, 0x35, 0x47, 0x02, 0x20, 0x00, 0x00, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x02, 0x02, 0x80, 0x8a, 0x00, - 0x00, 0x20, 0x00, 0x08, 0x0a, 0x00, 0x80, 0x88, 0x80, 0x20, 0x14, 0x48, - 0x7a, 0x73, 0x8b, 0x73, 0xac, 0x3e, 0xa5, 0x73, 0xb8, 0x3e, 0xb8, 0x3e, - 0x47, 0x74, 0x5c, 0x74, 0x71, 0x74, 0x85, 0x74, 0xca, 0x74, 0x1b, 0x3f, - 0x24, 0x75, 0x36, 0x4c, 0x3e, 0x75, 0x92, 0x4c, 0x70, 0x75, 0x9f, 0x21, - 0x10, 0x76, 0xa1, 0x4f, 0xb8, 0x4f, 0x44, 0x50, 0xfc, 0x3f, 0x08, 0x40, - 0xf4, 0x76, 0xf3, 0x50, 0xf2, 0x50, 0x19, 0x51, 0x33, 0x51, 0x1e, 0x77, - 0x1f, 0x77, 0x1f, 0x77, 0x4a, 0x77, 0x39, 0x40, 0x8b, 0x77, 0x46, 0x40, - 0x96, 0x40, 0x1d, 0x54, 0x4e, 0x78, 0x8c, 0x78, 0xcc, 0x78, 0xe3, 0x40, - 0x26, 0x56, 0x56, 0x79, 0x9a, 0x56, 0xc5, 0x56, 0x8f, 0x79, 0xeb, 0x79, - 0x2f, 0x41, 0x40, 0x7a, 0x4a, 0x7a, 0x4f, 0x7a, 0x7c, 0x59, 0xa7, 0x5a, - 0xa7, 0x5a, 0xee, 0x7a, 0x02, 0x42, 0xab, 0x5b, 0xc6, 0x7b, 0xc9, 0x7b, - 0x27, 0x42, 0x80, 0x5c, 0xd2, 0x7c, 0xa0, 0x42, 0xe8, 0x7c, 0xe3, 0x7c, - 0x00, 0x7d, 0x86, 0x5f, 0x63, 0x7d, 0x01, 0x43, 0xc7, 0x7d, 0x02, 0x7e, - 0x45, 0x7e, 0x34, 0x43, 0x28, 0x62, 0x47, 0x62, 0x59, 0x43, 0xd9, 0x62, - 0x7a, 0x7f, 0x3e, 0x63, 0x95, 0x7f, 0xfa, 0x7f, 0x05, 0x80, 0xda, 0x64, - 0x23, 0x65, 0x60, 0x80, 0xa8, 0x65, 0x70, 0x80, 0x5f, 0x33, 0xd5, 0x43, - 0xb2, 0x80, 0x03, 0x81, 0x0b, 0x44, 0x3e, 0x81, 0xb5, 0x5a, 0xa7, 0x67, - 0xb5, 0x67, 0x93, 0x33, 0x9c, 0x33, 0x01, 0x82, 0x04, 0x82, 0x9e, 0x8f, - 0x6b, 0x44, 0x91, 0x82, 0x8b, 0x82, 0x9d, 0x82, 0xb3, 0x52, 0xb1, 0x82, - 0xb3, 0x82, 0xbd, 0x82, 0xe6, 0x82, 0x3c, 0x6b, 0xe5, 0x82, 0x1d, 0x83, - 0x63, 0x83, 0xad, 0x83, 0x23, 0x83, 0xbd, 0x83, 0xe7, 0x83, 0x57, 0x84, - 0x53, 0x83, 0xca, 0x83, 0xcc, 0x83, 0xdc, 0x83, 0x36, 0x6c, 0x6b, 0x6d, - 0x02, 0x00, 0x00, 0x20, 0x22, 0x2a, 0xa0, 0x0a, 0x00, 0x20, 0x80, 0x28, - 0x00, 0xa8, 0x20, 0x20, 0x00, 0x02, 0x80, 0x22, 0x02, 0x8a, 0x08, 0x00, - 0xaa, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x28, 0xd5, 0x6c, 0x2b, 0x45, - 0xf1, 0x84, 0xf3, 0x84, 0x16, 0x85, 0xca, 0x73, 0x64, 0x85, 0x2c, 0x6f, - 0x5d, 0x45, 0x61, 0x45, 0xb1, 0x6f, 0xd2, 0x70, 0x6b, 0x45, 0x50, 0x86, - 0x5c, 0x86, 0x67, 0x86, 0x69, 0x86, 0xa9, 0x86, 0x88, 0x86, 0x0e, 0x87, - 0xe2, 0x86, 0x79, 0x87, 0x28, 0x87, 0x6b, 0x87, 0x86, 0x87, 0xd7, 0x45, - 0xe1, 0x87, 0x01, 0x88, 0xf9, 0x45, 0x60, 0x88, 0x63, 0x88, 0x67, 0x76, - 0xd7, 0x88, 0xde, 0x88, 0x35, 0x46, 0xfa, 0x88, 0xbb, 0x34, 0xae, 0x78, - 0x66, 0x79, 0xbe, 0x46, 0xc7, 0x46, 0xa0, 0x8a, 0xed, 0x8a, 0x8a, 0x8b, - 0x55, 0x8c, 0xa8, 0x7c, 0xab, 0x8c, 0xc1, 0x8c, 0x1b, 0x8d, 0x77, 0x8d, - 0x2f, 0x7f, 0x04, 0x08, 0xcb, 0x8d, 0xbc, 0x8d, 0xf0, 0x8d, 0xde, 0x08, - 0xd4, 0x8e, 0x38, 0x8f, 0xd2, 0x85, 0xed, 0x85, 0x94, 0x90, 0xf1, 0x90, - 0x11, 0x91, 0x2e, 0x87, 0x1b, 0x91, 0x38, 0x92, 0xd7, 0x92, 0xd8, 0x92, - 0x7c, 0x92, 0xf9, 0x93, 0x15, 0x94, 0xfa, 0x8b, 0x8b, 0x95, 0x95, 0x49, - 0xb7, 0x95, 0x77, 0x8d, 0xe6, 0x49, 0xc3, 0x96, 0xb2, 0x5d, 0x23, 0x97, - 0x45, 0x91, 0x1a, 0x92, 0x6e, 0x4a, 0x76, 0x4a, 0xe0, 0x97, 0x0a, 0x94, - 0xb2, 0x4a, 0x96, 0x94, 0x0b, 0x98, 0x0b, 0x98, 0x29, 0x98, 0xb6, 0x95, - 0xe2, 0x98, 0x33, 0x4b, 0x29, 0x99, 0xa7, 0x99, 0xc2, 0x99, 0xfe, 0x99, - 0xce, 0x4b, 0x30, 0x9b, 0x12, 0x9b, 0x40, 0x9c, 0xfd, 0x9c, 0xce, 0x4c, - 0xed, 0x4c, 0x67, 0x9d, 0xce, 0xa0, 0xf8, 0x4c, 0x05, 0xa1, 0x0e, 0xa2, - 0x91, 0xa2, 0xbb, 0x9e, 0x56, 0x4d, 0xf9, 0x9e, 0xfe, 0x9e, 0x05, 0x9f, - 0x0f, 0x9f, 0x16, 0x9f, 0x3b, 0x9f, 0x00, 0xa6, 0x02, 0x88, 0xa0, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x28, 0x00, 0x08, 0xa0, 0x80, 0xa0, 0x80, - 0x00, 0x80, 0x80, 0x00, 0x0a, 0x88, 0x80, 0x00, 0x80, 0x00, 0x20, 0x2a, - 0x00, 0x80, -}; - -static const uint16_t unicode_comp_table[944] = { - 0x4a01, 0x49c0, 0x4a02, 0x0280, 0x0281, 0x0282, 0x0283, 0x02c0, 0x02c2, - 0x0a00, 0x0284, 0x2442, 0x0285, 0x07c0, 0x0980, 0x0982, 0x2440, 0x2280, - 0x02c4, 0x2282, 0x2284, 0x2286, 0x02c6, 0x02c8, 0x02ca, 0x02cc, 0x0287, - 0x228a, 0x02ce, 0x228c, 0x2290, 0x2292, 0x228e, 0x0288, 0x0289, 0x028a, - 0x2482, 0x0300, 0x0302, 0x0304, 0x028b, 0x2480, 0x0308, 0x0984, 0x0986, - 0x2458, 0x0a02, 0x0306, 0x2298, 0x229a, 0x229e, 0x0900, 0x030a, 0x22a0, - 0x030c, 0x030e, 0x0840, 0x0310, 0x0312, 0x22a2, 0x22a6, 0x09c0, 0x22a4, - 0x22a8, 0x22aa, 0x028c, 0x028d, 0x028e, 0x0340, 0x0342, 0x0344, 0x0380, - 0x028f, 0x248e, 0x07c2, 0x0988, 0x098a, 0x2490, 0x0346, 0x22ac, 0x0400, - 0x22b0, 0x0842, 0x22b2, 0x0402, 0x22b4, 0x0440, 0x0444, 0x22b6, 0x0442, - 0x22c2, 0x22c0, 0x22c4, 0x22c6, 0x22c8, 0x0940, 0x04c0, 0x0291, 0x22ca, - 0x04c4, 0x22cc, 0x04c2, 0x22d0, 0x22ce, 0x0292, 0x0293, 0x0294, 0x0295, - 0x0540, 0x0542, 0x0a08, 0x0296, 0x2494, 0x0544, 0x07c4, 0x098c, 0x098e, - 0x06c0, 0x2492, 0x0844, 0x2308, 0x230a, 0x0580, 0x230c, 0x0584, 0x0990, - 0x0992, 0x230e, 0x0582, 0x2312, 0x0586, 0x0588, 0x2314, 0x058c, 0x2316, - 0x0998, 0x058a, 0x231e, 0x0590, 0x2320, 0x099a, 0x058e, 0x2324, 0x2322, - 0x0299, 0x029a, 0x029b, 0x05c0, 0x05c2, 0x05c4, 0x029c, 0x24ac, 0x05c6, - 0x05c8, 0x07c6, 0x0994, 0x0996, 0x0700, 0x24aa, 0x2326, 0x05ca, 0x232a, - 0x2328, 0x2340, 0x2342, 0x2344, 0x2346, 0x05cc, 0x234a, 0x2348, 0x234c, - 0x234e, 0x2350, 0x24b8, 0x029d, 0x05ce, 0x24be, 0x0a0c, 0x2352, 0x0600, - 0x24bc, 0x24ba, 0x0640, 0x2354, 0x0642, 0x0644, 0x2356, 0x2358, 0x02a0, - 0x02a1, 0x02a2, 0x02a3, 0x02c1, 0x02c3, 0x0a01, 0x02a4, 0x2443, 0x02a5, - 0x07c1, 0x0981, 0x0983, 0x2441, 0x2281, 0x02c5, 0x2283, 0x2285, 0x2287, - 0x02c7, 0x02c9, 0x02cb, 0x02cd, 0x02a7, 0x228b, 0x02cf, 0x228d, 0x2291, - 0x2293, 0x228f, 0x02a8, 0x02a9, 0x02aa, 0x2483, 0x0301, 0x0303, 0x0305, - 0x02ab, 0x2481, 0x0309, 0x0985, 0x0987, 0x2459, 0x0a03, 0x0307, 0x2299, - 0x229b, 0x229f, 0x0901, 0x030b, 0x22a1, 0x030d, 0x030f, 0x0841, 0x0311, - 0x0313, 0x22a3, 0x22a7, 0x09c1, 0x22a5, 0x22a9, 0x22ab, 0x2380, 0x02ac, - 0x02ad, 0x02ae, 0x0341, 0x0343, 0x0345, 0x02af, 0x248f, 0x07c3, 0x0989, - 0x098b, 0x2491, 0x0347, 0x22ad, 0x0401, 0x0884, 0x22b1, 0x0843, 0x22b3, - 0x0403, 0x22b5, 0x0441, 0x0445, 0x22b7, 0x0443, 0x22c3, 0x22c1, 0x22c5, - 0x22c7, 0x22c9, 0x0941, 0x04c1, 0x02b1, 0x22cb, 0x04c5, 0x22cd, 0x04c3, - 0x22d1, 0x22cf, 0x02b2, 0x02b3, 0x02b4, 0x02b5, 0x0541, 0x0543, 0x0a09, - 0x02b6, 0x2495, 0x0545, 0x07c5, 0x098d, 0x098f, 0x06c1, 0x2493, 0x0845, - 0x2309, 0x230b, 0x0581, 0x230d, 0x0585, 0x0991, 0x0993, 0x230f, 0x0583, - 0x2313, 0x0587, 0x0589, 0x2315, 0x058d, 0x2317, 0x0999, 0x058b, 0x231f, - 0x2381, 0x0591, 0x2321, 0x099b, 0x058f, 0x2325, 0x2323, 0x02b9, 0x02ba, - 0x02bb, 0x05c1, 0x05c3, 0x05c5, 0x02bc, 0x24ad, 0x05c7, 0x05c9, 0x07c7, - 0x0995, 0x0997, 0x0701, 0x24ab, 0x2327, 0x05cb, 0x232b, 0x2329, 0x2341, - 0x2343, 0x2345, 0x2347, 0x05cd, 0x234b, 0x2349, 0x2382, 0x234d, 0x234f, - 0x2351, 0x24b9, 0x02bd, 0x05cf, 0x24bf, 0x0a0d, 0x2353, 0x02bf, 0x24bd, - 0x2383, 0x24bb, 0x0641, 0x2355, 0x0643, 0x0645, 0x2357, 0x2359, 0x3101, - 0x0c80, 0x2e00, 0x2446, 0x2444, 0x244a, 0x2448, 0x0800, 0x0942, 0x0944, - 0x0804, 0x2288, 0x2486, 0x2484, 0x248a, 0x2488, 0x22ae, 0x2498, 0x2496, - 0x249c, 0x249a, 0x2300, 0x0a06, 0x2302, 0x0a04, 0x0946, 0x07ce, 0x07ca, - 0x07c8, 0x07cc, 0x2447, 0x2445, 0x244b, 0x2449, 0x0801, 0x0943, 0x0945, - 0x0805, 0x2289, 0x2487, 0x2485, 0x248b, 0x2489, 0x22af, 0x2499, 0x2497, - 0x249d, 0x249b, 0x2301, 0x0a07, 0x2303, 0x0a05, 0x0947, 0x07cf, 0x07cb, - 0x07c9, 0x07cd, 0x2450, 0x244e, 0x2454, 0x2452, 0x2451, 0x244f, 0x2455, - 0x2453, 0x2294, 0x2296, 0x2295, 0x2297, 0x2304, 0x2306, 0x2305, 0x2307, - 0x2318, 0x2319, 0x231a, 0x231b, 0x232c, 0x232d, 0x232e, 0x232f, 0x2400, - 0x24a2, 0x24a0, 0x24a6, 0x24a4, 0x24a8, 0x24a3, 0x24a1, 0x24a7, 0x24a5, - 0x24a9, 0x24b0, 0x24ae, 0x24b4, 0x24b2, 0x24b6, 0x24b1, 0x24af, 0x24b5, - 0x24b3, 0x24b7, 0x0882, 0x0880, 0x0881, 0x0802, 0x0803, 0x229c, 0x229d, - 0x0a0a, 0x0a0b, 0x0883, 0x0b40, 0x2c8a, 0x0c81, 0x2c89, 0x2c88, 0x2540, - 0x2541, 0x2d00, 0x2e07, 0x0d00, 0x2640, 0x2641, 0x2e80, 0x0d01, 0x26c8, - 0x26c9, 0x2f00, 0x2f84, 0x0d02, 0x2f83, 0x2f82, 0x0d40, 0x26d8, 0x26d9, - 0x3186, 0x0d04, 0x2740, 0x2741, 0x3100, 0x3086, 0x0d06, 0x3085, 0x3084, - 0x0d41, 0x2840, 0x3200, 0x0d07, 0x284f, 0x2850, 0x3280, 0x2c84, 0x2e03, - 0x2857, 0x0d42, 0x2c81, 0x2c80, 0x24c0, 0x24c1, 0x2c86, 0x2c83, 0x28c0, - 0x0d43, 0x25c0, 0x25c1, 0x2940, 0x0d44, 0x26c0, 0x26c1, 0x2e05, 0x2e02, - 0x29c0, 0x0d45, 0x2f05, 0x2f04, 0x0d80, 0x26d0, 0x26d1, 0x2f80, 0x2a40, - 0x0d82, 0x26e0, 0x26e1, 0x3080, 0x3081, 0x2ac0, 0x0d83, 0x3004, 0x3003, - 0x0d81, 0x27c0, 0x27c1, 0x3082, 0x2b40, 0x0d84, 0x2847, 0x2848, 0x3184, - 0x3181, 0x2f06, 0x0d08, 0x2f81, 0x3005, 0x0d46, 0x3083, 0x3182, 0x0e00, - 0x0e01, 0x0f40, 0x1180, 0x1182, 0x0f03, 0x0f00, 0x11c0, 0x0f01, 0x1140, - 0x1202, 0x1204, 0x0f81, 0x1240, 0x0fc0, 0x1242, 0x0f80, 0x1244, 0x1284, - 0x0f82, 0x1286, 0x1288, 0x128a, 0x12c0, 0x1282, 0x1181, 0x1183, 0x1043, - 0x1040, 0x11c1, 0x1041, 0x1141, 0x1203, 0x1205, 0x10c1, 0x1241, 0x1000, - 0x1243, 0x10c0, 0x1245, 0x1285, 0x10c2, 0x1287, 0x1289, 0x128b, 0x12c1, - 0x1283, 0x1080, 0x1100, 0x1101, 0x1200, 0x1201, 0x1280, 0x1281, 0x1340, - 0x1341, 0x1343, 0x1342, 0x1344, 0x13c2, 0x1400, 0x13c0, 0x1440, 0x1480, - 0x14c0, 0x1540, 0x1541, 0x1740, 0x1700, 0x1741, 0x17c0, 0x1800, 0x1802, - 0x1801, 0x1840, 0x1880, 0x1900, 0x18c0, 0x18c1, 0x1901, 0x1940, 0x1942, - 0x1941, 0x1980, 0x19c0, 0x19c2, 0x19c1, 0x1c80, 0x1cc0, 0x1dc0, 0x1f80, - 0x2000, 0x2002, 0x2004, 0x2006, 0x2008, 0x2040, 0x2080, 0x2082, 0x20c0, - 0x20c1, 0x2100, 0x22b8, 0x22b9, 0x2310, 0x2311, 0x231c, 0x231d, 0x244c, - 0x2456, 0x244d, 0x2457, 0x248c, 0x248d, 0x249e, 0x249f, 0x2500, 0x2502, - 0x2504, 0x2bc0, 0x2501, 0x2503, 0x2505, 0x2bc1, 0x2bc2, 0x2bc3, 0x2bc4, - 0x2bc5, 0x2bc6, 0x2bc7, 0x2580, 0x2582, 0x2584, 0x2bc8, 0x2581, 0x2583, - 0x2585, 0x2bc9, 0x2bca, 0x2bcb, 0x2bcc, 0x2bcd, 0x2bce, 0x2bcf, 0x2600, - 0x2602, 0x2601, 0x2603, 0x2680, 0x2682, 0x2681, 0x2683, 0x26c2, 0x26c4, - 0x26c6, 0x2c00, 0x26c3, 0x26c5, 0x26c7, 0x2c01, 0x2c02, 0x2c03, 0x2c04, - 0x2c05, 0x2c06, 0x2c07, 0x26ca, 0x26cc, 0x26ce, 0x2c08, 0x26cb, 0x26cd, - 0x26cf, 0x2c09, 0x2c0a, 0x2c0b, 0x2c0c, 0x2c0d, 0x2c0e, 0x2c0f, 0x26d2, - 0x26d4, 0x26d6, 0x26d3, 0x26d5, 0x26d7, 0x26da, 0x26dc, 0x26de, 0x26db, - 0x26dd, 0x26df, 0x2700, 0x2702, 0x2701, 0x2703, 0x2780, 0x2782, 0x2781, - 0x2783, 0x2800, 0x2802, 0x2804, 0x2801, 0x2803, 0x2805, 0x2842, 0x2844, - 0x2846, 0x2849, 0x284b, 0x284d, 0x2c40, 0x284a, 0x284c, 0x284e, 0x2c41, - 0x2c42, 0x2c43, 0x2c44, 0x2c45, 0x2c46, 0x2c47, 0x2851, 0x2853, 0x2855, - 0x2c48, 0x2852, 0x2854, 0x2856, 0x2c49, 0x2c4a, 0x2c4b, 0x2c4c, 0x2c4d, - 0x2c4e, 0x2c4f, 0x2c82, 0x2e01, 0x3180, 0x2c87, 0x2f01, 0x2f02, 0x2f03, - 0x2e06, 0x3185, 0x3000, 0x3001, 0x3002, 0x4640, 0x4641, 0x4680, 0x46c0, - 0x46c2, 0x46c1, 0x4700, 0x4740, 0x4780, 0x47c0, 0x47c2, 0x4900, 0x4940, - 0x4980, 0x4982, 0x4a00, 0x49c2, 0x4a03, 0x4a04, 0x4a40, 0x4a41, 0x4a80, - 0x4a81, 0x4ac0, 0x4ac1, 0x4bc0, 0x4bc1, 0x4b00, 0x4b01, 0x4b40, 0x4b41, - 0x4bc2, 0x4bc3, 0x4b80, 0x4b81, 0x4b82, 0x4b83, 0x4c00, 0x4c01, 0x4c02, - 0x4c03, 0x5600, 0x5440, 0x5442, 0x5444, 0x5446, 0x5448, 0x544a, 0x544c, - 0x544e, 0x5450, 0x5452, 0x5454, 0x5456, 0x5480, 0x5482, 0x5484, 0x54c0, - 0x54c1, 0x5500, 0x5501, 0x5540, 0x5541, 0x5580, 0x5581, 0x55c0, 0x55c1, - 0x5680, 0x58c0, 0x5700, 0x5702, 0x5704, 0x5706, 0x5708, 0x570a, 0x570c, - 0x570e, 0x5710, 0x5712, 0x5714, 0x5716, 0x5740, 0x5742, 0x5744, 0x5780, - 0x5781, 0x57c0, 0x57c1, 0x5800, 0x5801, 0x5840, 0x5841, 0x5880, 0x5881, - 0x5900, 0x5901, 0x5902, 0x5903, 0x5940, 0x8e40, 0x8e42, 0x8e80, 0x8ec0, - 0x8ec1, 0x8f00, 0x8f01, 0x8f41, 0x8f40, 0x8f43, 0x8f80, 0x8f81, -}; - -typedef enum { - UNICODE_GC_Cn, - UNICODE_GC_Lu, - UNICODE_GC_Ll, - UNICODE_GC_Lt, - UNICODE_GC_Lm, - UNICODE_GC_Lo, - UNICODE_GC_Mn, - UNICODE_GC_Mc, - UNICODE_GC_Me, - UNICODE_GC_Nd, - UNICODE_GC_Nl, - UNICODE_GC_No, - UNICODE_GC_Sm, - UNICODE_GC_Sc, - UNICODE_GC_Sk, - UNICODE_GC_So, - UNICODE_GC_Pc, - UNICODE_GC_Pd, - UNICODE_GC_Ps, - UNICODE_GC_Pe, - UNICODE_GC_Pi, - UNICODE_GC_Pf, - UNICODE_GC_Po, - UNICODE_GC_Zs, - UNICODE_GC_Zl, - UNICODE_GC_Zp, - UNICODE_GC_Cc, - UNICODE_GC_Cf, - UNICODE_GC_Cs, - UNICODE_GC_Co, - UNICODE_GC_LC, - UNICODE_GC_L, - UNICODE_GC_M, - UNICODE_GC_N, - UNICODE_GC_S, - UNICODE_GC_P, - UNICODE_GC_Z, - UNICODE_GC_C, - UNICODE_GC_COUNT, -} UnicodeGCEnum; - -static const char unicode_gc_name_table[] = - "Cn,Unassigned" - "\0" - "Lu,Uppercase_Letter" - "\0" - "Ll,Lowercase_Letter" - "\0" - "Lt,Titlecase_Letter" - "\0" - "Lm,Modifier_Letter" - "\0" - "Lo,Other_Letter" - "\0" - "Mn,Nonspacing_Mark" - "\0" - "Mc,Spacing_Mark" - "\0" - "Me,Enclosing_Mark" - "\0" - "Nd,Decimal_Number,digit" - "\0" - "Nl,Letter_Number" - "\0" - "No,Other_Number" - "\0" - "Sm,Math_Symbol" - "\0" - "Sc,Currency_Symbol" - "\0" - "Sk,Modifier_Symbol" - "\0" - "So,Other_Symbol" - "\0" - "Pc,Connector_Punctuation" - "\0" - "Pd,Dash_Punctuation" - "\0" - "Ps,Open_Punctuation" - "\0" - "Pe,Close_Punctuation" - "\0" - "Pi,Initial_Punctuation" - "\0" - "Pf,Final_Punctuation" - "\0" - "Po,Other_Punctuation" - "\0" - "Zs,Space_Separator" - "\0" - "Zl,Line_Separator" - "\0" - "Zp,Paragraph_Separator" - "\0" - "Cc,Control,cntrl" - "\0" - "Cf,Format" - "\0" - "Cs,Surrogate" - "\0" - "Co,Private_Use" - "\0" - "LC,Cased_Letter" - "\0" - "L,Letter" - "\0" - "M,Mark,Combining_Mark" - "\0" - "N,Number" - "\0" - "S,Symbol" - "\0" - "P,Punctuation,punct" - "\0" - "Z,Separator" - "\0" - "C,Other" - "\0"; - -static const uint8_t unicode_gc_table[3719] = { - 0xfa, 0x18, 0x17, 0x56, 0x0d, 0x56, 0x12, 0x13, 0x16, 0x0c, 0x16, 0x11, - 0x36, 0xe9, 0x02, 0x36, 0x4c, 0x36, 0xe1, 0x12, 0x12, 0x16, 0x13, 0x0e, - 0x10, 0x0e, 0xe2, 0x12, 0x12, 0x0c, 0x13, 0x0c, 0xfa, 0x19, 0x17, 0x16, - 0x6d, 0x0f, 0x16, 0x0e, 0x0f, 0x05, 0x14, 0x0c, 0x1b, 0x0f, 0x0e, 0x0f, - 0x0c, 0x2b, 0x0e, 0x02, 0x36, 0x0e, 0x0b, 0x05, 0x15, 0x4b, 0x16, 0xe1, - 0x0f, 0x0c, 0xc1, 0xe2, 0x10, 0x0c, 0xe2, 0x00, 0xff, 0x30, 0x02, 0xff, - 0x08, 0x02, 0xff, 0x27, 0xbf, 0x22, 0x21, 0x02, 0x5f, 0x5f, 0x21, 0x22, - 0x61, 0x02, 0x21, 0x02, 0x41, 0x42, 0x21, 0x02, 0x21, 0x02, 0x9f, 0x7f, - 0x02, 0x5f, 0x5f, 0x21, 0x02, 0x5f, 0x3f, 0x02, 0x05, 0x3f, 0x22, 0x65, - 0x01, 0x03, 0x02, 0x01, 0x03, 0x02, 0x01, 0x03, 0x02, 0xff, 0x08, 0x02, - 0xff, 0x0a, 0x02, 0x01, 0x03, 0x02, 0x5f, 0x21, 0x02, 0xff, 0x32, 0xa2, - 0x21, 0x02, 0x21, 0x22, 0x5f, 0x41, 0x02, 0xff, 0x00, 0xe2, 0x3c, 0x05, - 0xe2, 0x13, 0xe4, 0x0a, 0x6e, 0xe4, 0x04, 0xee, 0x06, 0x84, 0xce, 0x04, - 0x0e, 0x04, 0xee, 0x09, 0xe6, 0x68, 0x7f, 0x04, 0x0e, 0x3f, 0x20, 0x04, - 0x42, 0x16, 0x01, 0x60, 0x2e, 0x01, 0x16, 0x41, 0x00, 0x01, 0x00, 0x21, - 0x02, 0xe1, 0x09, 0x00, 0xe1, 0x01, 0xe2, 0x1b, 0x3f, 0x02, 0x41, 0x42, - 0xff, 0x10, 0x62, 0x3f, 0x0c, 0x5f, 0x3f, 0x02, 0xe1, 0x2b, 0xe2, 0x28, - 0xff, 0x1a, 0x0f, 0x86, 0x28, 0xff, 0x2f, 0xff, 0x06, 0x02, 0xff, 0x58, - 0x00, 0xe1, 0x1e, 0x20, 0x04, 0xb6, 0xe2, 0x21, 0x16, 0x11, 0x20, 0x2f, - 0x0d, 0x00, 0xe6, 0x25, 0x11, 0x06, 0x16, 0x26, 0x16, 0x26, 0x16, 0x06, - 0xe0, 0x00, 0xe5, 0x13, 0x60, 0x65, 0x36, 0xe0, 0x03, 0xbb, 0x4c, 0x36, - 0x0d, 0x36, 0x2f, 0xe6, 0x03, 0x16, 0x1b, 0x00, 0x36, 0xe5, 0x18, 0x04, - 0xe5, 0x02, 0xe6, 0x0d, 0xe9, 0x02, 0x76, 0x25, 0x06, 0xe5, 0x5b, 0x16, - 0x05, 0xc6, 0x1b, 0x0f, 0xa6, 0x24, 0x26, 0x0f, 0x66, 0x25, 0xe9, 0x02, - 0x45, 0x2f, 0x05, 0xf6, 0x06, 0x00, 0x1b, 0x05, 0x06, 0xe5, 0x16, 0xe6, - 0x13, 0x20, 0xe5, 0x51, 0xe6, 0x03, 0x05, 0xe0, 0x06, 0xe9, 0x02, 0xe5, - 0x19, 0xe6, 0x01, 0x24, 0x0f, 0x56, 0x04, 0x20, 0x06, 0x2d, 0xe5, 0x0e, - 0x66, 0x04, 0xe6, 0x01, 0x04, 0x46, 0x04, 0x86, 0x20, 0xf6, 0x07, 0x00, - 0xe5, 0x11, 0x46, 0x20, 0x16, 0x00, 0xe5, 0x03, 0xe0, 0x2d, 0xe5, 0x0d, - 0x00, 0xe5, 0x00, 0xe0, 0x0d, 0xe6, 0x07, 0x1b, 0xe6, 0x18, 0x07, 0xe5, - 0x2e, 0x06, 0x07, 0x06, 0x05, 0x47, 0xe6, 0x00, 0x67, 0x06, 0x27, 0x05, - 0xc6, 0xe5, 0x02, 0x26, 0x36, 0xe9, 0x02, 0x16, 0x04, 0xe5, 0x07, 0x06, - 0x27, 0x00, 0xe5, 0x00, 0x20, 0x25, 0x20, 0xe5, 0x0e, 0x00, 0xc5, 0x00, - 0x05, 0x40, 0x65, 0x20, 0x06, 0x05, 0x47, 0x66, 0x20, 0x27, 0x20, 0x27, - 0x06, 0x05, 0xe0, 0x00, 0x07, 0x60, 0x25, 0x00, 0x45, 0x26, 0x20, 0xe9, - 0x02, 0x25, 0x2d, 0xab, 0x0f, 0x0d, 0x05, 0x16, 0x06, 0x20, 0x26, 0x07, - 0x00, 0xa5, 0x60, 0x25, 0x20, 0xe5, 0x0e, 0x00, 0xc5, 0x00, 0x25, 0x00, - 0x25, 0x00, 0x25, 0x20, 0x06, 0x00, 0x47, 0x26, 0x60, 0x26, 0x20, 0x46, - 0x40, 0x06, 0xc0, 0x65, 0x00, 0x05, 0xc0, 0xe9, 0x02, 0x26, 0x45, 0x06, - 0x16, 0xe0, 0x02, 0x26, 0x07, 0x00, 0xe5, 0x01, 0x00, 0x45, 0x00, 0xe5, - 0x0e, 0x00, 0xc5, 0x00, 0x25, 0x00, 0x85, 0x20, 0x06, 0x05, 0x47, 0x86, - 0x00, 0x26, 0x07, 0x00, 0x27, 0x06, 0x20, 0x05, 0xe0, 0x07, 0x25, 0x26, - 0x20, 0xe9, 0x02, 0x16, 0x0d, 0xc0, 0x05, 0xa6, 0x00, 0x06, 0x27, 0x00, - 0xe5, 0x00, 0x20, 0x25, 0x20, 0xe5, 0x0e, 0x00, 0xc5, 0x00, 0x25, 0x00, - 0x85, 0x20, 0x06, 0x05, 0x07, 0x06, 0x07, 0x66, 0x20, 0x27, 0x20, 0x27, - 0x06, 0xe0, 0x00, 0x06, 0x07, 0x60, 0x25, 0x00, 0x45, 0x26, 0x20, 0xe9, - 0x02, 0x0f, 0x05, 0xab, 0xe0, 0x02, 0x06, 0x05, 0x00, 0xa5, 0x40, 0x45, - 0x00, 0x65, 0x40, 0x25, 0x00, 0x05, 0x00, 0x25, 0x40, 0x25, 0x40, 0x45, - 0x40, 0xe5, 0x04, 0x60, 0x27, 0x06, 0x27, 0x40, 0x47, 0x00, 0x47, 0x06, - 0x20, 0x05, 0xa0, 0x07, 0xe0, 0x06, 0xe9, 0x02, 0x4b, 0xaf, 0x0d, 0x0f, - 0x80, 0x06, 0x47, 0x06, 0xe5, 0x00, 0x00, 0x45, 0x00, 0xe5, 0x0f, 0x00, - 0xe5, 0x08, 0x40, 0x05, 0x46, 0x67, 0x00, 0x46, 0x00, 0x66, 0xc0, 0x26, - 0x00, 0x45, 0x80, 0x25, 0x26, 0x20, 0xe9, 0x02, 0xc0, 0x16, 0xcb, 0x0f, - 0x05, 0x06, 0x27, 0x16, 0xe5, 0x00, 0x00, 0x45, 0x00, 0xe5, 0x0f, 0x00, - 0xe5, 0x02, 0x00, 0x85, 0x20, 0x06, 0x05, 0x07, 0x06, 0x87, 0x00, 0x06, - 0x27, 0x00, 0x27, 0x26, 0xc0, 0x27, 0xc0, 0x05, 0x00, 0x25, 0x26, 0x20, - 0xe9, 0x02, 0x00, 0x25, 0xe0, 0x05, 0x26, 0x27, 0x00, 0xe5, 0x00, 0x00, - 0x45, 0x00, 0xe5, 0x21, 0x26, 0x05, 0x47, 0x66, 0x00, 0x47, 0x00, 0x47, - 0x06, 0x05, 0x0f, 0x60, 0x45, 0x07, 0xcb, 0x45, 0x26, 0x20, 0xe9, 0x02, - 0xeb, 0x01, 0x0f, 0xa5, 0x20, 0x27, 0x00, 0xe5, 0x0a, 0x40, 0xe5, 0x10, - 0x00, 0xe5, 0x01, 0x00, 0x05, 0x20, 0xc5, 0x40, 0x06, 0x60, 0x47, 0x46, - 0x00, 0x06, 0x00, 0xe7, 0x00, 0xa0, 0xe9, 0x02, 0x20, 0x27, 0x16, 0xe0, - 0x04, 0xe5, 0x28, 0x06, 0x25, 0xc6, 0x60, 0x0d, 0xa5, 0x04, 0xe6, 0x00, - 0x16, 0xe9, 0x02, 0x36, 0xe0, 0x1d, 0x25, 0x00, 0x05, 0x00, 0x85, 0x00, - 0xe5, 0x10, 0x00, 0x05, 0x00, 0xe5, 0x02, 0x06, 0x25, 0xe6, 0x01, 0x05, - 0x20, 0x85, 0x00, 0x04, 0x00, 0xa6, 0x20, 0xe9, 0x02, 0x20, 0x65, 0xe0, - 0x18, 0x05, 0x4f, 0xf6, 0x07, 0x0f, 0x16, 0x4f, 0x26, 0xaf, 0xe9, 0x02, - 0xeb, 0x02, 0x0f, 0x06, 0x0f, 0x06, 0x0f, 0x06, 0x12, 0x13, 0x12, 0x13, - 0x27, 0xe5, 0x00, 0x00, 0xe5, 0x1c, 0x60, 0xe6, 0x06, 0x07, 0x86, 0x16, - 0x26, 0x85, 0xe6, 0x03, 0x00, 0xe6, 0x1c, 0x00, 0xef, 0x00, 0x06, 0xaf, - 0x00, 0x2f, 0x96, 0x6f, 0x36, 0xe0, 0x1d, 0xe5, 0x23, 0x27, 0x66, 0x07, - 0xa6, 0x07, 0x26, 0x27, 0x26, 0x05, 0xe9, 0x02, 0xb6, 0xa5, 0x27, 0x26, - 0x65, 0x46, 0x05, 0x47, 0x25, 0xc7, 0x45, 0x66, 0xe5, 0x05, 0x06, 0x27, - 0x26, 0xa7, 0x06, 0x05, 0x07, 0xe9, 0x02, 0x47, 0x06, 0x2f, 0xe1, 0x1e, - 0x00, 0x01, 0x80, 0x01, 0x20, 0xe2, 0x23, 0x16, 0x04, 0x42, 0xe5, 0x80, - 0xc1, 0x00, 0x65, 0x20, 0xc5, 0x00, 0x05, 0x00, 0x65, 0x20, 0xe5, 0x21, - 0x00, 0x65, 0x20, 0xe5, 0x19, 0x00, 0x65, 0x20, 0xc5, 0x00, 0x05, 0x00, - 0x65, 0x20, 0xe5, 0x07, 0x00, 0xe5, 0x31, 0x00, 0x65, 0x20, 0xe5, 0x3b, - 0x20, 0x46, 0xf6, 0x01, 0xeb, 0x0c, 0x40, 0xe5, 0x08, 0xef, 0x02, 0xa0, - 0xe1, 0x4e, 0x20, 0xa2, 0x20, 0x11, 0xe5, 0x81, 0xe4, 0x0f, 0x16, 0xe5, - 0x09, 0x17, 0xe5, 0x12, 0x12, 0x13, 0x40, 0xe5, 0x43, 0x56, 0x4a, 0xe5, - 0x00, 0xc0, 0xe5, 0x05, 0x00, 0x65, 0x46, 0xe0, 0x03, 0xe5, 0x0a, 0x46, - 0x36, 0xe0, 0x01, 0xe5, 0x0a, 0x26, 0xe0, 0x04, 0xe5, 0x05, 0x00, 0x45, - 0x00, 0x26, 0xe0, 0x04, 0xe5, 0x2c, 0x26, 0x07, 0xc6, 0xe7, 0x00, 0x06, - 0x27, 0xe6, 0x03, 0x56, 0x04, 0x56, 0x0d, 0x05, 0x06, 0x20, 0xe9, 0x02, - 0xa0, 0xeb, 0x02, 0xa0, 0xb6, 0x11, 0x76, 0x46, 0x1b, 0x00, 0xe9, 0x02, - 0xa0, 0xe5, 0x1b, 0x04, 0xe5, 0x2d, 0xc0, 0x85, 0x26, 0xe5, 0x1a, 0x06, - 0x05, 0x80, 0xe5, 0x3e, 0xe0, 0x02, 0xe5, 0x17, 0x00, 0x46, 0x67, 0x26, - 0x47, 0x60, 0x27, 0x06, 0xa7, 0x46, 0x60, 0x0f, 0x40, 0x36, 0xe9, 0x02, - 0xe5, 0x16, 0x20, 0x85, 0xe0, 0x03, 0xe5, 0x24, 0x60, 0xe5, 0x12, 0xa0, - 0xe9, 0x02, 0x0b, 0x40, 0xef, 0x1a, 0xe5, 0x0f, 0x26, 0x27, 0x06, 0x20, - 0x36, 0xe5, 0x2d, 0x07, 0x06, 0x07, 0xc6, 0x00, 0x06, 0x07, 0x06, 0x27, - 0xe6, 0x00, 0xa7, 0xe6, 0x02, 0x20, 0x06, 0xe9, 0x02, 0xa0, 0xe9, 0x02, - 0xa0, 0xd6, 0x04, 0xb6, 0x20, 0xe6, 0x06, 0x08, 0xe0, 0x39, 0x66, 0x07, - 0xe5, 0x27, 0x06, 0x07, 0x86, 0x07, 0x06, 0x87, 0x06, 0x27, 0xc5, 0x60, - 0xe9, 0x02, 0xd6, 0xef, 0x02, 0xe6, 0x01, 0xef, 0x01, 0x40, 0x26, 0x07, - 0xe5, 0x16, 0x07, 0x66, 0x27, 0x26, 0x07, 0x46, 0x25, 0xe9, 0x02, 0xe5, - 0x24, 0x06, 0x07, 0x26, 0x47, 0x06, 0x07, 0x46, 0x27, 0xe0, 0x00, 0x76, - 0xe5, 0x1c, 0xe7, 0x00, 0xe6, 0x00, 0x27, 0x26, 0x40, 0x96, 0xe9, 0x02, - 0x40, 0x45, 0xe9, 0x02, 0xe5, 0x16, 0xa4, 0x36, 0xe2, 0x01, 0xc0, 0xe1, - 0x23, 0x20, 0x41, 0xf6, 0x00, 0xe0, 0x00, 0x46, 0x16, 0xe6, 0x05, 0x07, - 0xc6, 0x65, 0x06, 0xa5, 0x06, 0x25, 0x07, 0x26, 0x05, 0x80, 0xe2, 0x24, - 0xe4, 0x37, 0xe2, 0x05, 0x04, 0xe2, 0x1a, 0xe4, 0x1d, 0xe6, 0x32, 0x00, - 0x86, 0xff, 0x80, 0x0e, 0xe2, 0x00, 0xff, 0x5a, 0xe2, 0x00, 0xe1, 0x00, - 0xa2, 0x20, 0xa1, 0x20, 0xe2, 0x00, 0xe1, 0x00, 0xe2, 0x00, 0xe1, 0x00, - 0xa2, 0x20, 0xa1, 0x20, 0xe2, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x3f, 0xc2, 0xe1, 0x00, 0xe2, 0x06, 0x20, 0xe2, 0x00, 0xe3, 0x00, - 0xe2, 0x00, 0xe3, 0x00, 0xe2, 0x00, 0xe3, 0x00, 0x82, 0x00, 0x22, 0x61, - 0x03, 0x0e, 0x02, 0x4e, 0x42, 0x00, 0x22, 0x61, 0x03, 0x4e, 0x62, 0x20, - 0x22, 0x61, 0x00, 0x4e, 0xe2, 0x00, 0x81, 0x4e, 0x20, 0x42, 0x00, 0x22, - 0x61, 0x03, 0x2e, 0x00, 0xf7, 0x03, 0x9b, 0xb1, 0x36, 0x14, 0x15, 0x12, - 0x34, 0x15, 0x12, 0x14, 0xf6, 0x00, 0x18, 0x19, 0x9b, 0x17, 0xf6, 0x01, - 0x14, 0x15, 0x76, 0x30, 0x56, 0x0c, 0x12, 0x13, 0xf6, 0x03, 0x0c, 0x16, - 0x10, 0xf6, 0x02, 0x17, 0x9b, 0x00, 0xfb, 0x02, 0x0b, 0x04, 0x20, 0xab, - 0x4c, 0x12, 0x13, 0x04, 0xeb, 0x02, 0x4c, 0x12, 0x13, 0x00, 0xe4, 0x05, - 0x40, 0xed, 0x18, 0xe0, 0x08, 0xe6, 0x05, 0x68, 0x06, 0x48, 0xe6, 0x04, - 0xe0, 0x07, 0x2f, 0x01, 0x6f, 0x01, 0x2f, 0x02, 0x41, 0x22, 0x41, 0x02, - 0x0f, 0x01, 0x2f, 0x0c, 0x81, 0xaf, 0x01, 0x0f, 0x01, 0x0f, 0x01, 0x0f, - 0x61, 0x0f, 0x02, 0x61, 0x02, 0x65, 0x02, 0x2f, 0x22, 0x21, 0x8c, 0x3f, - 0x42, 0x0f, 0x0c, 0x2f, 0x02, 0x0f, 0xeb, 0x08, 0xea, 0x1b, 0x3f, 0x6a, - 0x0b, 0x2f, 0x60, 0x8c, 0x8f, 0x2c, 0x6f, 0x0c, 0x2f, 0x0c, 0x2f, 0x0c, - 0xcf, 0x0c, 0xef, 0x17, 0x2c, 0x2f, 0x0c, 0x0f, 0x0c, 0xef, 0x17, 0xec, - 0x80, 0x84, 0xef, 0x00, 0x12, 0x13, 0x12, 0x13, 0xef, 0x0c, 0x2c, 0xcf, - 0x12, 0x13, 0xef, 0x49, 0x0c, 0xef, 0x16, 0xec, 0x11, 0xef, 0x20, 0xac, - 0xef, 0x3d, 0xe0, 0x11, 0xef, 0x03, 0xe0, 0x0d, 0xeb, 0x34, 0xef, 0x46, - 0xeb, 0x0e, 0xef, 0x80, 0x2f, 0x0c, 0xef, 0x01, 0x0c, 0xef, 0x2e, 0xec, - 0x00, 0xef, 0x67, 0x0c, 0xef, 0x80, 0x70, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0xeb, 0x16, 0xef, - 0x24, 0x8c, 0x12, 0x13, 0xec, 0x17, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, - 0x12, 0x13, 0x12, 0x13, 0xec, 0x08, 0xef, 0x80, 0x78, 0xec, 0x7b, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0xec, 0x37, 0x12, - 0x13, 0x12, 0x13, 0xec, 0x18, 0x12, 0x13, 0xec, 0x80, 0x7a, 0xef, 0x28, - 0xec, 0x0d, 0x2f, 0xac, 0xef, 0x1f, 0x20, 0xef, 0x18, 0x20, 0xef, 0x60, - 0xe1, 0x27, 0x00, 0xe2, 0x27, 0x00, 0x5f, 0x21, 0x22, 0xdf, 0x41, 0x02, - 0x3f, 0x02, 0x3f, 0x82, 0x24, 0x41, 0x02, 0xff, 0x5a, 0x02, 0xaf, 0x7f, - 0x46, 0x3f, 0x80, 0x76, 0x0b, 0x36, 0xe2, 0x1e, 0x00, 0x02, 0x80, 0x02, - 0x20, 0xe5, 0x30, 0xc0, 0x04, 0x16, 0xe0, 0x06, 0x06, 0xe5, 0x0f, 0xe0, - 0x01, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, - 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xe6, 0x18, 0x36, 0x14, 0x15, 0x14, 0x15, - 0x56, 0x14, 0x15, 0x16, 0x14, 0x15, 0xf6, 0x01, 0x11, 0x36, 0x11, 0x16, - 0x14, 0x15, 0x36, 0x14, 0x15, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0x96, 0x04, 0xf6, 0x02, 0x31, 0x76, 0x11, 0x16, 0x12, 0xf6, 0x05, - 0xe0, 0x28, 0xef, 0x12, 0x00, 0xef, 0x51, 0xe0, 0x04, 0xef, 0x80, 0x4e, - 0xe0, 0x12, 0xef, 0x04, 0x60, 0x17, 0x56, 0x0f, 0x04, 0x05, 0x0a, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x2f, 0x12, 0x13, - 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x11, 0x12, 0x33, 0x0f, 0xea, 0x01, - 0x66, 0x27, 0x11, 0x84, 0x2f, 0x4a, 0x04, 0x05, 0x16, 0x2f, 0x00, 0xe5, - 0x4e, 0x20, 0x26, 0x2e, 0x24, 0x05, 0x11, 0xe5, 0x52, 0x16, 0x44, 0x05, - 0x80, 0xe5, 0x23, 0x00, 0xe5, 0x56, 0x00, 0x2f, 0x6b, 0xef, 0x02, 0xe5, - 0x13, 0x80, 0xef, 0x1c, 0xe0, 0x04, 0xe5, 0x08, 0xef, 0x17, 0x00, 0xeb, - 0x02, 0xef, 0x16, 0xeb, 0x00, 0x0f, 0xeb, 0x07, 0xef, 0x18, 0xeb, 0x02, - 0xef, 0x1f, 0xeb, 0x07, 0xef, 0x80, 0xb8, 0xe5, 0x99, 0x2e, 0xe0, 0x02, - 0xef, 0x38, 0xe5, 0xc0, 0x11, 0x68, 0xe0, 0x08, 0xe5, 0x0d, 0x04, 0xe5, - 0x83, 0xef, 0x40, 0xef, 0x2f, 0xe0, 0x01, 0xe5, 0x20, 0xa4, 0x36, 0xe5, - 0x80, 0x84, 0x04, 0x56, 0xe5, 0x08, 0xe9, 0x02, 0x25, 0xe0, 0x0c, 0xff, - 0x26, 0x05, 0x06, 0x48, 0x16, 0xe6, 0x02, 0x16, 0x04, 0xff, 0x14, 0x24, - 0x26, 0xe5, 0x3e, 0xea, 0x02, 0x26, 0xb6, 0xe0, 0x00, 0xee, 0x0f, 0xe4, - 0x01, 0x2e, 0xff, 0x06, 0x22, 0xff, 0x36, 0x04, 0xe2, 0x00, 0x9f, 0xff, - 0x02, 0x04, 0x2e, 0x7f, 0x05, 0x7f, 0x22, 0xff, 0x0d, 0x61, 0x02, 0x81, - 0x02, 0xff, 0x02, 0x20, 0x5f, 0x21, 0xe0, 0x28, 0x05, 0x24, 0x02, 0xc5, - 0x06, 0x45, 0x06, 0x65, 0x06, 0xe5, 0x0f, 0x27, 0x26, 0x07, 0x6f, 0x60, - 0xab, 0x2f, 0x0d, 0x0f, 0xa0, 0xe5, 0x2c, 0x76, 0xe0, 0x00, 0x27, 0xe5, - 0x2a, 0xe7, 0x08, 0x26, 0xe0, 0x00, 0x36, 0xe9, 0x02, 0xa0, 0xe6, 0x0a, - 0xa5, 0x56, 0x05, 0x16, 0x25, 0x06, 0xe9, 0x02, 0xe5, 0x14, 0xe6, 0x00, - 0x36, 0xe5, 0x0f, 0xe6, 0x03, 0x27, 0xe0, 0x03, 0x16, 0xe5, 0x15, 0x40, - 0x46, 0x07, 0xe5, 0x27, 0x06, 0x27, 0x66, 0x27, 0x26, 0x47, 0xf6, 0x05, - 0x00, 0x04, 0xe9, 0x02, 0x60, 0x36, 0x85, 0x06, 0x04, 0xe5, 0x01, 0xe9, - 0x02, 0x85, 0x00, 0xe5, 0x21, 0xa6, 0x27, 0x26, 0x27, 0x26, 0xe0, 0x01, - 0x45, 0x06, 0xe5, 0x00, 0x06, 0x07, 0x20, 0xe9, 0x02, 0x20, 0x76, 0xe5, - 0x08, 0x04, 0xa5, 0x4f, 0x05, 0x07, 0x06, 0x07, 0xe5, 0x2a, 0x06, 0x05, - 0x46, 0x25, 0x26, 0x85, 0x26, 0x05, 0x06, 0x05, 0xe0, 0x10, 0x25, 0x04, - 0x36, 0xe5, 0x03, 0x07, 0x26, 0x27, 0x36, 0x05, 0x24, 0x07, 0x06, 0xe0, - 0x02, 0xa5, 0x20, 0xa5, 0x20, 0xa5, 0xe0, 0x01, 0xc5, 0x00, 0xc5, 0x00, - 0xe2, 0x23, 0x0e, 0x64, 0xe2, 0x00, 0xe0, 0x00, 0xe2, 0x48, 0xe5, 0x1b, - 0x27, 0x06, 0x27, 0x06, 0x27, 0x16, 0x07, 0x06, 0x20, 0xe9, 0x02, 0xa0, - 0xe5, 0xab, 0x1c, 0xe0, 0x04, 0xe5, 0x0f, 0x60, 0xe5, 0x29, 0x60, 0xfc, - 0x87, 0x78, 0xfd, 0x98, 0x78, 0xe5, 0x80, 0xe6, 0x20, 0xe5, 0x62, 0xe0, - 0x1e, 0xc2, 0xe0, 0x04, 0x82, 0x80, 0x05, 0x06, 0xe5, 0x02, 0x0c, 0xe5, - 0x05, 0x00, 0x85, 0x00, 0x05, 0x00, 0x25, 0x00, 0x25, 0x00, 0xe5, 0x64, - 0xee, 0x08, 0xe0, 0x09, 0xe5, 0x80, 0xe3, 0x13, 0x12, 0xe0, 0x08, 0xe5, - 0x38, 0x20, 0xe5, 0x2e, 0xe0, 0x20, 0xe5, 0x04, 0x0d, 0x0f, 0x20, 0xe6, - 0x08, 0xd6, 0x12, 0x13, 0x16, 0xa0, 0xe6, 0x08, 0x16, 0x31, 0x30, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0x12, 0x13, 0x36, 0x12, 0x13, 0x76, 0x50, 0x56, 0x00, 0x76, 0x11, - 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x56, 0x0c, 0x11, 0x4c, 0x00, 0x16, - 0x0d, 0x36, 0x60, 0x85, 0x00, 0xe5, 0x7f, 0x20, 0x1b, 0x00, 0x56, 0x0d, - 0x56, 0x12, 0x13, 0x16, 0x0c, 0x16, 0x11, 0x36, 0xe9, 0x02, 0x36, 0x4c, - 0x36, 0xe1, 0x12, 0x12, 0x16, 0x13, 0x0e, 0x10, 0x0e, 0xe2, 0x12, 0x12, - 0x0c, 0x13, 0x0c, 0x12, 0x13, 0x16, 0x12, 0x13, 0x36, 0xe5, 0x02, 0x04, - 0xe5, 0x25, 0x24, 0xe5, 0x17, 0x40, 0xa5, 0x20, 0xa5, 0x20, 0xa5, 0x20, - 0x45, 0x40, 0x2d, 0x0c, 0x0e, 0x0f, 0x2d, 0x00, 0x0f, 0x6c, 0x2f, 0xe0, - 0x02, 0x5b, 0x2f, 0x20, 0xe5, 0x04, 0x00, 0xe5, 0x12, 0x00, 0xe5, 0x0b, - 0x00, 0x25, 0x00, 0xe5, 0x07, 0x20, 0xe5, 0x06, 0xe0, 0x1a, 0xe5, 0x73, - 0x80, 0x56, 0x60, 0xeb, 0x25, 0x40, 0xef, 0x01, 0xea, 0x2d, 0x6b, 0xef, - 0x09, 0x2b, 0x4f, 0x00, 0xef, 0x04, 0x60, 0x0f, 0xe0, 0x27, 0xef, 0x25, - 0x06, 0xe0, 0x7a, 0xe5, 0x15, 0x40, 0xe5, 0x29, 0xe0, 0x07, 0x06, 0xeb, - 0x13, 0x60, 0xe5, 0x18, 0x6b, 0xe0, 0x01, 0xe5, 0x0c, 0x0a, 0xe5, 0x00, - 0x0a, 0x80, 0xe5, 0x1e, 0x86, 0x80, 0xe5, 0x16, 0x00, 0x16, 0xe5, 0x1c, - 0x60, 0xe5, 0x00, 0x16, 0x8a, 0xe0, 0x22, 0xe1, 0x20, 0xe2, 0x20, 0xe5, - 0x46, 0x20, 0xe9, 0x02, 0xa0, 0xe1, 0x1c, 0x60, 0xe2, 0x1c, 0x60, 0xe5, - 0x20, 0xe0, 0x00, 0xe5, 0x2c, 0xe0, 0x03, 0x16, 0xe0, 0x80, 0x08, 0xe5, - 0x80, 0xaf, 0xe0, 0x01, 0xe5, 0x0e, 0xe0, 0x02, 0xe5, 0x00, 0xe0, 0x80, - 0x10, 0xa5, 0x20, 0x05, 0x00, 0xe5, 0x24, 0x00, 0x25, 0x40, 0x05, 0x20, - 0xe5, 0x0f, 0x00, 0x16, 0xeb, 0x00, 0xe5, 0x0f, 0x2f, 0xcb, 0xe5, 0x17, - 0xe0, 0x00, 0xeb, 0x01, 0xe0, 0x28, 0xe5, 0x0b, 0x00, 0x25, 0x80, 0x8b, - 0xe5, 0x0e, 0xab, 0x40, 0x16, 0xe5, 0x12, 0x80, 0x16, 0xe0, 0x38, 0xe5, - 0x30, 0x60, 0x2b, 0x25, 0xeb, 0x08, 0x20, 0xeb, 0x26, 0x05, 0x46, 0x00, - 0x26, 0x80, 0x66, 0x65, 0x00, 0x45, 0x00, 0xe5, 0x15, 0x20, 0x46, 0x60, - 0x06, 0xeb, 0x01, 0xc0, 0xf6, 0x01, 0xc0, 0xe5, 0x15, 0x2b, 0x16, 0xe5, - 0x15, 0x4b, 0xe0, 0x18, 0xe5, 0x00, 0x0f, 0xe5, 0x14, 0x26, 0x60, 0x8b, - 0xd6, 0xe0, 0x01, 0xe5, 0x2e, 0x40, 0xd6, 0xe5, 0x0e, 0x20, 0xeb, 0x00, - 0xe5, 0x0b, 0x80, 0xeb, 0x00, 0xe5, 0x0a, 0xc0, 0x76, 0xe0, 0x04, 0xcb, - 0xe0, 0x48, 0xe5, 0x41, 0xe0, 0x2f, 0xe1, 0x2b, 0xe0, 0x05, 0xe2, 0x2b, - 0xc0, 0xab, 0xe5, 0x1c, 0x66, 0xe0, 0x00, 0xe9, 0x02, 0xe0, 0x80, 0x9e, - 0xeb, 0x17, 0xe0, 0x79, 0xe5, 0x15, 0xeb, 0x02, 0x05, 0xe0, 0x00, 0xe5, - 0x0e, 0xe6, 0x03, 0x6b, 0x96, 0xe0, 0x7e, 0xe5, 0x0f, 0xe0, 0x01, 0x07, - 0x06, 0x07, 0xe5, 0x2d, 0xe6, 0x07, 0xd6, 0x60, 0xeb, 0x0c, 0xe9, 0x02, - 0xe0, 0x07, 0x46, 0x07, 0xe5, 0x25, 0x47, 0x66, 0x27, 0x26, 0x36, 0x1b, - 0x76, 0xe0, 0x03, 0x1b, 0x20, 0xe5, 0x11, 0xc0, 0xe9, 0x02, 0xa0, 0x46, - 0xe5, 0x1c, 0x86, 0x07, 0xe6, 0x00, 0x00, 0xe9, 0x02, 0x76, 0x05, 0x27, - 0xe0, 0x01, 0xe5, 0x1b, 0x06, 0x36, 0x05, 0xe0, 0x01, 0x26, 0x07, 0xe5, - 0x28, 0x47, 0xe6, 0x01, 0x27, 0x65, 0x76, 0x66, 0x16, 0x20, 0xe9, 0x02, - 0x05, 0x16, 0x05, 0x56, 0x00, 0xeb, 0x0c, 0xe0, 0x03, 0xe5, 0x0a, 0x00, - 0xe5, 0x11, 0x47, 0x46, 0x27, 0x06, 0x07, 0x26, 0xb6, 0x06, 0xe0, 0x39, - 0xc5, 0x00, 0x05, 0x00, 0x65, 0x00, 0xe5, 0x07, 0x00, 0xe5, 0x02, 0x16, - 0xa0, 0xe5, 0x27, 0x06, 0x47, 0xe6, 0x00, 0x80, 0xe9, 0x02, 0xa0, 0x26, - 0x27, 0x00, 0xe5, 0x00, 0x20, 0x25, 0x20, 0xe5, 0x0e, 0x00, 0xc5, 0x00, - 0x25, 0x00, 0x85, 0x00, 0x26, 0x05, 0x27, 0x06, 0x67, 0x20, 0x27, 0x20, - 0x47, 0x20, 0x05, 0xa0, 0x07, 0x80, 0x85, 0x27, 0x20, 0xc6, 0x40, 0x86, - 0xe0, 0x80, 0x03, 0xe5, 0x2d, 0x47, 0xe6, 0x00, 0x27, 0x46, 0x07, 0x06, - 0x65, 0x96, 0xe9, 0x02, 0x00, 0x16, 0x00, 0x16, 0x06, 0x05, 0xe0, 0x18, - 0xe5, 0x28, 0x47, 0xa6, 0x07, 0x06, 0x67, 0x26, 0x07, 0x26, 0x25, 0x16, - 0x05, 0xe0, 0x00, 0xe9, 0x02, 0xe0, 0x80, 0x1e, 0xe5, 0x27, 0x47, 0x66, - 0x20, 0x67, 0x26, 0x07, 0x26, 0xf6, 0x0f, 0x65, 0x26, 0xe0, 0x1a, 0xe5, - 0x28, 0x47, 0xe6, 0x00, 0x27, 0x06, 0x07, 0x26, 0x56, 0x05, 0xe0, 0x03, - 0xe9, 0x02, 0xa0, 0xf6, 0x05, 0xe0, 0x0b, 0xe5, 0x23, 0x06, 0x07, 0x06, - 0x27, 0xa6, 0x07, 0x06, 0x05, 0xc0, 0xe9, 0x02, 0xe0, 0x2e, 0xe5, 0x13, - 0x20, 0x46, 0x27, 0x66, 0x07, 0x86, 0x60, 0xe9, 0x02, 0x2b, 0x56, 0x0f, - 0xe0, 0x80, 0x38, 0xe5, 0x24, 0x47, 0xe6, 0x01, 0x07, 0x26, 0x16, 0xe0, - 0x5c, 0xe1, 0x18, 0xe2, 0x18, 0xe9, 0x02, 0xeb, 0x01, 0xe0, 0x04, 0x05, - 0xe0, 0x80, 0x18, 0xe5, 0x00, 0x20, 0xe5, 0x1f, 0x47, 0x66, 0x20, 0x26, - 0x67, 0x06, 0x05, 0x16, 0x05, 0x07, 0xe0, 0x13, 0x05, 0xe6, 0x02, 0xe5, - 0x20, 0xa6, 0x07, 0x05, 0x66, 0xf6, 0x00, 0x06, 0xe0, 0x00, 0x05, 0xa6, - 0x27, 0x46, 0xe5, 0x26, 0xe6, 0x05, 0x07, 0x26, 0x56, 0x05, 0x96, 0xe0, - 0x15, 0xe5, 0x31, 0xe0, 0x80, 0x7f, 0xe5, 0x01, 0x00, 0xe5, 0x1d, 0x07, - 0xc6, 0x00, 0xa6, 0x07, 0x06, 0x05, 0x96, 0xe0, 0x02, 0xe9, 0x02, 0xeb, - 0x0b, 0x40, 0x36, 0xe5, 0x16, 0x20, 0xe6, 0x0e, 0x00, 0x07, 0xc6, 0x07, - 0x26, 0x07, 0x26, 0xe0, 0x41, 0xc5, 0x00, 0x25, 0x00, 0xe5, 0x1e, 0xa6, - 0x40, 0x06, 0x00, 0x26, 0x00, 0xc6, 0x05, 0x06, 0xe0, 0x00, 0xe9, 0x02, - 0xa0, 0xa5, 0x00, 0x25, 0x00, 0xe5, 0x18, 0x87, 0x00, 0x26, 0x00, 0x27, - 0x06, 0x07, 0x06, 0x05, 0xc0, 0xe9, 0x02, 0xe0, 0x80, 0xae, 0xe5, 0x0b, - 0x26, 0x27, 0x36, 0xe0, 0x80, 0x3f, 0xeb, 0x0d, 0xef, 0x00, 0x6d, 0xef, - 0x09, 0xe0, 0x05, 0x16, 0xe5, 0x83, 0x12, 0xe0, 0x5e, 0xea, 0x67, 0x00, - 0x96, 0xe0, 0x03, 0xe5, 0x80, 0x3c, 0xe0, 0x8a, 0x34, 0xe5, 0x83, 0xa7, - 0x00, 0xfb, 0x01, 0xe0, 0x8f, 0x3f, 0xe5, 0x81, 0xbf, 0xe0, 0xa1, 0x31, - 0xe5, 0x81, 0xb1, 0xc0, 0xe5, 0x17, 0x00, 0xe9, 0x02, 0x60, 0x36, 0xe0, - 0x58, 0xe5, 0x16, 0x20, 0x86, 0x16, 0xe0, 0x02, 0xe5, 0x28, 0xc6, 0x96, - 0x6f, 0x64, 0x16, 0x0f, 0xe0, 0x02, 0xe9, 0x02, 0x00, 0xcb, 0x00, 0xe5, - 0x0d, 0x80, 0xe5, 0x0b, 0xe0, 0x82, 0x28, 0xe1, 0x18, 0xe2, 0x18, 0xeb, - 0x0f, 0x76, 0xe0, 0x5d, 0xe5, 0x43, 0x60, 0x06, 0x05, 0xe7, 0x2f, 0xc0, - 0x66, 0xe4, 0x05, 0xe0, 0x38, 0x24, 0x16, 0x04, 0xe0, 0x14, 0xe5, 0x97, - 0x70, 0xe0, 0x00, 0xe5, 0x82, 0x6b, 0xe0, 0xa4, 0x85, 0xe5, 0x80, 0x97, - 0xe0, 0x29, 0x45, 0xe0, 0x09, 0x65, 0xe0, 0x00, 0xe5, 0x81, 0x04, 0xe0, - 0x88, 0x7c, 0xe5, 0x63, 0x80, 0xe5, 0x05, 0x40, 0xe5, 0x01, 0xc0, 0xe5, - 0x02, 0x20, 0x0f, 0x26, 0x16, 0x7b, 0xe0, 0x92, 0xd4, 0xef, 0x80, 0x6e, - 0xe0, 0x02, 0xef, 0x1f, 0x20, 0xef, 0x34, 0x27, 0x46, 0x4f, 0xa7, 0xfb, - 0x00, 0xe6, 0x00, 0x2f, 0xc6, 0xef, 0x16, 0x66, 0xef, 0x33, 0xe0, 0x0f, - 0xef, 0x3a, 0x46, 0x0f, 0xe0, 0x80, 0x12, 0xeb, 0x0c, 0xe0, 0x04, 0xef, - 0x4f, 0xe0, 0x01, 0xeb, 0x11, 0xe0, 0x7f, 0xe1, 0x12, 0xe2, 0x12, 0xe1, - 0x12, 0xc2, 0x00, 0xe2, 0x0a, 0xe1, 0x12, 0xe2, 0x12, 0x01, 0x00, 0x21, - 0x20, 0x01, 0x20, 0x21, 0x20, 0x61, 0x00, 0xe1, 0x00, 0x62, 0x00, 0x02, - 0x00, 0xc2, 0x00, 0xe2, 0x03, 0xe1, 0x12, 0xe2, 0x12, 0x21, 0x00, 0x61, - 0x20, 0xe1, 0x00, 0x00, 0xc1, 0x00, 0xe2, 0x12, 0x21, 0x00, 0x61, 0x00, - 0x81, 0x00, 0x01, 0x40, 0xc1, 0x00, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, - 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, - 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x14, 0x20, 0xe1, 0x11, 0x0c, - 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, - 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, - 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0x3f, 0x20, 0xe9, 0x2a, - 0xef, 0x81, 0x78, 0xe6, 0x2f, 0x6f, 0xe6, 0x2a, 0xef, 0x00, 0x06, 0xef, - 0x06, 0x06, 0x2f, 0x96, 0xe0, 0x07, 0x86, 0x00, 0xe6, 0x07, 0xe0, 0x84, - 0xc8, 0xc6, 0x00, 0xe6, 0x09, 0x20, 0xc6, 0x00, 0x26, 0x00, 0x86, 0xe0, - 0x80, 0x4d, 0xe5, 0x25, 0x40, 0xc6, 0xc4, 0x20, 0xe9, 0x02, 0x60, 0x05, - 0x0f, 0xe0, 0x80, 0xe8, 0xe5, 0x24, 0x66, 0xe9, 0x02, 0x80, 0x0d, 0xe0, - 0x84, 0x78, 0xe5, 0x80, 0x3d, 0x20, 0xeb, 0x01, 0xc6, 0xe0, 0x21, 0xe1, - 0x1a, 0xe2, 0x1a, 0xc6, 0x04, 0x60, 0xe9, 0x02, 0x60, 0x36, 0xe0, 0x82, - 0x89, 0xeb, 0x33, 0x0f, 0x4b, 0x0d, 0x6b, 0xe0, 0x44, 0xeb, 0x25, 0x0f, - 0xeb, 0x07, 0xe0, 0x80, 0x3a, 0x65, 0x00, 0xe5, 0x13, 0x00, 0x25, 0x00, - 0x05, 0x20, 0x05, 0x00, 0xe5, 0x02, 0x00, 0x65, 0x00, 0x05, 0x00, 0x05, - 0xa0, 0x05, 0x60, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x45, 0x00, 0x25, - 0x00, 0x05, 0x20, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, - 0x00, 0x25, 0x00, 0x05, 0x20, 0x65, 0x00, 0xc5, 0x00, 0x65, 0x00, 0x65, - 0x00, 0x05, 0x00, 0xe5, 0x02, 0x00, 0xe5, 0x09, 0x80, 0x45, 0x00, 0x85, - 0x00, 0xe5, 0x09, 0xe0, 0x2c, 0x2c, 0xe0, 0x80, 0x86, 0xef, 0x24, 0x60, - 0xef, 0x5c, 0xe0, 0x04, 0xef, 0x07, 0x20, 0xef, 0x07, 0x00, 0xef, 0x07, - 0x00, 0xef, 0x1d, 0xe0, 0x02, 0xeb, 0x05, 0x40, 0xef, 0x55, 0x40, 0xef, - 0x35, 0xe0, 0x31, 0xef, 0x15, 0xe0, 0x05, 0xef, 0x24, 0x60, 0xef, 0x01, - 0xc0, 0x2f, 0xe0, 0x06, 0xaf, 0xe0, 0x80, 0x12, 0xef, 0x80, 0x73, 0x8e, - 0xef, 0x82, 0x4e, 0xe0, 0x02, 0xef, 0x05, 0x40, 0xef, 0x03, 0x80, 0xef, - 0x6c, 0xe0, 0x04, 0xef, 0x51, 0xc0, 0xef, 0x04, 0xe0, 0x0c, 0xef, 0x04, - 0x60, 0xef, 0x30, 0xe0, 0x00, 0xef, 0x02, 0xa0, 0xef, 0x20, 0xe0, 0x00, - 0xef, 0x16, 0xe0, 0x4a, 0xef, 0x04, 0x00, 0xef, 0x5d, 0x00, 0x6f, 0x40, - 0xef, 0x21, 0x20, 0xaf, 0x40, 0xef, 0x15, 0x20, 0xef, 0x7f, 0xe0, 0x04, - 0xef, 0x06, 0x20, 0x6f, 0x60, 0x4f, 0x80, 0x4f, 0xe0, 0x05, 0xaf, 0xe0, - 0x84, 0xe2, 0xe5, 0xc0, 0x66, 0x4f, 0xe0, 0x21, 0xe5, 0x8f, 0xad, 0xe0, - 0x03, 0xe5, 0x80, 0x56, 0x20, 0xe5, 0x95, 0xfa, 0xe0, 0x06, 0xe5, 0x9c, - 0xa9, 0xe0, 0x8b, 0x97, 0xe5, 0x81, 0x96, 0xe0, 0xca, 0xc5, 0x5b, 0x1b, - 0xe0, 0x16, 0xfb, 0x58, 0xe0, 0x78, 0xe6, 0x80, 0x68, 0xe0, 0xc0, 0xbd, - 0x88, 0xfd, 0xc0, 0xbf, 0x76, 0x20, 0xfd, 0xc0, 0xbf, 0x76, 0x20, -}; - -typedef enum { - UNICODE_SCRIPT_Unknown, - UNICODE_SCRIPT_Adlam, - UNICODE_SCRIPT_Ahom, - UNICODE_SCRIPT_Anatolian_Hieroglyphs, - UNICODE_SCRIPT_Arabic, - UNICODE_SCRIPT_Armenian, - UNICODE_SCRIPT_Avestan, - UNICODE_SCRIPT_Balinese, - UNICODE_SCRIPT_Bamum, - UNICODE_SCRIPT_Bassa_Vah, - UNICODE_SCRIPT_Batak, - UNICODE_SCRIPT_Bengali, - UNICODE_SCRIPT_Bhaiksuki, - UNICODE_SCRIPT_Bopomofo, - UNICODE_SCRIPT_Brahmi, - UNICODE_SCRIPT_Braille, - UNICODE_SCRIPT_Buginese, - UNICODE_SCRIPT_Buhid, - UNICODE_SCRIPT_Canadian_Aboriginal, - UNICODE_SCRIPT_Carian, - UNICODE_SCRIPT_Caucasian_Albanian, - UNICODE_SCRIPT_Chakma, - UNICODE_SCRIPT_Cham, - UNICODE_SCRIPT_Cherokee, - UNICODE_SCRIPT_Common, - UNICODE_SCRIPT_Coptic, - UNICODE_SCRIPT_Cuneiform, - UNICODE_SCRIPT_Cypriot, - UNICODE_SCRIPT_Cyrillic, - UNICODE_SCRIPT_Deseret, - UNICODE_SCRIPT_Devanagari, - UNICODE_SCRIPT_Dogra, - UNICODE_SCRIPT_Duployan, - UNICODE_SCRIPT_Egyptian_Hieroglyphs, - UNICODE_SCRIPT_Elbasan, - UNICODE_SCRIPT_Elymaic, - UNICODE_SCRIPT_Ethiopic, - UNICODE_SCRIPT_Georgian, - UNICODE_SCRIPT_Glagolitic, - UNICODE_SCRIPT_Gothic, - UNICODE_SCRIPT_Grantha, - UNICODE_SCRIPT_Greek, - UNICODE_SCRIPT_Gujarati, - UNICODE_SCRIPT_Gunjala_Gondi, - UNICODE_SCRIPT_Gurmukhi, - UNICODE_SCRIPT_Han, - UNICODE_SCRIPT_Hangul, - UNICODE_SCRIPT_Hanifi_Rohingya, - UNICODE_SCRIPT_Hanunoo, - UNICODE_SCRIPT_Hatran, - UNICODE_SCRIPT_Hebrew, - UNICODE_SCRIPT_Hiragana, - UNICODE_SCRIPT_Imperial_Aramaic, - UNICODE_SCRIPT_Inherited, - UNICODE_SCRIPT_Inscriptional_Pahlavi, - UNICODE_SCRIPT_Inscriptional_Parthian, - UNICODE_SCRIPT_Javanese, - UNICODE_SCRIPT_Kaithi, - UNICODE_SCRIPT_Kannada, - UNICODE_SCRIPT_Katakana, - UNICODE_SCRIPT_Kayah_Li, - UNICODE_SCRIPT_Kharoshthi, - UNICODE_SCRIPT_Khmer, - UNICODE_SCRIPT_Khojki, - UNICODE_SCRIPT_Khudawadi, - UNICODE_SCRIPT_Lao, - UNICODE_SCRIPT_Latin, - UNICODE_SCRIPT_Lepcha, - UNICODE_SCRIPT_Limbu, - UNICODE_SCRIPT_Linear_A, - UNICODE_SCRIPT_Linear_B, - UNICODE_SCRIPT_Lisu, - UNICODE_SCRIPT_Lycian, - UNICODE_SCRIPT_Lydian, - UNICODE_SCRIPT_Makasar, - UNICODE_SCRIPT_Mahajani, - UNICODE_SCRIPT_Malayalam, - UNICODE_SCRIPT_Mandaic, - UNICODE_SCRIPT_Manichaean, - UNICODE_SCRIPT_Marchen, - UNICODE_SCRIPT_Masaram_Gondi, - UNICODE_SCRIPT_Medefaidrin, - UNICODE_SCRIPT_Meetei_Mayek, - UNICODE_SCRIPT_Mende_Kikakui, - UNICODE_SCRIPT_Meroitic_Cursive, - UNICODE_SCRIPT_Meroitic_Hieroglyphs, - UNICODE_SCRIPT_Miao, - UNICODE_SCRIPT_Modi, - UNICODE_SCRIPT_Mongolian, - UNICODE_SCRIPT_Mro, - UNICODE_SCRIPT_Multani, - UNICODE_SCRIPT_Myanmar, - UNICODE_SCRIPT_Nabataean, - UNICODE_SCRIPT_Nandinagari, - UNICODE_SCRIPT_New_Tai_Lue, - UNICODE_SCRIPT_Newa, - UNICODE_SCRIPT_Nko, - UNICODE_SCRIPT_Nushu, - UNICODE_SCRIPT_Nyiakeng_Puachue_Hmong, - UNICODE_SCRIPT_Ogham, - UNICODE_SCRIPT_Ol_Chiki, - UNICODE_SCRIPT_Old_Hungarian, - UNICODE_SCRIPT_Old_Italic, - UNICODE_SCRIPT_Old_North_Arabian, - UNICODE_SCRIPT_Old_Permic, - UNICODE_SCRIPT_Old_Persian, - UNICODE_SCRIPT_Old_Sogdian, - UNICODE_SCRIPT_Old_South_Arabian, - UNICODE_SCRIPT_Old_Turkic, - UNICODE_SCRIPT_Oriya, - UNICODE_SCRIPT_Osage, - UNICODE_SCRIPT_Osmanya, - UNICODE_SCRIPT_Pahawh_Hmong, - UNICODE_SCRIPT_Palmyrene, - UNICODE_SCRIPT_Pau_Cin_Hau, - UNICODE_SCRIPT_Phags_Pa, - UNICODE_SCRIPT_Phoenician, - UNICODE_SCRIPT_Psalter_Pahlavi, - UNICODE_SCRIPT_Rejang, - UNICODE_SCRIPT_Runic, - UNICODE_SCRIPT_Samaritan, - UNICODE_SCRIPT_Saurashtra, - UNICODE_SCRIPT_Sharada, - UNICODE_SCRIPT_Shavian, - UNICODE_SCRIPT_Siddham, - UNICODE_SCRIPT_SignWriting, - UNICODE_SCRIPT_Sinhala, - UNICODE_SCRIPT_Sogdian, - UNICODE_SCRIPT_Sora_Sompeng, - UNICODE_SCRIPT_Soyombo, - UNICODE_SCRIPT_Sundanese, - UNICODE_SCRIPT_Syloti_Nagri, - UNICODE_SCRIPT_Syriac, - UNICODE_SCRIPT_Tagalog, - UNICODE_SCRIPT_Tagbanwa, - UNICODE_SCRIPT_Tai_Le, - UNICODE_SCRIPT_Tai_Tham, - UNICODE_SCRIPT_Tai_Viet, - UNICODE_SCRIPT_Takri, - UNICODE_SCRIPT_Tamil, - UNICODE_SCRIPT_Tangut, - UNICODE_SCRIPT_Telugu, - UNICODE_SCRIPT_Thaana, - UNICODE_SCRIPT_Thai, - UNICODE_SCRIPT_Tibetan, - UNICODE_SCRIPT_Tifinagh, - UNICODE_SCRIPT_Tirhuta, - UNICODE_SCRIPT_Ugaritic, - UNICODE_SCRIPT_Vai, - UNICODE_SCRIPT_Wancho, - UNICODE_SCRIPT_Warang_Citi, - UNICODE_SCRIPT_Yi, - UNICODE_SCRIPT_Zanabazar_Square, - UNICODE_SCRIPT_COUNT, -} UnicodeScriptEnum; - -static const char unicode_script_name_table[] = - "Adlam,Adlm" - "\0" - "Ahom,Ahom" - "\0" - "Anatolian_Hieroglyphs,Hluw" - "\0" - "Arabic,Arab" - "\0" - "Armenian,Armn" - "\0" - "Avestan,Avst" - "\0" - "Balinese,Bali" - "\0" - "Bamum,Bamu" - "\0" - "Bassa_Vah,Bass" - "\0" - "Batak,Batk" - "\0" - "Bengali,Beng" - "\0" - "Bhaiksuki,Bhks" - "\0" - "Bopomofo,Bopo" - "\0" - "Brahmi,Brah" - "\0" - "Braille,Brai" - "\0" - "Buginese,Bugi" - "\0" - "Buhid,Buhd" - "\0" - "Canadian_Aboriginal,Cans" - "\0" - "Carian,Cari" - "\0" - "Caucasian_Albanian,Aghb" - "\0" - "Chakma,Cakm" - "\0" - "Cham,Cham" - "\0" - "Cherokee,Cher" - "\0" - "Common,Zyyy" - "\0" - "Coptic,Copt,Qaac" - "\0" - "Cuneiform,Xsux" - "\0" - "Cypriot,Cprt" - "\0" - "Cyrillic,Cyrl" - "\0" - "Deseret,Dsrt" - "\0" - "Devanagari,Deva" - "\0" - "Dogra,Dogr" - "\0" - "Duployan,Dupl" - "\0" - "Egyptian_Hieroglyphs,Egyp" - "\0" - "Elbasan,Elba" - "\0" - "Elymaic,Elym" - "\0" - "Ethiopic,Ethi" - "\0" - "Georgian,Geor" - "\0" - "Glagolitic,Glag" - "\0" - "Gothic,Goth" - "\0" - "Grantha,Gran" - "\0" - "Greek,Grek" - "\0" - "Gujarati,Gujr" - "\0" - "Gunjala_Gondi,Gong" - "\0" - "Gurmukhi,Guru" - "\0" - "Han,Hani" - "\0" - "Hangul,Hang" - "\0" - "Hanifi_Rohingya,Rohg" - "\0" - "Hanunoo,Hano" - "\0" - "Hatran,Hatr" - "\0" - "Hebrew,Hebr" - "\0" - "Hiragana,Hira" - "\0" - "Imperial_Aramaic,Armi" - "\0" - "Inherited,Zinh,Qaai" - "\0" - "Inscriptional_Pahlavi,Phli" - "\0" - "Inscriptional_Parthian,Prti" - "\0" - "Javanese,Java" - "\0" - "Kaithi,Kthi" - "\0" - "Kannada,Knda" - "\0" - "Katakana,Kana" - "\0" - "Kayah_Li,Kali" - "\0" - "Kharoshthi,Khar" - "\0" - "Khmer,Khmr" - "\0" - "Khojki,Khoj" - "\0" - "Khudawadi,Sind" - "\0" - "Lao,Laoo" - "\0" - "Latin,Latn" - "\0" - "Lepcha,Lepc" - "\0" - "Limbu,Limb" - "\0" - "Linear_A,Lina" - "\0" - "Linear_B,Linb" - "\0" - "Lisu,Lisu" - "\0" - "Lycian,Lyci" - "\0" - "Lydian,Lydi" - "\0" - "Makasar,Maka" - "\0" - "Mahajani,Mahj" - "\0" - "Malayalam,Mlym" - "\0" - "Mandaic,Mand" - "\0" - "Manichaean,Mani" - "\0" - "Marchen,Marc" - "\0" - "Masaram_Gondi,Gonm" - "\0" - "Medefaidrin,Medf" - "\0" - "Meetei_Mayek,Mtei" - "\0" - "Mende_Kikakui,Mend" - "\0" - "Meroitic_Cursive,Merc" - "\0" - "Meroitic_Hieroglyphs,Mero" - "\0" - "Miao,Plrd" - "\0" - "Modi,Modi" - "\0" - "Mongolian,Mong" - "\0" - "Mro,Mroo" - "\0" - "Multani,Mult" - "\0" - "Myanmar,Mymr" - "\0" - "Nabataean,Nbat" - "\0" - "Nandinagari,Nand" - "\0" - "New_Tai_Lue,Talu" - "\0" - "Newa,Newa" - "\0" - "Nko,Nkoo" - "\0" - "Nushu,Nshu" - "\0" - "Nyiakeng_Puachue_Hmong,Hmnp" - "\0" - "Ogham,Ogam" - "\0" - "Ol_Chiki,Olck" - "\0" - "Old_Hungarian,Hung" - "\0" - "Old_Italic,Ital" - "\0" - "Old_North_Arabian,Narb" - "\0" - "Old_Permic,Perm" - "\0" - "Old_Persian,Xpeo" - "\0" - "Old_Sogdian,Sogo" - "\0" - "Old_South_Arabian,Sarb" - "\0" - "Old_Turkic,Orkh" - "\0" - "Oriya,Orya" - "\0" - "Osage,Osge" - "\0" - "Osmanya,Osma" - "\0" - "Pahawh_Hmong,Hmng" - "\0" - "Palmyrene,Palm" - "\0" - "Pau_Cin_Hau,Pauc" - "\0" - "Phags_Pa,Phag" - "\0" - "Phoenician,Phnx" - "\0" - "Psalter_Pahlavi,Phlp" - "\0" - "Rejang,Rjng" - "\0" - "Runic,Runr" - "\0" - "Samaritan,Samr" - "\0" - "Saurashtra,Saur" - "\0" - "Sharada,Shrd" - "\0" - "Shavian,Shaw" - "\0" - "Siddham,Sidd" - "\0" - "SignWriting,Sgnw" - "\0" - "Sinhala,Sinh" - "\0" - "Sogdian,Sogd" - "\0" - "Sora_Sompeng,Sora" - "\0" - "Soyombo,Soyo" - "\0" - "Sundanese,Sund" - "\0" - "Syloti_Nagri,Sylo" - "\0" - "Syriac,Syrc" - "\0" - "Tagalog,Tglg" - "\0" - "Tagbanwa,Tagb" - "\0" - "Tai_Le,Tale" - "\0" - "Tai_Tham,Lana" - "\0" - "Tai_Viet,Tavt" - "\0" - "Takri,Takr" - "\0" - "Tamil,Taml" - "\0" - "Tangut,Tang" - "\0" - "Telugu,Telu" - "\0" - "Thaana,Thaa" - "\0" - "Thai,Thai" - "\0" - "Tibetan,Tibt" - "\0" - "Tifinagh,Tfng" - "\0" - "Tirhuta,Tirh" - "\0" - "Ugaritic,Ugar" - "\0" - "Vai,Vaii" - "\0" - "Wancho,Wcho" - "\0" - "Warang_Citi,Wara" - "\0" - "Yi,Yiii" - "\0" - "Zanabazar_Square,Zanb" - "\0"; - -static const uint8_t unicode_script_table[2565] = { - 0xc0, 0x18, 0x99, 0x42, 0x85, 0x18, 0x99, 0x42, 0xae, 0x18, 0x80, 0x42, - 0x8e, 0x18, 0x80, 0x42, 0x84, 0x18, 0x96, 0x42, 0x80, 0x18, 0x9e, 0x42, - 0x80, 0x18, 0xe1, 0x60, 0x42, 0xa6, 0x18, 0x84, 0x42, 0x84, 0x18, 0x81, - 0x0d, 0x93, 0x18, 0xe0, 0x0f, 0x35, 0x83, 0x29, 0x80, 0x18, 0x82, 0x29, - 0x01, 0x83, 0x29, 0x80, 0x18, 0x80, 0x29, 0x03, 0x80, 0x29, 0x80, 0x18, - 0x80, 0x29, 0x80, 0x18, 0x82, 0x29, 0x00, 0x80, 0x29, 0x00, 0x93, 0x29, - 0x00, 0xbe, 0x29, 0x8d, 0x19, 0x8f, 0x29, 0xe0, 0x24, 0x1c, 0x81, 0x35, - 0xe0, 0x48, 0x1c, 0x00, 0xa5, 0x05, 0x01, 0xaf, 0x05, 0x80, 0x18, 0x80, - 0x05, 0x01, 0x82, 0x05, 0x00, 0xb6, 0x32, 0x07, 0x9a, 0x32, 0x03, 0x85, - 0x32, 0x0a, 0x84, 0x04, 0x80, 0x18, 0x85, 0x04, 0x80, 0x18, 0x8d, 0x04, - 0x80, 0x18, 0x80, 0x04, 0x00, 0x80, 0x04, 0x80, 0x18, 0x9f, 0x04, 0x80, - 0x18, 0x89, 0x04, 0x8a, 0x35, 0x99, 0x04, 0x80, 0x35, 0xe0, 0x0b, 0x04, - 0x80, 0x18, 0xa1, 0x04, 0x8d, 0x84, 0x00, 0xbb, 0x84, 0x01, 0x82, 0x84, - 0xaf, 0x04, 0xb1, 0x8e, 0x0d, 0xba, 0x60, 0x01, 0x82, 0x60, 0xad, 0x78, - 0x01, 0x8e, 0x78, 0x00, 0x9b, 0x4d, 0x01, 0x80, 0x4d, 0x00, 0x8a, 0x84, - 0x34, 0x94, 0x04, 0x00, 0x87, 0x04, 0x14, 0x8e, 0x04, 0x80, 0x18, 0x9c, - 0x04, 0xd0, 0x1e, 0x83, 0x35, 0x8e, 0x1e, 0x81, 0x18, 0x99, 0x1e, 0x83, - 0x0b, 0x00, 0x87, 0x0b, 0x01, 0x81, 0x0b, 0x01, 0x95, 0x0b, 0x00, 0x86, - 0x0b, 0x00, 0x80, 0x0b, 0x02, 0x83, 0x0b, 0x01, 0x88, 0x0b, 0x01, 0x81, - 0x0b, 0x01, 0x83, 0x0b, 0x07, 0x80, 0x0b, 0x03, 0x81, 0x0b, 0x00, 0x84, - 0x0b, 0x01, 0x98, 0x0b, 0x01, 0x82, 0x2c, 0x00, 0x85, 0x2c, 0x03, 0x81, - 0x2c, 0x01, 0x95, 0x2c, 0x00, 0x86, 0x2c, 0x00, 0x81, 0x2c, 0x00, 0x81, - 0x2c, 0x00, 0x81, 0x2c, 0x01, 0x80, 0x2c, 0x00, 0x84, 0x2c, 0x03, 0x81, - 0x2c, 0x01, 0x82, 0x2c, 0x02, 0x80, 0x2c, 0x06, 0x83, 0x2c, 0x00, 0x80, - 0x2c, 0x06, 0x90, 0x2c, 0x09, 0x82, 0x2a, 0x00, 0x88, 0x2a, 0x00, 0x82, - 0x2a, 0x00, 0x95, 0x2a, 0x00, 0x86, 0x2a, 0x00, 0x81, 0x2a, 0x00, 0x84, - 0x2a, 0x01, 0x89, 0x2a, 0x00, 0x82, 0x2a, 0x00, 0x82, 0x2a, 0x01, 0x80, - 0x2a, 0x0e, 0x83, 0x2a, 0x01, 0x8b, 0x2a, 0x06, 0x86, 0x2a, 0x00, 0x82, - 0x6d, 0x00, 0x87, 0x6d, 0x01, 0x81, 0x6d, 0x01, 0x95, 0x6d, 0x00, 0x86, - 0x6d, 0x00, 0x81, 0x6d, 0x00, 0x84, 0x6d, 0x01, 0x88, 0x6d, 0x01, 0x81, - 0x6d, 0x01, 0x82, 0x6d, 0x07, 0x81, 0x6d, 0x03, 0x81, 0x6d, 0x00, 0x84, - 0x6d, 0x01, 0x91, 0x6d, 0x09, 0x81, 0x8b, 0x00, 0x85, 0x8b, 0x02, 0x82, - 0x8b, 0x00, 0x83, 0x8b, 0x02, 0x81, 0x8b, 0x00, 0x80, 0x8b, 0x00, 0x81, - 0x8b, 0x02, 0x81, 0x8b, 0x02, 0x82, 0x8b, 0x02, 0x8b, 0x8b, 0x03, 0x84, - 0x8b, 0x02, 0x82, 0x8b, 0x00, 0x83, 0x8b, 0x01, 0x80, 0x8b, 0x05, 0x80, - 0x8b, 0x0d, 0x94, 0x8b, 0x04, 0x8c, 0x8d, 0x00, 0x82, 0x8d, 0x00, 0x96, - 0x8d, 0x00, 0x8f, 0x8d, 0x02, 0x87, 0x8d, 0x00, 0x82, 0x8d, 0x00, 0x83, - 0x8d, 0x06, 0x81, 0x8d, 0x00, 0x82, 0x8d, 0x04, 0x83, 0x8d, 0x01, 0x89, - 0x8d, 0x06, 0x88, 0x8d, 0x8c, 0x3a, 0x00, 0x82, 0x3a, 0x00, 0x96, 0x3a, - 0x00, 0x89, 0x3a, 0x00, 0x84, 0x3a, 0x01, 0x88, 0x3a, 0x00, 0x82, 0x3a, - 0x00, 0x83, 0x3a, 0x06, 0x81, 0x3a, 0x06, 0x80, 0x3a, 0x00, 0x83, 0x3a, - 0x01, 0x89, 0x3a, 0x00, 0x81, 0x3a, 0x0c, 0x83, 0x4c, 0x00, 0x87, 0x4c, - 0x00, 0x82, 0x4c, 0x00, 0xb2, 0x4c, 0x00, 0x82, 0x4c, 0x00, 0x85, 0x4c, - 0x03, 0x8f, 0x4c, 0x01, 0x99, 0x4c, 0x01, 0x81, 0x7e, 0x00, 0x91, 0x7e, - 0x02, 0x97, 0x7e, 0x00, 0x88, 0x7e, 0x00, 0x80, 0x7e, 0x01, 0x86, 0x7e, - 0x02, 0x80, 0x7e, 0x03, 0x85, 0x7e, 0x00, 0x80, 0x7e, 0x00, 0x87, 0x7e, - 0x05, 0x89, 0x7e, 0x01, 0x82, 0x7e, 0x0b, 0xb9, 0x8f, 0x03, 0x80, 0x18, - 0x9b, 0x8f, 0x24, 0x81, 0x41, 0x00, 0x80, 0x41, 0x00, 0x84, 0x41, 0x00, - 0x97, 0x41, 0x00, 0x80, 0x41, 0x00, 0x96, 0x41, 0x01, 0x84, 0x41, 0x00, - 0x80, 0x41, 0x00, 0x85, 0x41, 0x01, 0x89, 0x41, 0x01, 0x83, 0x41, 0x1f, - 0xc7, 0x90, 0x00, 0xa3, 0x90, 0x03, 0xa6, 0x90, 0x00, 0xa3, 0x90, 0x00, - 0x8e, 0x90, 0x00, 0x86, 0x90, 0x83, 0x18, 0x81, 0x90, 0x24, 0xe0, 0x3f, - 0x5b, 0xa5, 0x25, 0x00, 0x80, 0x25, 0x04, 0x80, 0x25, 0x01, 0xaa, 0x25, - 0x80, 0x18, 0x83, 0x25, 0xe0, 0x9f, 0x2e, 0xc8, 0x24, 0x00, 0x83, 0x24, - 0x01, 0x86, 0x24, 0x00, 0x80, 0x24, 0x00, 0x83, 0x24, 0x01, 0xa8, 0x24, - 0x00, 0x83, 0x24, 0x01, 0xa0, 0x24, 0x00, 0x83, 0x24, 0x01, 0x86, 0x24, - 0x00, 0x80, 0x24, 0x00, 0x83, 0x24, 0x01, 0x8e, 0x24, 0x00, 0xb8, 0x24, - 0x00, 0x83, 0x24, 0x01, 0xc2, 0x24, 0x01, 0x9f, 0x24, 0x02, 0x99, 0x24, - 0x05, 0xd5, 0x17, 0x01, 0x85, 0x17, 0x01, 0xe2, 0x1f, 0x12, 0x9c, 0x63, - 0x02, 0xca, 0x77, 0x82, 0x18, 0x8a, 0x77, 0x06, 0x8c, 0x85, 0x00, 0x86, - 0x85, 0x0a, 0x94, 0x30, 0x81, 0x18, 0x08, 0x93, 0x11, 0x0b, 0x8c, 0x86, - 0x00, 0x82, 0x86, 0x00, 0x81, 0x86, 0x0b, 0xdd, 0x3e, 0x01, 0x89, 0x3e, - 0x05, 0x89, 0x3e, 0x05, 0x81, 0x58, 0x81, 0x18, 0x80, 0x58, 0x80, 0x18, - 0x88, 0x58, 0x00, 0x89, 0x58, 0x05, 0xd8, 0x58, 0x06, 0xaa, 0x58, 0x04, - 0xc5, 0x12, 0x09, 0x9e, 0x44, 0x00, 0x8b, 0x44, 0x03, 0x8b, 0x44, 0x03, - 0x80, 0x44, 0x02, 0x8b, 0x44, 0x9d, 0x87, 0x01, 0x84, 0x87, 0x0a, 0xab, - 0x5e, 0x03, 0x99, 0x5e, 0x05, 0x8a, 0x5e, 0x02, 0x81, 0x5e, 0x9f, 0x3e, - 0x9b, 0x10, 0x01, 0x81, 0x10, 0xbe, 0x88, 0x00, 0x9c, 0x88, 0x01, 0x8a, - 0x88, 0x05, 0x89, 0x88, 0x05, 0x8d, 0x88, 0x01, 0x8e, 0x35, 0x40, 0xcb, - 0x07, 0x03, 0xac, 0x07, 0x02, 0xbf, 0x82, 0xb3, 0x0a, 0x07, 0x83, 0x0a, - 0xb7, 0x43, 0x02, 0x8e, 0x43, 0x02, 0x82, 0x43, 0xaf, 0x64, 0x88, 0x1c, - 0x06, 0xaa, 0x25, 0x01, 0x82, 0x25, 0x87, 0x82, 0x07, 0x82, 0x35, 0x80, - 0x18, 0x8c, 0x35, 0x80, 0x18, 0x86, 0x35, 0x83, 0x18, 0x80, 0x35, 0x85, - 0x18, 0x80, 0x35, 0x82, 0x18, 0x81, 0x35, 0x80, 0x18, 0x04, 0xa5, 0x42, - 0x84, 0x29, 0x80, 0x1c, 0xb0, 0x42, 0x84, 0x29, 0x83, 0x42, 0x84, 0x29, - 0x8c, 0x42, 0x80, 0x1c, 0xc5, 0x42, 0x80, 0x29, 0xb9, 0x35, 0x00, 0x84, - 0x35, 0xe0, 0x9f, 0x42, 0x95, 0x29, 0x01, 0x85, 0x29, 0x01, 0xa5, 0x29, - 0x01, 0x85, 0x29, 0x01, 0x87, 0x29, 0x00, 0x80, 0x29, 0x00, 0x80, 0x29, - 0x00, 0x80, 0x29, 0x00, 0x9e, 0x29, 0x01, 0xb4, 0x29, 0x00, 0x8e, 0x29, - 0x00, 0x8d, 0x29, 0x01, 0x85, 0x29, 0x00, 0x92, 0x29, 0x01, 0x82, 0x29, - 0x00, 0x88, 0x29, 0x00, 0x8b, 0x18, 0x81, 0x35, 0xd6, 0x18, 0x00, 0x8a, - 0x18, 0x80, 0x42, 0x01, 0x8a, 0x18, 0x80, 0x42, 0x8e, 0x18, 0x00, 0x8c, - 0x42, 0x02, 0x9f, 0x18, 0x0f, 0xa0, 0x35, 0x0e, 0xa5, 0x18, 0x80, 0x29, - 0x82, 0x18, 0x81, 0x42, 0x85, 0x18, 0x80, 0x42, 0x9a, 0x18, 0x80, 0x42, - 0x90, 0x18, 0xa8, 0x42, 0x82, 0x18, 0x03, 0xe2, 0x36, 0x18, 0x18, 0x8a, - 0x18, 0x14, 0xe3, 0x3f, 0x18, 0xe0, 0x9f, 0x0f, 0xe2, 0x13, 0x18, 0x01, - 0x9f, 0x18, 0x01, 0xe0, 0x07, 0x18, 0xae, 0x26, 0x00, 0xae, 0x26, 0x00, - 0x9f, 0x42, 0xe0, 0x13, 0x19, 0x04, 0x86, 0x19, 0xa5, 0x25, 0x00, 0x80, - 0x25, 0x04, 0x80, 0x25, 0x01, 0xb7, 0x91, 0x06, 0x81, 0x91, 0x0d, 0x80, - 0x91, 0x96, 0x24, 0x08, 0x86, 0x24, 0x00, 0x86, 0x24, 0x00, 0x86, 0x24, - 0x00, 0x86, 0x24, 0x00, 0x86, 0x24, 0x00, 0x86, 0x24, 0x00, 0x86, 0x24, - 0x00, 0x86, 0x24, 0x00, 0x9f, 0x1c, 0xcf, 0x18, 0x2f, 0x99, 0x2d, 0x00, - 0xd8, 0x2d, 0x0b, 0xe0, 0x75, 0x2d, 0x19, 0x8b, 0x18, 0x03, 0x84, 0x18, - 0x80, 0x2d, 0x80, 0x18, 0x80, 0x2d, 0x98, 0x18, 0x88, 0x2d, 0x83, 0x35, - 0x81, 0x2e, 0x87, 0x18, 0x83, 0x2d, 0x83, 0x18, 0x00, 0xd5, 0x33, 0x01, - 0x81, 0x35, 0x81, 0x18, 0x82, 0x33, 0x80, 0x18, 0xd9, 0x3b, 0x81, 0x18, - 0x82, 0x3b, 0x04, 0xaa, 0x0d, 0x00, 0xdd, 0x2e, 0x00, 0x8f, 0x18, 0x9a, - 0x0d, 0x04, 0xa3, 0x18, 0x0b, 0x8f, 0x3b, 0x9e, 0x2e, 0x00, 0xbf, 0x18, - 0x9e, 0x2e, 0xd0, 0x18, 0xae, 0x3b, 0x80, 0x18, 0xd7, 0x3b, 0xe0, 0x47, - 0x18, 0xf0, 0x09, 0x55, 0x2d, 0x09, 0xbf, 0x18, 0xf0, 0x41, 0x8f, 0x2d, - 0x0f, 0xe4, 0x2c, 0x97, 0x02, 0xb6, 0x97, 0x08, 0xaf, 0x47, 0xe0, 0xcb, - 0x94, 0x13, 0xdf, 0x1c, 0xd7, 0x08, 0x07, 0xa1, 0x18, 0xe0, 0x05, 0x42, - 0x82, 0x18, 0xb4, 0x42, 0x01, 0x84, 0x42, 0x2f, 0x88, 0x42, 0xab, 0x83, - 0x03, 0x89, 0x18, 0x05, 0xb7, 0x73, 0x07, 0xc5, 0x79, 0x07, 0x8b, 0x79, - 0x05, 0x9f, 0x1e, 0xad, 0x3c, 0x80, 0x18, 0x80, 0x3c, 0xa3, 0x76, 0x0a, - 0x80, 0x76, 0x9c, 0x2e, 0x02, 0xcd, 0x38, 0x00, 0x80, 0x18, 0x89, 0x38, - 0x03, 0x81, 0x38, 0x9e, 0x5b, 0x00, 0xb6, 0x16, 0x08, 0x8d, 0x16, 0x01, - 0x89, 0x16, 0x01, 0x83, 0x16, 0x9f, 0x5b, 0xc2, 0x89, 0x17, 0x84, 0x89, - 0x96, 0x52, 0x09, 0x85, 0x24, 0x01, 0x85, 0x24, 0x01, 0x85, 0x24, 0x08, - 0x86, 0x24, 0x00, 0x86, 0x24, 0x00, 0xaa, 0x42, 0x80, 0x18, 0x88, 0x42, - 0x80, 0x29, 0x81, 0x42, 0x07, 0xcf, 0x17, 0xad, 0x52, 0x01, 0x89, 0x52, - 0x05, 0xf0, 0x1b, 0x43, 0x2e, 0x0b, 0x96, 0x2e, 0x03, 0xb0, 0x2e, 0x70, - 0x10, 0xa3, 0xe1, 0x0d, 0x2d, 0x01, 0xe0, 0x09, 0x2d, 0x25, 0x86, 0x42, - 0x0b, 0x84, 0x05, 0x04, 0x99, 0x32, 0x00, 0x84, 0x32, 0x00, 0x80, 0x32, - 0x00, 0x81, 0x32, 0x00, 0x81, 0x32, 0x00, 0x89, 0x32, 0xe0, 0x11, 0x04, - 0x10, 0xe1, 0x0a, 0x04, 0x81, 0x18, 0x0f, 0xbf, 0x04, 0x01, 0xb5, 0x04, - 0x27, 0x8d, 0x04, 0x01, 0x8f, 0x35, 0x89, 0x18, 0x05, 0x8d, 0x35, 0x81, - 0x1c, 0xa2, 0x18, 0x00, 0x92, 0x18, 0x00, 0x83, 0x18, 0x03, 0x84, 0x04, - 0x00, 0xe0, 0x26, 0x04, 0x01, 0x80, 0x18, 0x00, 0x9f, 0x18, 0x99, 0x42, - 0x85, 0x18, 0x99, 0x42, 0x8a, 0x18, 0x89, 0x3b, 0x80, 0x18, 0xac, 0x3b, - 0x81, 0x18, 0x9e, 0x2e, 0x02, 0x85, 0x2e, 0x01, 0x85, 0x2e, 0x01, 0x85, - 0x2e, 0x01, 0x82, 0x2e, 0x02, 0x86, 0x18, 0x00, 0x86, 0x18, 0x09, 0x84, - 0x18, 0x01, 0x8b, 0x46, 0x00, 0x99, 0x46, 0x00, 0x92, 0x46, 0x00, 0x81, - 0x46, 0x00, 0x8e, 0x46, 0x01, 0x8d, 0x46, 0x21, 0xe0, 0x1a, 0x46, 0x04, - 0x82, 0x18, 0x03, 0xac, 0x18, 0x02, 0x88, 0x18, 0xce, 0x29, 0x00, 0x8b, - 0x18, 0x03, 0x80, 0x29, 0x2e, 0xac, 0x18, 0x80, 0x35, 0x60, 0x21, 0x9c, - 0x48, 0x02, 0xb0, 0x13, 0x0e, 0x80, 0x35, 0x9a, 0x18, 0x03, 0xa3, 0x66, - 0x08, 0x82, 0x66, 0x9a, 0x27, 0x04, 0xaa, 0x68, 0x04, 0x9d, 0x93, 0x00, - 0x80, 0x93, 0xa3, 0x69, 0x03, 0x8d, 0x69, 0x29, 0xcf, 0x1d, 0xaf, 0x7b, - 0x9d, 0x6f, 0x01, 0x89, 0x6f, 0x05, 0xa3, 0x6e, 0x03, 0xa3, 0x6e, 0x03, - 0xa7, 0x22, 0x07, 0xb3, 0x14, 0x0a, 0x80, 0x14, 0x60, 0x2f, 0xe0, 0xd6, - 0x45, 0x08, 0x95, 0x45, 0x09, 0x87, 0x45, 0x60, 0x37, 0x85, 0x1b, 0x01, - 0x80, 0x1b, 0x00, 0xab, 0x1b, 0x00, 0x81, 0x1b, 0x02, 0x80, 0x1b, 0x01, - 0x80, 0x1b, 0x95, 0x34, 0x00, 0x88, 0x34, 0x9f, 0x71, 0x9e, 0x5c, 0x07, - 0x88, 0x5c, 0x2f, 0x92, 0x31, 0x00, 0x81, 0x31, 0x04, 0x84, 0x31, 0x9b, - 0x74, 0x02, 0x80, 0x74, 0x99, 0x49, 0x04, 0x80, 0x49, 0x3f, 0x9f, 0x55, - 0x97, 0x54, 0x03, 0x93, 0x54, 0x01, 0xad, 0x54, 0x83, 0x3d, 0x00, 0x81, - 0x3d, 0x04, 0x87, 0x3d, 0x00, 0x82, 0x3d, 0x00, 0x9c, 0x3d, 0x01, 0x82, - 0x3d, 0x03, 0x89, 0x3d, 0x06, 0x88, 0x3d, 0x06, 0x9f, 0x6b, 0x9f, 0x67, - 0x1f, 0xa6, 0x4e, 0x03, 0x8b, 0x4e, 0x08, 0xb5, 0x06, 0x02, 0x86, 0x06, - 0x95, 0x37, 0x01, 0x87, 0x37, 0x92, 0x36, 0x04, 0x87, 0x36, 0x91, 0x75, - 0x06, 0x83, 0x75, 0x0b, 0x86, 0x75, 0x4f, 0xc8, 0x6c, 0x36, 0xb2, 0x65, - 0x0c, 0xb2, 0x65, 0x06, 0x85, 0x65, 0xa7, 0x2f, 0x07, 0x89, 0x2f, 0x60, - 0xc5, 0x9e, 0x04, 0x60, 0x20, 0xa7, 0x6a, 0x07, 0xa9, 0x7f, 0x60, 0x25, - 0x96, 0x23, 0x08, 0xcd, 0x0e, 0x03, 0x9d, 0x0e, 0x0e, 0x80, 0x0e, 0xc1, - 0x39, 0x0a, 0x80, 0x39, 0x01, 0x98, 0x80, 0x06, 0x89, 0x80, 0x05, 0xb4, - 0x15, 0x00, 0x90, 0x15, 0x08, 0xa6, 0x4b, 0x08, 0xcd, 0x7a, 0x01, 0x8f, - 0x7a, 0x00, 0x93, 0x7e, 0x0a, 0x91, 0x3f, 0x00, 0xab, 0x3f, 0x40, 0x86, - 0x5a, 0x00, 0x80, 0x5a, 0x00, 0x83, 0x5a, 0x00, 0x8e, 0x5a, 0x00, 0x8a, - 0x5a, 0x05, 0xba, 0x40, 0x04, 0x89, 0x40, 0x05, 0x83, 0x28, 0x00, 0x87, - 0x28, 0x01, 0x81, 0x28, 0x01, 0x95, 0x28, 0x00, 0x86, 0x28, 0x00, 0x81, - 0x28, 0x00, 0x84, 0x28, 0x00, 0x80, 0x35, 0x88, 0x28, 0x01, 0x81, 0x28, - 0x01, 0x82, 0x28, 0x01, 0x80, 0x28, 0x05, 0x80, 0x28, 0x04, 0x86, 0x28, - 0x01, 0x86, 0x28, 0x02, 0x84, 0x28, 0x60, 0x2a, 0xd9, 0x5f, 0x00, 0x80, - 0x5f, 0x00, 0x82, 0x5f, 0x1f, 0xc7, 0x92, 0x07, 0x89, 0x92, 0x60, 0x45, - 0xb5, 0x7c, 0x01, 0xa5, 0x7c, 0x21, 0xc4, 0x57, 0x0a, 0x89, 0x57, 0x05, - 0x8c, 0x58, 0x12, 0xb8, 0x8a, 0x06, 0x89, 0x8a, 0x35, 0x9a, 0x02, 0x01, - 0x8e, 0x02, 0x03, 0x8f, 0x02, 0x60, 0x5f, 0xbb, 0x1f, 0x60, 0x03, 0xd2, - 0x96, 0x0b, 0x80, 0x96, 0x60, 0x3f, 0x87, 0x5d, 0x01, 0xad, 0x5d, 0x01, - 0x8a, 0x5d, 0x1a, 0xc7, 0x98, 0x07, 0xd2, 0x81, 0x1c, 0xb8, 0x72, 0x60, - 0xa6, 0x88, 0x0c, 0x00, 0xac, 0x0c, 0x00, 0x8d, 0x0c, 0x09, 0x9c, 0x0c, - 0x02, 0x9f, 0x4f, 0x01, 0x95, 0x4f, 0x00, 0x8d, 0x4f, 0x48, 0x86, 0x50, - 0x00, 0x81, 0x50, 0x00, 0xab, 0x50, 0x02, 0x80, 0x50, 0x00, 0x81, 0x50, - 0x00, 0x88, 0x50, 0x07, 0x89, 0x50, 0x05, 0x85, 0x2b, 0x00, 0x81, 0x2b, - 0x00, 0xa4, 0x2b, 0x00, 0x81, 0x2b, 0x00, 0x85, 0x2b, 0x06, 0x89, 0x2b, - 0x60, 0xd5, 0x98, 0x4a, 0x60, 0x66, 0xb1, 0x8b, 0x0c, 0x80, 0x8b, 0xe3, - 0x39, 0x1a, 0x60, 0x05, 0xe0, 0x0e, 0x1a, 0x00, 0x84, 0x1a, 0x0a, 0xe0, - 0x63, 0x1a, 0x6a, 0x5b, 0xe3, 0xce, 0x21, 0x00, 0x88, 0x21, 0x6f, 0x66, - 0xe1, 0xe6, 0x03, 0x70, 0x11, 0x58, 0xe1, 0xd8, 0x08, 0x06, 0x9e, 0x59, - 0x00, 0x89, 0x59, 0x03, 0x81, 0x59, 0x5f, 0x9d, 0x09, 0x01, 0x85, 0x09, - 0x09, 0xc5, 0x70, 0x09, 0x89, 0x70, 0x00, 0x86, 0x70, 0x00, 0x94, 0x70, - 0x04, 0x92, 0x70, 0x62, 0x4f, 0xda, 0x51, 0x60, 0x04, 0xca, 0x56, 0x03, - 0xb8, 0x56, 0x06, 0x90, 0x56, 0x3f, 0x80, 0x8c, 0x80, 0x61, 0x81, 0x18, - 0x1b, 0xf0, 0x07, 0x97, 0x8c, 0x07, 0xe2, 0x92, 0x8c, 0x70, 0x14, 0xac, - 0x80, 0x3b, 0xe0, 0xbd, 0x33, 0x30, 0x82, 0x33, 0x10, 0x83, 0x3b, 0x07, - 0xe1, 0x2b, 0x61, 0x68, 0xa3, 0xe0, 0x0a, 0x20, 0x04, 0x8c, 0x20, 0x02, - 0x88, 0x20, 0x06, 0x89, 0x20, 0x01, 0x83, 0x20, 0x83, 0x18, 0x70, 0x02, - 0xfb, 0xe0, 0x95, 0x18, 0x09, 0xa6, 0x18, 0x01, 0xbd, 0x18, 0x82, 0x35, - 0x90, 0x18, 0x87, 0x35, 0x81, 0x18, 0x86, 0x35, 0x9d, 0x18, 0x83, 0x35, - 0xba, 0x18, 0x16, 0xc5, 0x29, 0x60, 0x39, 0x93, 0x18, 0x0b, 0xd6, 0x18, - 0x08, 0x98, 0x18, 0x60, 0x26, 0xd4, 0x18, 0x00, 0xc6, 0x18, 0x00, 0x81, - 0x18, 0x01, 0x80, 0x18, 0x01, 0x81, 0x18, 0x01, 0x83, 0x18, 0x00, 0x8b, - 0x18, 0x00, 0x80, 0x18, 0x00, 0x86, 0x18, 0x00, 0xc0, 0x18, 0x00, 0x83, - 0x18, 0x01, 0x87, 0x18, 0x00, 0x86, 0x18, 0x00, 0x9b, 0x18, 0x00, 0x83, - 0x18, 0x00, 0x84, 0x18, 0x00, 0x80, 0x18, 0x02, 0x86, 0x18, 0x00, 0xe0, - 0xf3, 0x18, 0x01, 0xe0, 0xc3, 0x18, 0x01, 0xb1, 0x18, 0xe2, 0x2b, 0x7d, - 0x0e, 0x84, 0x7d, 0x00, 0x8e, 0x7d, 0x64, 0xef, 0x86, 0x26, 0x00, 0x90, - 0x26, 0x01, 0x86, 0x26, 0x00, 0x81, 0x26, 0x00, 0x84, 0x26, 0x60, 0x74, - 0xac, 0x62, 0x02, 0x8d, 0x62, 0x01, 0x89, 0x62, 0x03, 0x81, 0x62, 0x61, - 0x0f, 0xb9, 0x95, 0x04, 0x80, 0x95, 0x64, 0x9f, 0xe0, 0x64, 0x53, 0x01, - 0x8f, 0x53, 0x28, 0xcb, 0x01, 0x03, 0x89, 0x01, 0x03, 0x81, 0x01, 0x62, - 0xb0, 0xc3, 0x18, 0x4b, 0xbc, 0x18, 0x60, 0x61, 0x83, 0x04, 0x00, 0x9a, - 0x04, 0x00, 0x81, 0x04, 0x00, 0x80, 0x04, 0x01, 0x80, 0x04, 0x00, 0x89, - 0x04, 0x00, 0x83, 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, 0x05, 0x80, - 0x04, 0x03, 0x80, 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, 0x00, 0x82, - 0x04, 0x00, 0x81, 0x04, 0x00, 0x80, 0x04, 0x01, 0x80, 0x04, 0x00, 0x80, - 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, 0x00, 0x81, - 0x04, 0x00, 0x80, 0x04, 0x01, 0x83, 0x04, 0x00, 0x86, 0x04, 0x00, 0x83, - 0x04, 0x00, 0x83, 0x04, 0x00, 0x80, 0x04, 0x00, 0x89, 0x04, 0x00, 0x90, - 0x04, 0x04, 0x82, 0x04, 0x00, 0x84, 0x04, 0x00, 0x90, 0x04, 0x33, 0x81, - 0x04, 0x60, 0xad, 0xab, 0x18, 0x03, 0xe0, 0x03, 0x18, 0x0b, 0x8e, 0x18, - 0x01, 0x8e, 0x18, 0x00, 0x8e, 0x18, 0x00, 0xa4, 0x18, 0x09, 0x8c, 0x18, - 0x02, 0xdc, 0x18, 0x02, 0xbc, 0x18, 0x38, 0x99, 0x18, 0x80, 0x33, 0x81, - 0x18, 0x0c, 0xab, 0x18, 0x03, 0x88, 0x18, 0x06, 0x81, 0x18, 0x0d, 0x85, - 0x18, 0x60, 0x39, 0xe3, 0x75, 0x18, 0x09, 0x8c, 0x18, 0x02, 0x8a, 0x18, - 0x04, 0xe0, 0x13, 0x18, 0x0b, 0xd8, 0x18, 0x06, 0x8b, 0x18, 0x13, 0x8b, - 0x18, 0x03, 0xb7, 0x18, 0x07, 0x89, 0x18, 0x05, 0xa7, 0x18, 0x07, 0x9d, - 0x18, 0x51, 0x8b, 0x18, 0x00, 0xe0, 0x04, 0x18, 0x00, 0x83, 0x18, 0x02, - 0xa8, 0x18, 0x01, 0x85, 0x18, 0x02, 0x9c, 0x18, 0x01, 0xe0, 0x26, 0x18, - 0x0b, 0x8d, 0x18, 0x01, 0x83, 0x18, 0x03, 0x82, 0x18, 0x04, 0x82, 0x18, - 0x0c, 0x85, 0x18, 0x65, 0x09, 0xf0, 0x96, 0x76, 0x2d, 0x28, 0xef, 0xd4, - 0x2d, 0x0a, 0xe0, 0x7d, 0x2d, 0x01, 0xf0, 0x06, 0x21, 0x2d, 0x0d, 0xf0, - 0x0c, 0xd0, 0x2d, 0x6b, 0xbe, 0xe1, 0xbd, 0x2d, 0x7a, 0xf5, 0x82, 0x80, - 0x18, 0x1d, 0xdf, 0x18, 0x60, 0x1f, 0xe0, 0x8f, 0x35, -}; - -static const uint8_t unicode_script_ext_table[789] = { - 0x82, 0xc1, 0x00, 0x00, 0x01, 0x29, 0x01, 0x00, 0x00, 0x01, 0x29, 0x1c, - 0x00, 0x0c, 0x01, 0x42, 0x80, 0x92, 0x00, 0x00, 0x02, 0x1c, 0x68, 0x00, - 0x02, 0x1c, 0x26, 0x01, 0x02, 0x1c, 0x42, 0x00, 0x02, 0x1c, 0x26, 0x80, - 0x80, 0x00, 0x00, 0x02, 0x05, 0x25, 0x80, 0x01, 0x00, 0x00, 0x04, 0x04, - 0x2f, 0x84, 0x8e, 0x0d, 0x00, 0x00, 0x04, 0x04, 0x2f, 0x84, 0x8e, 0x00, - 0x03, 0x04, 0x84, 0x8e, 0x01, 0x00, 0x00, 0x04, 0x04, 0x2f, 0x84, 0x8e, - 0x1f, 0x00, 0x00, 0x08, 0x01, 0x04, 0x4d, 0x4e, 0x75, 0x2f, 0x7f, 0x84, - 0x09, 0x00, 0x0a, 0x02, 0x04, 0x84, 0x09, 0x00, 0x09, 0x02, 0x04, 0x8e, - 0x05, 0x00, 0x00, 0x02, 0x04, 0x84, 0x62, 0x00, 0x00, 0x02, 0x04, 0x2f, - 0x81, 0xfb, 0x00, 0x00, 0x0d, 0x0b, 0x1e, 0x28, 0x2a, 0x2c, 0x3a, 0x42, - 0x4c, 0x6d, 0x7a, 0x8b, 0x8d, 0x92, 0x00, 0x0c, 0x0b, 0x1e, 0x28, 0x2a, - 0x2c, 0x3a, 0x42, 0x4c, 0x6d, 0x8b, 0x8d, 0x92, 0x10, 0x00, 0x00, 0x14, - 0x0b, 0x1e, 0x1f, 0x2b, 0x50, 0x28, 0x2a, 0x2c, 0x3a, 0x4b, 0x4c, 0x5d, - 0x6d, 0x40, 0x7e, 0x83, 0x8a, 0x8b, 0x8d, 0x92, 0x00, 0x15, 0x0b, 0x1e, - 0x1f, 0x2b, 0x50, 0x28, 0x2a, 0x2c, 0x3a, 0x44, 0x4b, 0x4c, 0x5d, 0x6d, - 0x40, 0x7e, 0x83, 0x8a, 0x8b, 0x8d, 0x92, 0x09, 0x04, 0x1e, 0x1f, 0x39, - 0x4b, 0x75, 0x00, 0x09, 0x03, 0x0b, 0x15, 0x83, 0x75, 0x00, 0x09, 0x02, - 0x2c, 0x5a, 0x75, 0x00, 0x09, 0x02, 0x2a, 0x3f, 0x80, 0x75, 0x00, 0x0d, - 0x02, 0x28, 0x8b, 0x80, 0x71, 0x00, 0x09, 0x02, 0x3a, 0x5d, 0x82, 0xcf, - 0x00, 0x09, 0x03, 0x15, 0x5b, 0x87, 0x80, 0x30, 0x00, 0x00, 0x02, 0x25, - 0x42, 0x85, 0xb8, 0x00, 0x01, 0x04, 0x11, 0x30, 0x86, 0x85, 0x80, 0x4a, - 0x00, 0x01, 0x02, 0x58, 0x73, 0x00, 0x00, 0x00, 0x02, 0x58, 0x73, 0x84, - 0x49, 0x00, 0x00, 0x04, 0x0b, 0x1e, 0x28, 0x3a, 0x00, 0x01, 0x1e, 0x00, - 0x04, 0x0b, 0x1e, 0x28, 0x3a, 0x00, 0x02, 0x1e, 0x28, 0x00, 0x01, 0x1e, - 0x01, 0x02, 0x0b, 0x1e, 0x00, 0x02, 0x1e, 0x7a, 0x00, 0x02, 0x0b, 0x1e, - 0x00, 0x02, 0x1e, 0x7a, 0x00, 0x06, 0x1e, 0x3a, 0x4c, 0x6d, 0x8b, 0x8d, - 0x00, 0x01, 0x1e, 0x01, 0x02, 0x1e, 0x7a, 0x01, 0x01, 0x1e, 0x00, 0x02, - 0x1e, 0x7a, 0x00, 0x02, 0x0b, 0x1e, 0x06, 0x01, 0x1e, 0x00, 0x02, 0x1e, - 0x5d, 0x00, 0x02, 0x0b, 0x1e, 0x01, 0x01, 0x1e, 0x00, 0x02, 0x0b, 0x1e, - 0x03, 0x01, 0x1e, 0x00, 0x08, 0x0b, 0x1e, 0x28, 0x3a, 0x5d, 0x6d, 0x8d, - 0x92, 0x00, 0x02, 0x1e, 0x28, 0x00, 0x03, 0x1e, 0x28, 0x3a, 0x01, 0x02, - 0x0b, 0x1e, 0x00, 0x01, 0x0b, 0x01, 0x02, 0x1e, 0x28, 0x00, 0x01, 0x5d, - 0x80, 0x44, 0x00, 0x01, 0x01, 0x29, 0x81, 0xec, 0x00, 0x00, 0x02, 0x42, - 0x58, 0x80, 0x3f, 0x00, 0x00, 0x03, 0x1e, 0x28, 0x42, 0x8c, 0xd1, 0x00, - 0x00, 0x02, 0x1c, 0x26, 0x81, 0x3c, 0x00, 0x01, 0x06, 0x0d, 0x2e, 0x2d, - 0x33, 0x3b, 0x97, 0x00, 0x05, 0x0d, 0x2e, 0x2d, 0x33, 0x3b, 0x01, 0x00, - 0x00, 0x01, 0x2d, 0x00, 0x00, 0x09, 0x06, 0x0d, 0x2e, 0x2d, 0x33, 0x3b, - 0x97, 0x00, 0x00, 0x00, 0x05, 0x0d, 0x2e, 0x2d, 0x33, 0x3b, 0x07, 0x06, - 0x0d, 0x2e, 0x2d, 0x33, 0x3b, 0x97, 0x03, 0x05, 0x0d, 0x2e, 0x2d, 0x33, - 0x3b, 0x09, 0x00, 0x03, 0x02, 0x0d, 0x2d, 0x01, 0x00, 0x00, 0x05, 0x0d, - 0x2e, 0x2d, 0x33, 0x3b, 0x04, 0x02, 0x33, 0x3b, 0x00, 0x00, 0x00, 0x05, - 0x0d, 0x2e, 0x2d, 0x33, 0x3b, 0x03, 0x00, 0x01, 0x03, 0x2d, 0x33, 0x3b, - 0x01, 0x01, 0x2d, 0x58, 0x00, 0x03, 0x02, 0x33, 0x3b, 0x02, 0x00, 0x00, - 0x02, 0x33, 0x3b, 0x59, 0x00, 0x00, 0x06, 0x0d, 0x2e, 0x2d, 0x33, 0x3b, - 0x97, 0x00, 0x02, 0x33, 0x3b, 0x80, 0x12, 0x00, 0x0f, 0x01, 0x2d, 0x1f, - 0x00, 0x23, 0x01, 0x2d, 0x3b, 0x00, 0x27, 0x01, 0x2d, 0x37, 0x00, 0x30, - 0x01, 0x2d, 0x0e, 0x00, 0x0b, 0x01, 0x2d, 0x32, 0x00, 0x00, 0x01, 0x2d, - 0x57, 0x00, 0x18, 0x01, 0x2d, 0x09, 0x00, 0x04, 0x01, 0x2d, 0x5f, 0x00, - 0x1e, 0x01, 0x2d, 0xc0, 0x31, 0xef, 0x00, 0x00, 0x02, 0x1c, 0x26, 0x81, - 0x3f, 0x00, 0x02, 0x0e, 0x1e, 0x1f, 0x2a, 0x2c, 0x3f, 0x3a, 0x39, 0x4b, - 0x4c, 0x57, 0x5d, 0x40, 0x8a, 0x92, 0x02, 0x0d, 0x1e, 0x1f, 0x2a, 0x2c, - 0x3f, 0x3a, 0x39, 0x4b, 0x57, 0x5d, 0x40, 0x8a, 0x92, 0x03, 0x0b, 0x1e, - 0x1f, 0x2a, 0x2c, 0x3f, 0x39, 0x4b, 0x57, 0x40, 0x8a, 0x92, 0x80, 0x36, - 0x00, 0x00, 0x02, 0x0b, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x1e, 0x8b, 0x39, - 0x00, 0x00, 0x03, 0x3c, 0x42, 0x5b, 0x80, 0x1f, 0x00, 0x00, 0x02, 0x10, - 0x38, 0xc0, 0x13, 0xa1, 0x00, 0x00, 0x02, 0x04, 0x8e, 0x09, 0x00, 0x00, - 0x02, 0x04, 0x8e, 0x46, 0x00, 0x01, 0x05, 0x0d, 0x2e, 0x2d, 0x33, 0x3b, - 0x80, 0x99, 0x00, 0x04, 0x06, 0x0d, 0x2e, 0x2d, 0x33, 0x3b, 0x97, 0x09, - 0x00, 0x00, 0x02, 0x33, 0x3b, 0x2c, 0x00, 0x01, 0x02, 0x33, 0x3b, 0x80, - 0xdf, 0x00, 0x02, 0x02, 0x1b, 0x46, 0x03, 0x00, 0x2c, 0x03, 0x1b, 0x45, - 0x46, 0x02, 0x00, 0x08, 0x02, 0x1b, 0x46, 0x81, 0x1f, 0x00, 0x1b, 0x02, - 0x04, 0x19, 0x8f, 0x84, 0x00, 0x00, 0x02, 0x28, 0x8b, 0x00, 0x00, 0x00, - 0x02, 0x28, 0x8b, 0x36, 0x00, 0x01, 0x02, 0x28, 0x8b, 0x8c, 0x12, 0x00, - 0x01, 0x02, 0x28, 0x8b, 0x00, 0x00, 0x00, 0x02, 0x28, 0x8b, 0xc0, 0x5c, - 0x4b, 0x00, 0x03, 0x01, 0x20, 0x96, 0x3b, 0x00, 0x11, 0x01, 0x2d, 0x9e, - 0x5d, 0x00, 0x01, 0x01, 0x2d, 0xce, 0xcd, 0x2d, 0x00, -}; - -static const uint8_t unicode_prop_Hyphen_table[28] = { - 0xac, 0x80, 0xfe, 0x80, 0x44, 0xdb, 0x80, 0x52, 0x7a, 0x80, - 0x48, 0x08, 0x81, 0x4e, 0x04, 0x80, 0x42, 0xe2, 0x80, 0x60, - 0xcd, 0x66, 0x80, 0x40, 0xa8, 0x80, 0xd6, 0x80, -}; - -static const uint8_t unicode_prop_Other_Math_table[200] = { - 0xdd, 0x80, 0x43, 0x70, 0x11, 0x80, 0x99, 0x09, 0x81, 0x5c, 0x1f, 0x80, - 0x9a, 0x82, 0x8a, 0x80, 0x9f, 0x83, 0x97, 0x81, 0x8d, 0x81, 0xc0, 0x8c, - 0x18, 0x11, 0x1c, 0x91, 0x03, 0x01, 0x89, 0x00, 0x14, 0x28, 0x11, 0x09, - 0x02, 0x05, 0x13, 0x24, 0xca, 0x21, 0x18, 0x08, 0x08, 0x00, 0x21, 0x0b, - 0x0b, 0x91, 0x09, 0x00, 0x06, 0x00, 0x29, 0x41, 0x21, 0x83, 0x40, 0xa7, - 0x08, 0x80, 0x97, 0x80, 0x90, 0x80, 0x41, 0xbc, 0x81, 0x8b, 0x88, 0x24, - 0x21, 0x09, 0x14, 0x8d, 0x00, 0x01, 0x85, 0x97, 0x81, 0xb8, 0x00, 0x80, - 0x9c, 0x83, 0x88, 0x81, 0x41, 0x55, 0x81, 0x9e, 0x89, 0x41, 0x92, 0x95, - 0xbe, 0x83, 0x9f, 0x81, 0x60, 0xd4, 0x62, 0x00, 0x03, 0x80, 0x40, 0xd2, - 0x00, 0x80, 0x60, 0xd4, 0xc0, 0xd4, 0x80, 0xc6, 0x01, 0x08, 0x09, 0x0b, - 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, - 0x04, 0x00, 0x16, 0x80, 0x41, 0x53, 0x81, 0x98, 0x80, 0x98, 0x80, 0x9e, - 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, - 0x80, 0x98, 0x07, 0x81, 0xb1, 0x55, 0xff, 0x18, 0x9a, 0x01, 0x00, 0x08, - 0x80, 0x89, 0x03, 0x00, 0x00, 0x28, 0x18, 0x00, 0x00, 0x02, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00, - 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, -}; - -static const uint8_t unicode_prop_Other_Alphabetic_table[396] = { - 0x43, 0x44, 0x80, 0x42, 0x69, 0x8d, 0x00, 0x01, 0x01, 0x00, 0xc7, 0x8a, - 0xaf, 0x8c, 0x06, 0x8f, 0x80, 0xe4, 0x33, 0x19, 0x0b, 0x80, 0xa2, 0x80, - 0x9d, 0x8f, 0xe5, 0x8a, 0xe4, 0x0a, 0x88, 0x02, 0x03, 0x40, 0xa6, 0x8b, - 0x16, 0x85, 0x93, 0xb5, 0x09, 0x8e, 0x01, 0x22, 0x89, 0x81, 0x9c, 0x82, - 0xb9, 0x31, 0x09, 0x81, 0x89, 0x80, 0x89, 0x81, 0x9c, 0x82, 0xb9, 0x23, - 0x09, 0x0b, 0x80, 0x9d, 0x0a, 0x80, 0x8a, 0x82, 0xb9, 0x38, 0x10, 0x81, - 0x94, 0x81, 0x95, 0x13, 0x82, 0xb9, 0x31, 0x09, 0x81, 0x88, 0x81, 0x89, - 0x81, 0x9d, 0x80, 0xba, 0x22, 0x10, 0x82, 0x89, 0x80, 0xa7, 0x83, 0xb9, - 0x30, 0x10, 0x17, 0x81, 0x8a, 0x81, 0x9c, 0x82, 0xb9, 0x30, 0x10, 0x17, - 0x81, 0x8a, 0x81, 0x9b, 0x83, 0xb9, 0x30, 0x10, 0x82, 0x89, 0x80, 0x89, - 0x81, 0x9d, 0x81, 0xca, 0x28, 0x00, 0x87, 0x91, 0x81, 0xbc, 0x01, 0x86, - 0x91, 0x80, 0xe2, 0x01, 0x28, 0x81, 0x8f, 0x80, 0x40, 0xa2, 0x90, 0x8a, - 0x8a, 0x80, 0xa3, 0xed, 0x8b, 0x00, 0x0b, 0x96, 0x1b, 0x10, 0x11, 0x32, - 0x83, 0x8c, 0x8b, 0x00, 0x89, 0x83, 0x46, 0x73, 0x81, 0x9d, 0x81, 0x9d, - 0x81, 0x9d, 0x81, 0xc1, 0x92, 0x40, 0xbb, 0x81, 0xa1, 0x80, 0xf5, 0x8b, - 0x83, 0x88, 0x40, 0xdd, 0x84, 0xb8, 0x89, 0x81, 0x93, 0x40, 0x8a, 0x84, - 0xaf, 0x8e, 0xbb, 0x82, 0x9d, 0x88, 0x09, 0xb8, 0x8a, 0xb1, 0x92, 0x41, - 0xaf, 0x8d, 0x46, 0xc0, 0xb3, 0x48, 0xf5, 0x9f, 0x60, 0x78, 0x73, 0x87, - 0xa1, 0x81, 0x41, 0x61, 0x07, 0x80, 0x96, 0x84, 0xd7, 0x81, 0xb1, 0x8f, - 0x00, 0xb8, 0x80, 0xa5, 0x84, 0x9b, 0x8b, 0xac, 0x83, 0xaf, 0x8b, 0xa4, - 0x80, 0xc2, 0x8d, 0x8b, 0x07, 0x81, 0xac, 0x82, 0xb1, 0x00, 0x11, 0x0c, - 0x80, 0xab, 0x24, 0x80, 0x40, 0xec, 0x87, 0x60, 0x4f, 0x32, 0x80, 0x48, - 0x56, 0x84, 0x46, 0x85, 0x10, 0x0c, 0x83, 0x43, 0x13, 0x83, 0x42, 0xd7, - 0x82, 0xb4, 0x8d, 0xbb, 0x80, 0xac, 0x88, 0xc6, 0x82, 0xa3, 0x8b, 0x91, - 0x81, 0xb8, 0x82, 0xaf, 0x8c, 0xeb, 0x88, 0x08, 0x28, 0x40, 0x9f, 0x89, - 0x96, 0x83, 0xb9, 0x31, 0x09, 0x81, 0x89, 0x80, 0x89, 0x81, 0x40, 0xd0, - 0x8c, 0x02, 0xe9, 0x91, 0x40, 0xec, 0x31, 0x86, 0x9c, 0x81, 0xd1, 0x8e, - 0x00, 0xe9, 0x8a, 0xe6, 0x8d, 0x41, 0x00, 0x8c, 0x41, 0x97, 0x31, 0x2b, - 0x80, 0x9b, 0x89, 0xa9, 0x20, 0x83, 0x91, 0x8a, 0xad, 0x8d, 0x41, 0x96, - 0x38, 0x86, 0xd2, 0x95, 0x80, 0x8d, 0xf9, 0x2a, 0x00, 0x08, 0x10, 0x02, - 0x80, 0xc1, 0x20, 0x08, 0x83, 0x41, 0x5b, 0x83, 0x60, 0x50, 0x57, 0x00, - 0xb6, 0x33, 0x60, 0x4d, 0x0a, 0x80, 0x60, 0x23, 0x60, 0x30, 0x90, 0x0e, - 0x01, 0x04, 0x49, 0x1b, 0x80, 0x47, 0xe7, 0x99, 0x85, 0x99, 0x85, 0x99, -}; - -static const uint8_t unicode_prop_Other_Lowercase_table[51] = { - 0x40, 0xa9, 0x80, 0x8e, 0x80, 0x41, 0xf4, 0x88, 0x31, 0x9d, 0x84, - 0xdf, 0x80, 0xb3, 0x80, 0x59, 0xb0, 0xbe, 0x8c, 0x80, 0xa1, 0xa4, - 0x42, 0xb0, 0x80, 0x8c, 0x80, 0x8f, 0x8c, 0x40, 0xd2, 0x8f, 0x43, - 0x4f, 0x99, 0x47, 0x91, 0x81, 0x60, 0x7a, 0x1d, 0x81, 0x40, 0xd1, - 0x80, 0x40, 0x86, 0x81, 0x43, 0x61, 0x83, -}; - -static const uint8_t unicode_prop_Other_Uppercase_table[15] = { - 0x60, 0x21, 0x5f, 0x8f, 0x43, 0x45, 0x99, 0x61, - 0xcc, 0x5f, 0x99, 0x85, 0x99, 0x85, 0x99, -}; - -static const uint8_t unicode_prop_Other_Grapheme_Extend_table[62] = { - 0x49, 0xbd, 0x80, 0x97, 0x80, 0x41, 0x65, 0x80, 0x97, 0x80, 0xe5, - 0x80, 0x97, 0x80, 0x40, 0xe9, 0x80, 0x91, 0x81, 0xe6, 0x80, 0x97, - 0x80, 0xf6, 0x80, 0x8e, 0x80, 0x4d, 0x54, 0x80, 0x44, 0xd5, 0x80, - 0x50, 0x20, 0x81, 0x60, 0xcf, 0x6d, 0x81, 0x53, 0x9d, 0x80, 0x97, - 0x80, 0x41, 0x57, 0x80, 0x8b, 0x80, 0x40, 0xf0, 0x80, 0x60, 0xbb, - 0xb4, 0x07, 0x84, 0x6c, 0x2e, 0xac, 0xdf, -}; - -static const uint8_t unicode_prop_Other_Default_Ignorable_Code_Point_table[32] = - { - 0x43, 0x4e, 0x80, 0x4e, 0x0e, 0x81, 0x46, 0x52, 0x81, 0x48, 0xae, - 0x80, 0x50, 0xfd, 0x80, 0x60, 0xce, 0x3a, 0x80, 0xce, 0x88, 0x6d, - 0x00, 0x06, 0x00, 0x9d, 0xdf, 0xff, 0x40, 0xef, 0x4e, 0x0f, -}; - -static const uint8_t unicode_prop_Other_ID_Start_table[11] = { - 0x58, 0x84, 0x81, 0x48, 0x90, 0x80, 0x94, 0x80, 0x4f, 0x6b, 0x81, -}; - -static const uint8_t unicode_prop_Other_ID_Continue_table[12] = { - 0x40, 0xb6, 0x80, 0x42, 0xce, 0x80, 0x4f, 0xe0, 0x88, 0x46, 0x67, 0x80, -}; - -static const uint8_t unicode_prop_Prepended_Concatenation_Mark_table[17] = { - 0x45, 0xff, 0x85, 0x40, 0xd6, 0x80, 0xb0, 0x80, 0x41, - 0xd1, 0x80, 0x61, 0x07, 0xd9, 0x80, 0x8e, 0x80, -}; - -static const uint8_t unicode_prop_XID_Start1_table[31] = { - 0x43, 0x79, 0x80, 0x4a, 0xb7, 0x80, 0xfe, 0x80, 0x60, 0x21, 0xe6, - 0x81, 0x60, 0xcb, 0xc0, 0x85, 0x41, 0x95, 0x81, 0xf3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0x1e, 0x81, -}; - -static const uint8_t unicode_prop_XID_Continue1_table[23] = { - 0x43, 0x79, 0x80, 0x60, 0x2d, 0x1f, 0x81, 0x60, 0xcb, 0xc0, 0x85, 0x41, - 0x95, 0x81, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -}; - -static const uint8_t unicode_prop_Changes_When_Titlecased1_table[22] = { - 0x41, 0xc3, 0x08, 0x08, 0x81, 0xa4, 0x81, 0x4e, 0xdc, 0xaa, 0x0a, - 0x4e, 0x87, 0x3f, 0x3f, 0x87, 0x8b, 0x80, 0x8e, 0x80, 0xae, 0x80, -}; - -static const uint8_t unicode_prop_Changes_When_Casefolded1_table[33] = { - 0x40, 0xde, 0x80, 0xcf, 0x80, 0x97, 0x80, 0x44, 0x3c, 0x80, 0x59, - 0x11, 0x80, 0x40, 0xe4, 0x3f, 0x3f, 0x87, 0x89, 0x11, 0x05, 0x02, - 0x11, 0x80, 0xa9, 0x11, 0x80, 0x60, 0xdb, 0x07, 0x86, 0x8b, 0x84, -}; - -static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[436] = { - 0x40, 0x9f, 0x06, 0x00, 0x01, 0x00, 0x01, 0x12, 0x10, 0x82, 0x9f, 0x80, - 0xcf, 0x01, 0x80, 0x8b, 0x07, 0x80, 0xfb, 0x01, 0x01, 0x80, 0xa5, 0x80, - 0x40, 0xbb, 0x88, 0x9e, 0x29, 0x84, 0xda, 0x08, 0x81, 0x89, 0x80, 0xa3, - 0x04, 0x02, 0x04, 0x08, 0x80, 0xc9, 0x82, 0x9c, 0x80, 0x41, 0x93, 0x80, - 0x40, 0x93, 0x80, 0xd7, 0x83, 0x42, 0xde, 0x87, 0xfb, 0x08, 0x80, 0xd2, - 0x01, 0x80, 0xa1, 0x11, 0x80, 0x40, 0xfc, 0x81, 0x42, 0xd4, 0x80, 0xfe, - 0x80, 0xa7, 0x81, 0xad, 0x80, 0xb5, 0x80, 0x88, 0x03, 0x03, 0x03, 0x80, - 0x8b, 0x80, 0x88, 0x00, 0x26, 0x80, 0x90, 0x80, 0x88, 0x03, 0x03, 0x03, - 0x80, 0x8b, 0x80, 0x41, 0x41, 0x80, 0xe1, 0x81, 0x46, 0x52, 0x81, 0xd4, - 0x83, 0x45, 0x1c, 0x10, 0x8a, 0x80, 0x91, 0x80, 0x9b, 0x8c, 0x80, 0xa1, - 0xa4, 0x40, 0xd9, 0x80, 0x40, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x3f, 0x3f, 0x87, 0x89, 0x11, 0x04, 0x00, 0x29, 0x04, 0x12, 0x80, - 0x88, 0x12, 0x80, 0x88, 0x11, 0x11, 0x04, 0x08, 0x8f, 0x00, 0x20, 0x8b, - 0x12, 0x2a, 0x08, 0x0b, 0x00, 0x07, 0x82, 0x8c, 0x06, 0x92, 0x81, 0x9a, - 0x80, 0x8c, 0x8a, 0x80, 0xd6, 0x18, 0x10, 0x8a, 0x01, 0x0c, 0x0a, 0x00, - 0x10, 0x11, 0x02, 0x06, 0x05, 0x1c, 0x85, 0x8f, 0x8f, 0x8f, 0x88, 0x80, - 0x40, 0xa1, 0x08, 0x81, 0x40, 0xf7, 0x81, 0x41, 0x34, 0xd5, 0x99, 0x9a, - 0x45, 0x20, 0x80, 0xe6, 0x82, 0xe4, 0x80, 0x41, 0x9e, 0x81, 0x40, 0xf0, - 0x80, 0x41, 0x2e, 0x80, 0xd2, 0x80, 0x8b, 0x40, 0xd5, 0xa9, 0x80, 0xb4, - 0x00, 0x82, 0xdf, 0x09, 0x80, 0xde, 0x80, 0xb0, 0xdd, 0x82, 0x8d, 0xdf, - 0x9e, 0x80, 0xa7, 0x87, 0xae, 0x80, 0x41, 0x7f, 0x60, 0x72, 0x9b, 0x81, - 0x40, 0xd1, 0x80, 0x40, 0x86, 0x81, 0x43, 0x61, 0x83, 0x60, 0x4d, 0x9f, - 0x41, 0x0d, 0x08, 0x00, 0x81, 0x89, 0x00, 0x00, 0x09, 0x82, 0xc3, 0x81, - 0xe9, 0xa5, 0x86, 0x8b, 0x24, 0x00, 0x97, 0x04, 0x00, 0x01, 0x01, 0x80, - 0xeb, 0xa0, 0x41, 0x6a, 0x91, 0xbf, 0x81, 0xb5, 0xa7, 0x8c, 0x82, 0x99, - 0x95, 0x94, 0x81, 0x8b, 0x80, 0x92, 0x03, 0x1a, 0x00, 0x80, 0x40, 0x86, - 0x08, 0x80, 0x9f, 0x99, 0x40, 0x83, 0x15, 0x0d, 0x0d, 0x0a, 0x16, 0x06, - 0x80, 0x88, 0x60, 0xbc, 0xa6, 0x83, 0x54, 0xb9, 0x86, 0x8d, 0x87, 0xbf, - 0x85, 0x42, 0x3e, 0xd4, 0x80, 0xc6, 0x01, 0x08, 0x09, 0x0b, 0x80, 0x8b, - 0x00, 0x06, 0x80, 0xc0, 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, - 0x16, 0x80, 0x41, 0x53, 0x81, 0x41, 0x23, 0x81, 0xb1, 0x55, 0xff, 0x18, - 0x9a, 0x01, 0x00, 0x08, 0x80, 0x89, 0x03, 0x00, 0x00, 0x28, 0x18, 0x00, - 0x00, 0x02, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b, - 0x06, 0x03, 0x03, 0x00, 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, - 0x42, 0x43, 0x8a, 0x84, 0x9e, 0x80, 0x9f, 0x99, 0x82, 0xa2, 0x80, 0xee, - 0x82, 0x8c, 0xab, 0x83, 0x88, 0x31, 0x61, 0x05, 0xad, 0x42, 0x1d, 0x6b, - 0x05, 0xe1, 0x4f, 0xff, -}; - -static const uint8_t unicode_prop_ASCII_Hex_Digit_table[5] = { - 0xaf, 0x89, 0x35, 0x99, 0x85, -}; - -static const uint8_t unicode_prop_Bidi_Control_table[10] = { - 0x46, 0x1b, 0x80, 0x59, 0xf0, 0x81, 0x99, 0x84, 0xb6, 0x83, -}; - -static const uint8_t unicode_prop_Dash_table[50] = { - 0xac, 0x80, 0x45, 0x5b, 0x80, 0xb2, 0x80, 0x4e, 0x40, 0x80, - 0x44, 0x04, 0x80, 0x48, 0x08, 0x85, 0xbc, 0x80, 0xa6, 0x80, - 0x8e, 0x80, 0x41, 0x85, 0x80, 0x4c, 0x03, 0x01, 0x80, 0x9e, - 0x0b, 0x80, 0x41, 0xda, 0x80, 0x92, 0x80, 0xee, 0x80, 0x60, - 0xcd, 0x8f, 0x81, 0xa4, 0x80, 0x89, 0x80, 0x40, 0xa8, 0x80, -}; - -static const uint8_t unicode_prop_Deprecated_table[23] = { - 0x41, 0x48, 0x80, 0x45, 0x28, 0x80, 0x49, 0x02, 0x00, 0x80, 0x48, 0x28, - 0x81, 0x48, 0xc4, 0x85, 0x42, 0xb8, 0x81, 0x6d, 0xdc, 0xd5, 0x80, -}; - -static const uint8_t unicode_prop_Diacritic_table[350] = { - 0xdd, 0x00, 0x80, 0xc6, 0x05, 0x03, 0x01, 0x81, 0x41, 0xf6, 0x40, 0x9e, - 0x07, 0x25, 0x90, 0x0b, 0x80, 0x88, 0x81, 0x40, 0xfc, 0x84, 0x40, 0xd0, - 0x80, 0xb6, 0x90, 0x80, 0x9a, 0x00, 0x01, 0x00, 0x40, 0x85, 0x3b, 0x81, - 0x40, 0x85, 0x0b, 0x0a, 0x82, 0xc2, 0x9a, 0xda, 0x8a, 0xb9, 0x8a, 0xa1, - 0x81, 0x40, 0xc8, 0x9b, 0xbc, 0x80, 0x8f, 0x02, 0x83, 0x9b, 0x80, 0xc9, - 0x80, 0x8f, 0x80, 0xed, 0x80, 0x8f, 0x80, 0xed, 0x80, 0x8f, 0x80, 0xae, - 0x82, 0xbb, 0x80, 0x8f, 0x80, 0xfe, 0x80, 0xfe, 0x80, 0xed, 0x80, 0x8f, - 0x80, 0xec, 0x81, 0x8f, 0x80, 0xfb, 0x80, 0xfb, 0x28, 0x80, 0xea, 0x80, - 0x8c, 0x84, 0xca, 0x81, 0x9a, 0x00, 0x00, 0x03, 0x81, 0xc1, 0x10, 0x81, - 0xbd, 0x80, 0xef, 0x00, 0x81, 0xa7, 0x0b, 0x84, 0x98, 0x30, 0x80, 0x89, - 0x81, 0x42, 0xc0, 0x82, 0x44, 0x68, 0x8a, 0x88, 0x80, 0x41, 0x5a, 0x82, - 0x41, 0x38, 0x39, 0x80, 0xaf, 0x8d, 0xf5, 0x80, 0x8e, 0x80, 0xa5, 0x88, - 0xb5, 0x81, 0x40, 0x89, 0x81, 0xbf, 0x85, 0xd1, 0x98, 0x18, 0x28, 0x0a, - 0xb1, 0xbe, 0xd8, 0x8b, 0xa4, 0x22, 0x82, 0x41, 0xbc, 0x00, 0x82, 0x8a, - 0x82, 0x8c, 0x82, 0x8c, 0x82, 0x8c, 0x81, 0x4c, 0xef, 0x82, 0x41, 0x3c, - 0x80, 0x41, 0xf9, 0x85, 0xe8, 0x83, 0xde, 0x80, 0x60, 0x75, 0x71, 0x80, - 0x8b, 0x08, 0x80, 0x9b, 0x81, 0xd1, 0x81, 0x8d, 0xa1, 0xe5, 0x82, 0xec, - 0x81, 0x40, 0xc9, 0x80, 0x9a, 0x91, 0xb8, 0x83, 0xa3, 0x80, 0xde, 0x80, - 0x8b, 0x80, 0xa3, 0x80, 0x40, 0x94, 0x82, 0xc0, 0x83, 0xb2, 0x80, 0xe3, - 0x84, 0x40, 0x8b, 0x81, 0x60, 0x4f, 0x2f, 0x80, 0x43, 0x00, 0x8f, 0x41, - 0x0d, 0x00, 0x80, 0xae, 0x80, 0xac, 0x81, 0xc2, 0x80, 0x42, 0xfb, 0x80, - 0x48, 0x03, 0x81, 0x42, 0x3a, 0x85, 0x42, 0x1d, 0x8a, 0x41, 0x67, 0x81, - 0xf7, 0x81, 0xbd, 0x80, 0xcb, 0x80, 0x88, 0x82, 0xe7, 0x81, 0x40, 0xb1, - 0x81, 0xd0, 0x80, 0x8f, 0x80, 0x97, 0x32, 0x84, 0x40, 0xcc, 0x02, 0x80, - 0xfa, 0x81, 0x40, 0xfa, 0x81, 0xfd, 0x80, 0xf5, 0x81, 0xf2, 0x80, 0x41, - 0x0c, 0x81, 0x41, 0xa4, 0x80, 0xd2, 0x80, 0x91, 0x80, 0xd0, 0x80, 0x41, - 0xa4, 0x80, 0x41, 0x01, 0x00, 0x81, 0xd0, 0x80, 0x60, 0x4d, 0x57, 0x84, - 0xba, 0x86, 0x44, 0x57, 0x90, 0x60, 0x61, 0xc6, 0x12, 0x2f, 0x39, 0x86, - 0x9d, 0x83, 0x4f, 0x81, 0x86, 0x41, 0xb4, 0x83, 0x45, 0xdf, 0x86, 0xec, - 0x10, 0x82, -}; - -static const uint8_t unicode_prop_Extender_table[86] = { - 0x40, 0xb6, 0x80, 0x42, 0x17, 0x81, 0x43, 0x6d, 0x80, 0x41, 0xb8, - 0x80, 0x46, 0x4a, 0x80, 0xfe, 0x80, 0x49, 0x42, 0x80, 0xb7, 0x80, - 0x42, 0x62, 0x80, 0x41, 0x8d, 0x80, 0xc3, 0x80, 0x53, 0x88, 0x80, - 0xaa, 0x84, 0xe6, 0x81, 0xdc, 0x82, 0x60, 0x6f, 0x15, 0x80, 0x45, - 0xf5, 0x80, 0x43, 0xc1, 0x80, 0x95, 0x80, 0x40, 0x88, 0x80, 0xeb, - 0x80, 0x94, 0x81, 0x60, 0x54, 0x7a, 0x80, 0x53, 0xeb, 0x80, 0x42, - 0x67, 0x82, 0x44, 0xce, 0x80, 0x60, 0x50, 0xa8, 0x81, 0x44, 0x9b, - 0x08, 0x80, 0x60, 0x71, 0x57, 0x81, 0x48, 0x05, 0x82, -}; - -static const uint8_t unicode_prop_Hex_Digit_table[12] = { - 0xaf, 0x89, 0x35, 0x99, 0x85, 0x60, 0xfe, 0xa8, 0x89, 0x35, 0x99, 0x85, -}; - -static const uint8_t unicode_prop_IDS_Binary_Operator_table[5] = { - 0x60, 0x2f, 0xef, 0x09, 0x87, -}; - -static const uint8_t unicode_prop_IDS_Trinary_Operator_table[4] = { - 0x60, - 0x2f, - 0xf1, - 0x81, -}; - -static const uint8_t unicode_prop_Ideographic_table[58] = { - 0x60, 0x30, 0x05, 0x81, 0x98, 0x88, 0x8d, 0x82, 0x43, 0xc4, 0x59, 0xb5, - 0xc9, 0x60, 0x51, 0xef, 0x60, 0x59, 0x0f, 0x41, 0x6d, 0x81, 0xe9, 0x60, - 0x75, 0x25, 0x57, 0xf7, 0x87, 0x42, 0xf2, 0x60, 0x26, 0x7c, 0x41, 0x8b, - 0x60, 0x4d, 0x03, 0x60, 0xa6, 0xd6, 0xa8, 0x50, 0x34, 0x8a, 0x40, 0xdd, - 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x4c, 0x1e, 0x42, 0x1d, -}; - -static const uint8_t unicode_prop_Join_Control_table[4] = { - 0x60, - 0x20, - 0x0b, - 0x81, -}; - -static const uint8_t unicode_prop_Logical_Order_Exception_table[15] = { - 0x4e, 0x3f, 0x84, 0xfa, 0x84, 0x4a, 0xef, 0x11, - 0x80, 0x60, 0x90, 0xf9, 0x09, 0x00, 0x81, -}; - -static const uint8_t unicode_prop_Noncharacter_Code_Point_table[71] = { - 0x60, 0xfd, 0xcf, 0x9f, 0x42, 0x0d, 0x81, 0x60, 0xff, 0xfd, 0x81, 0x60, - 0xff, 0xfd, 0x81, 0x60, 0xff, 0xfd, 0x81, 0x60, 0xff, 0xfd, 0x81, 0x60, - 0xff, 0xfd, 0x81, 0x60, 0xff, 0xfd, 0x81, 0x60, 0xff, 0xfd, 0x81, 0x60, - 0xff, 0xfd, 0x81, 0x60, 0xff, 0xfd, 0x81, 0x60, 0xff, 0xfd, 0x81, 0x60, - 0xff, 0xfd, 0x81, 0x60, 0xff, 0xfd, 0x81, 0x60, 0xff, 0xfd, 0x81, 0x60, - 0xff, 0xfd, 0x81, 0x60, 0xff, 0xfd, 0x81, 0x60, 0xff, 0xfd, 0x81, -}; - -static const uint8_t unicode_prop_Pattern_Syntax_table[58] = { - 0xa0, 0x8e, 0x89, 0x86, 0x99, 0x18, 0x80, 0x99, 0x83, 0xa1, 0x30, 0x00, - 0x08, 0x00, 0x0b, 0x03, 0x02, 0x80, 0x96, 0x80, 0x9e, 0x80, 0x5f, 0x17, - 0x97, 0x87, 0x8e, 0x81, 0x92, 0x80, 0x89, 0x41, 0x30, 0x42, 0xcf, 0x40, - 0x9f, 0x42, 0x75, 0x9d, 0x44, 0x6b, 0x41, 0xff, 0xff, 0x41, 0x80, 0x13, - 0x98, 0x8e, 0x80, 0x60, 0xcd, 0x0c, 0x81, 0x41, 0x04, 0x81, -}; - -static const uint8_t unicode_prop_Pattern_White_Space_table[11] = { - 0x88, 0x84, 0x91, 0x80, 0xe3, 0x80, 0x5f, 0x87, 0x81, 0x97, 0x81, -}; - -static const uint8_t unicode_prop_Quotation_Mark_table[31] = { - 0xa1, 0x03, 0x80, 0x40, 0x82, 0x80, 0x8e, 0x80, 0x5f, 0x5b, 0x87, - 0x98, 0x81, 0x4e, 0x06, 0x80, 0x41, 0xc8, 0x83, 0x8c, 0x82, 0x60, - 0xce, 0x20, 0x83, 0x40, 0xbc, 0x03, 0x80, 0xd9, 0x81, -}; - -static const uint8_t unicode_prop_Radical_table[9] = { - 0x60, 0x2e, 0x7f, 0x99, 0x80, 0xd8, 0x8b, 0x40, 0xd5, -}; - -static const uint8_t unicode_prop_Regional_Indicator_table[4] = { - 0x61, - 0xf1, - 0xe5, - 0x99, -}; - -static const uint8_t unicode_prop_Sentence_Terminal_table[184] = { - 0xa0, 0x80, 0x8b, 0x80, 0x8f, 0x80, 0x45, 0x48, 0x80, 0x40, 0x93, 0x81, - 0x40, 0xb3, 0x80, 0xaa, 0x82, 0x40, 0xf5, 0x80, 0xbc, 0x00, 0x02, 0x81, - 0x41, 0x24, 0x81, 0x46, 0xe3, 0x81, 0x43, 0x15, 0x03, 0x81, 0x43, 0x04, - 0x80, 0x40, 0xc5, 0x81, 0x40, 0xcb, 0x04, 0x80, 0x41, 0x39, 0x81, 0x41, - 0x61, 0x83, 0x40, 0xad, 0x09, 0x81, 0x40, 0xda, 0x81, 0xc0, 0x81, 0x43, - 0xbb, 0x81, 0x88, 0x82, 0x4d, 0xe3, 0x80, 0x8c, 0x80, 0x41, 0xc4, 0x80, - 0x60, 0x74, 0xfb, 0x80, 0x41, 0x0d, 0x81, 0x40, 0xe2, 0x02, 0x80, 0x41, - 0x7d, 0x81, 0xd5, 0x81, 0xde, 0x80, 0x40, 0x97, 0x81, 0x40, 0x92, 0x82, - 0x40, 0x8f, 0x81, 0x40, 0xf8, 0x80, 0x60, 0x52, 0x65, 0x02, 0x81, 0x40, - 0xa8, 0x80, 0x8b, 0x80, 0x8f, 0x80, 0xc0, 0x80, 0x4a, 0xf3, 0x81, 0x44, - 0xfc, 0x84, 0x40, 0xec, 0x81, 0xf4, 0x83, 0xfe, 0x82, 0x40, 0x80, 0x0d, - 0x80, 0x8f, 0x81, 0xd7, 0x08, 0x81, 0xeb, 0x80, 0x41, 0xa0, 0x81, 0x41, - 0x74, 0x0c, 0x8e, 0xe8, 0x81, 0x40, 0xf8, 0x82, 0x43, 0x02, 0x81, 0xd6, - 0x81, 0x41, 0xa3, 0x81, 0x42, 0xb3, 0x81, 0x60, 0x4b, 0x74, 0x81, 0x40, - 0x84, 0x80, 0xc0, 0x81, 0x8a, 0x80, 0x43, 0x52, 0x80, 0x60, 0x4e, 0x05, - 0x80, 0x5d, 0xe7, 0x80, -}; - -static const uint8_t unicode_prop_Soft_Dotted_table[71] = { - 0xe8, 0x81, 0x40, 0xc3, 0x80, 0x41, 0x18, 0x80, 0x9d, 0x80, 0xb3, 0x80, - 0x93, 0x80, 0x41, 0x3f, 0x80, 0xe1, 0x00, 0x80, 0x59, 0x08, 0x80, 0xb2, - 0x80, 0x8c, 0x02, 0x80, 0x40, 0x83, 0x80, 0x40, 0x9c, 0x80, 0x41, 0xa4, - 0x80, 0x40, 0xd5, 0x81, 0x4b, 0x31, 0x80, 0x61, 0xa7, 0xa4, 0x81, 0xb1, - 0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1, - 0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1, 0x81, -}; - -static const uint8_t unicode_prop_Terminal_Punctuation_table[237] = { - 0xa0, 0x80, 0x89, 0x00, 0x80, 0x8a, 0x0a, 0x80, 0x43, 0x3d, 0x07, 0x80, - 0x42, 0x00, 0x80, 0xb8, 0x80, 0xc7, 0x80, 0x8d, 0x01, 0x81, 0x40, 0xb3, - 0x80, 0xaa, 0x8a, 0x00, 0x40, 0xea, 0x81, 0xb5, 0x8e, 0x9e, 0x80, 0x41, - 0x04, 0x81, 0x44, 0xf3, 0x81, 0x40, 0xab, 0x03, 0x85, 0x41, 0x36, 0x81, - 0x43, 0x14, 0x87, 0x43, 0x04, 0x80, 0xfb, 0x82, 0xc6, 0x81, 0x40, 0x9c, - 0x12, 0x80, 0xa6, 0x19, 0x81, 0x41, 0x39, 0x81, 0x41, 0x61, 0x83, 0x40, - 0xad, 0x08, 0x82, 0x40, 0xda, 0x84, 0xbd, 0x81, 0x43, 0xbb, 0x81, 0x88, - 0x82, 0x4d, 0xe3, 0x80, 0x8c, 0x03, 0x80, 0x89, 0x00, 0x81, 0x41, 0xb0, - 0x81, 0x60, 0x74, 0xfa, 0x81, 0x41, 0x0c, 0x82, 0x40, 0xe2, 0x84, 0x41, - 0x7d, 0x81, 0xd5, 0x81, 0xde, 0x80, 0x40, 0x96, 0x82, 0x40, 0x92, 0x82, - 0xfe, 0x80, 0x8f, 0x81, 0x40, 0xf8, 0x80, 0x60, 0x52, 0x63, 0x10, 0x83, - 0x40, 0xa8, 0x80, 0x89, 0x00, 0x80, 0x8a, 0x0a, 0x80, 0xc0, 0x01, 0x80, - 0x44, 0x39, 0x80, 0xaf, 0x80, 0x44, 0x85, 0x80, 0x40, 0xc6, 0x80, 0x41, - 0x35, 0x81, 0x40, 0x97, 0x85, 0xc3, 0x85, 0xd8, 0x83, 0x43, 0xb7, 0x84, - 0x40, 0xec, 0x86, 0xef, 0x83, 0xfe, 0x82, 0x40, 0x80, 0x0d, 0x80, 0x8f, - 0x81, 0xd7, 0x84, 0xeb, 0x80, 0x41, 0xa0, 0x82, 0x8c, 0x80, 0x41, 0x65, - 0x1a, 0x8e, 0xe8, 0x81, 0x40, 0xf8, 0x82, 0x43, 0x02, 0x81, 0xd6, 0x0b, - 0x81, 0x41, 0x9d, 0x82, 0xac, 0x80, 0x42, 0x84, 0x81, 0x45, 0x76, 0x84, - 0x60, 0x45, 0xf8, 0x81, 0x40, 0x84, 0x80, 0xc0, 0x82, 0x89, 0x80, 0x43, - 0x51, 0x81, 0x60, 0x4e, 0x05, 0x80, 0x5d, 0xe6, 0x83, -}; - -static const uint8_t unicode_prop_Unified_Ideograph_table[38] = { - 0x60, 0x33, 0xff, 0x59, 0xb5, 0xc9, 0x60, 0x51, 0xef, 0x60, - 0x5a, 0x1d, 0x08, 0x00, 0x81, 0x89, 0x00, 0x00, 0x09, 0x82, - 0x61, 0x05, 0xd5, 0x60, 0xa6, 0xd6, 0xa8, 0x50, 0x34, 0x8a, - 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, -}; - -static const uint8_t unicode_prop_Variation_Selector_table[12] = { - 0x58, 0x0a, 0x82, 0x60, 0xe5, 0xf1, 0x8f, 0x6d, 0x02, 0xef, 0x40, 0xef, -}; - -static const uint8_t unicode_prop_White_Space_table[22] = { - 0x88, 0x84, 0x91, 0x80, 0xe3, 0x80, 0x99, 0x80, 0x55, 0xde, 0x80, - 0x49, 0x7e, 0x8a, 0x9c, 0x0c, 0x80, 0xae, 0x80, 0x4f, 0x9f, 0x80, -}; - -static const uint8_t unicode_prop_Bidi_Mirrored_table[171] = { - 0xa7, 0x81, 0x91, 0x00, 0x80, 0x9b, 0x00, 0x80, 0x9c, 0x00, 0x80, 0xac, - 0x80, 0x8e, 0x80, 0x4e, 0x7d, 0x83, 0x47, 0x5c, 0x81, 0x49, 0x9b, 0x81, - 0x89, 0x81, 0xb5, 0x81, 0x8d, 0x81, 0x40, 0xb0, 0x80, 0x40, 0xbf, 0x1a, - 0x2a, 0x02, 0x0a, 0x18, 0x18, 0x00, 0x03, 0x88, 0x20, 0x80, 0x91, 0x23, - 0x88, 0x08, 0x00, 0x39, 0x9e, 0x0b, 0x20, 0x88, 0x09, 0x92, 0x21, 0x88, - 0x21, 0x0b, 0x97, 0x81, 0x8f, 0x3b, 0x93, 0x0e, 0x81, 0x44, 0x3c, 0x8d, - 0xc9, 0x01, 0x18, 0x08, 0x14, 0x1c, 0x12, 0x8d, 0x41, 0x92, 0x95, 0x0d, - 0x80, 0x8d, 0x38, 0x35, 0x10, 0x1c, 0x01, 0x0c, 0x18, 0x02, 0x09, 0x89, - 0x29, 0x81, 0x8b, 0x92, 0x03, 0x08, 0x00, 0x08, 0x03, 0x21, 0x2a, 0x97, - 0x81, 0x8a, 0x0b, 0x18, 0x09, 0x0b, 0xaa, 0x0f, 0x80, 0xa7, 0x20, 0x00, - 0x14, 0x22, 0x18, 0x14, 0x00, 0x40, 0xff, 0x80, 0x42, 0x02, 0x1a, 0x08, - 0x81, 0x8d, 0x09, 0x89, 0x41, 0xdd, 0x89, 0x0f, 0x60, 0xce, 0x3c, 0x2c, - 0x81, 0x40, 0xa1, 0x81, 0x91, 0x00, 0x80, 0x9b, 0x00, 0x80, 0x9c, 0x00, - 0x00, 0x08, 0x81, 0x60, 0xd7, 0x76, 0x80, 0xb8, 0x80, 0xb8, 0x80, 0xb8, - 0x80, 0xb8, 0x80, -}; - -static const uint8_t unicode_prop_Emoji_table[236] = { - 0xa2, 0x05, 0x04, 0x89, 0xee, 0x03, 0x80, 0x5f, 0x8c, 0x80, 0x8b, 0x80, - 0x40, 0xd7, 0x80, 0x95, 0x80, 0xd9, 0x85, 0x8e, 0x81, 0x41, 0x6e, 0x81, - 0x8b, 0x80, 0x40, 0xa5, 0x80, 0x98, 0x8a, 0x1a, 0x40, 0xc6, 0x80, 0x40, - 0xe6, 0x81, 0x89, 0x80, 0x88, 0x80, 0xb9, 0x18, 0x84, 0x88, 0x01, 0x01, - 0x09, 0x03, 0x01, 0x00, 0x09, 0x02, 0x02, 0x0f, 0x14, 0x00, 0x04, 0x8b, - 0x8a, 0x09, 0x00, 0x08, 0x80, 0x91, 0x01, 0x81, 0x91, 0x28, 0x00, 0x0a, - 0x0f, 0x0b, 0x81, 0x8a, 0x0c, 0x09, 0x04, 0x08, 0x00, 0x81, 0x93, 0x0c, - 0x28, 0x19, 0x03, 0x01, 0x01, 0x28, 0x01, 0x00, 0x00, 0x05, 0x02, 0x05, - 0x80, 0x89, 0x81, 0x8e, 0x01, 0x03, 0x00, 0x03, 0x10, 0x80, 0x8a, 0x81, - 0xaf, 0x82, 0x88, 0x80, 0x8d, 0x80, 0x8d, 0x80, 0x41, 0x73, 0x81, 0x41, - 0xce, 0x82, 0x92, 0x81, 0xb2, 0x03, 0x80, 0x44, 0xd9, 0x80, 0x8b, 0x80, - 0x42, 0x58, 0x00, 0x80, 0x61, 0xbd, 0x69, 0x80, 0x40, 0xc9, 0x80, 0x40, - 0x9f, 0x81, 0x8b, 0x81, 0x8d, 0x01, 0x89, 0xca, 0x99, 0x01, 0x96, 0x80, - 0x93, 0x01, 0x88, 0x94, 0x81, 0x40, 0xad, 0xa1, 0x81, 0xef, 0x09, 0x02, - 0x81, 0xd2, 0x0a, 0x80, 0x41, 0x06, 0x80, 0xbe, 0x8a, 0x28, 0x97, 0x31, - 0x0f, 0x8b, 0x01, 0x19, 0x03, 0x81, 0x8c, 0x09, 0x07, 0x81, 0x88, 0x04, - 0x82, 0x8b, 0x17, 0x11, 0x00, 0x03, 0x05, 0x02, 0x05, 0xd5, 0xaf, 0xc5, - 0x27, 0x08, 0x89, 0x2a, 0x00, 0x0a, 0x01, 0x87, 0x40, 0xe4, 0x8b, 0x41, - 0x20, 0xad, 0x80, 0x89, 0x80, 0xaa, 0x03, 0x82, 0xa8, 0x0d, 0x82, 0x9c, - 0x81, 0xb2, 0xef, 0x1b, 0x14, 0x82, 0x8c, 0x85, -}; - -static const uint8_t unicode_prop_Emoji_Component_table[28] = { - 0xa2, 0x05, 0x04, 0x89, 0x5f, 0xd2, 0x80, 0x40, 0xd4, 0x80, - 0x60, 0xdd, 0x2a, 0x80, 0x60, 0xf3, 0xd5, 0x99, 0x41, 0xfa, - 0x84, 0x45, 0xaf, 0x83, 0x6c, 0x06, 0x6b, 0xdf, -}; - -static const uint8_t unicode_prop_Emoji_Modifier_table[4] = { - 0x61, - 0xf3, - 0xfa, - 0x84, -}; - -static const uint8_t unicode_prop_Emoji_Modifier_Base_table[63] = { - 0x60, 0x26, 0x1c, 0x80, 0x40, 0xda, 0x80, 0x8f, 0x83, 0x61, 0xcc, - 0x76, 0x80, 0xbb, 0x11, 0x01, 0x82, 0xf4, 0x09, 0x8a, 0x94, 0x92, - 0x10, 0x1a, 0x02, 0x30, 0x00, 0x97, 0x80, 0x40, 0xc8, 0x0b, 0x80, - 0x94, 0x03, 0x81, 0x40, 0xad, 0x12, 0x84, 0xd2, 0x80, 0x8f, 0x82, - 0x88, 0x80, 0x8a, 0x80, 0x42, 0x41, 0x07, 0x3d, 0x80, 0x88, 0x89, - 0x0a, 0xf5, 0x08, 0x08, 0x80, 0x90, 0x10, 0x8c, -}; - -static const uint8_t unicode_prop_Emoji_Presentation_table[143] = { - 0x60, 0x23, 0x19, 0x81, 0x40, 0xcc, 0x1a, 0x01, 0x80, 0x42, 0x08, 0x81, - 0x94, 0x81, 0xb1, 0x8b, 0xaa, 0x80, 0x92, 0x80, 0x8c, 0x07, 0x81, 0x90, - 0x0c, 0x0f, 0x04, 0x80, 0x94, 0x06, 0x08, 0x03, 0x01, 0x06, 0x03, 0x81, - 0x9b, 0x80, 0xa2, 0x00, 0x03, 0x10, 0x80, 0xbc, 0x82, 0x97, 0x80, 0x8d, - 0x80, 0x43, 0x5a, 0x81, 0xb2, 0x03, 0x80, 0x61, 0xc4, 0xad, 0x80, 0x40, - 0xc9, 0x80, 0x40, 0xbd, 0x01, 0x89, 0xca, 0x99, 0x00, 0x97, 0x80, 0x93, - 0x01, 0x20, 0x82, 0x94, 0x81, 0x40, 0xad, 0xa0, 0x8b, 0x88, 0x80, 0xc5, - 0x80, 0x95, 0x8b, 0xaa, 0x1c, 0x8b, 0x90, 0x10, 0x82, 0xc6, 0x00, 0x80, - 0x40, 0xba, 0x81, 0xbe, 0x8c, 0x18, 0x97, 0x91, 0x80, 0x99, 0x81, 0x8c, - 0x80, 0xd5, 0xd4, 0xaf, 0xc5, 0x28, 0x12, 0x08, 0x94, 0x0e, 0x86, 0x40, - 0xe4, 0x8b, 0x41, 0x20, 0xad, 0x80, 0x89, 0x80, 0xaa, 0x03, 0x82, 0xa8, - 0x0d, 0x82, 0x9c, 0x81, 0xb2, 0xef, 0x1b, 0x14, 0x82, 0x8c, 0x85, -}; - -static const uint8_t unicode_prop_Extended_Pictographic_table[152] = { - 0x40, 0xa8, 0x03, 0x80, 0x5f, 0x8c, 0x80, 0x8b, 0x80, 0x40, 0xd7, 0x80, - 0x95, 0x80, 0xd9, 0x85, 0x8e, 0x81, 0x41, 0x6e, 0x81, 0x8b, 0x80, 0xde, - 0x80, 0xc5, 0x80, 0x98, 0x8a, 0x1a, 0x40, 0xc6, 0x80, 0x40, 0xe6, 0x81, - 0x89, 0x80, 0x88, 0x80, 0xb9, 0x18, 0x28, 0x8b, 0x80, 0xf1, 0x89, 0xf5, - 0x81, 0x8a, 0x00, 0x00, 0x28, 0x10, 0x28, 0x89, 0x81, 0x8e, 0x01, 0x03, - 0x00, 0x03, 0x10, 0x80, 0x8a, 0x84, 0xac, 0x82, 0x88, 0x80, 0x8d, 0x80, - 0x8d, 0x80, 0x41, 0x73, 0x81, 0x41, 0xce, 0x82, 0x92, 0x81, 0xb2, 0x03, - 0x80, 0x44, 0xd9, 0x80, 0x8b, 0x80, 0x42, 0x58, 0x00, 0x80, 0x61, 0xbd, - 0x65, 0x40, 0xff, 0x8c, 0x82, 0x9e, 0x80, 0xbb, 0x85, 0x8b, 0x81, 0x8d, - 0x01, 0x89, 0x91, 0xb8, 0x9a, 0x8e, 0x89, 0x80, 0x93, 0x01, 0x88, 0x03, - 0x88, 0x41, 0xb1, 0x84, 0x41, 0x3d, 0x87, 0x41, 0x09, 0xaf, 0xff, 0xf3, - 0x8b, 0xd4, 0xaa, 0x8b, 0x83, 0xb7, 0x87, 0x89, 0x85, 0xa7, 0x87, 0x9d, - 0xd1, 0x8b, 0xae, 0x80, 0x89, 0x80, 0x46, 0xb6, -}; - -static const uint8_t unicode_prop_Default_Ignorable_Code_Point_table[51] = { - 0x40, 0xac, 0x80, 0x42, 0xa0, 0x80, 0x42, 0xcb, 0x80, 0x4b, 0x41, - 0x81, 0x46, 0x52, 0x81, 0xd4, 0x83, 0x47, 0xfb, 0x84, 0x99, 0x84, - 0xb0, 0x8f, 0x50, 0xf3, 0x80, 0x60, 0xcc, 0x9a, 0x8f, 0x40, 0xee, - 0x80, 0x40, 0x9f, 0x80, 0xce, 0x88, 0x60, 0xbc, 0xa6, 0x83, 0x54, - 0xce, 0x87, 0x6c, 0x2e, 0x84, 0x4f, 0xff, -}; - -typedef enum { - UNICODE_PROP_Hyphen, - UNICODE_PROP_Other_Math, - UNICODE_PROP_Other_Alphabetic, - UNICODE_PROP_Other_Lowercase, - UNICODE_PROP_Other_Uppercase, - UNICODE_PROP_Other_Grapheme_Extend, - UNICODE_PROP_Other_Default_Ignorable_Code_Point, - UNICODE_PROP_Other_ID_Start, - UNICODE_PROP_Other_ID_Continue, - UNICODE_PROP_Prepended_Concatenation_Mark, - UNICODE_PROP_ID_Continue1, - UNICODE_PROP_XID_Start1, - UNICODE_PROP_XID_Continue1, - UNICODE_PROP_Changes_When_Titlecased1, - UNICODE_PROP_Changes_When_Casefolded1, - UNICODE_PROP_Changes_When_NFKC_Casefolded1, - UNICODE_PROP_ASCII_Hex_Digit, - UNICODE_PROP_Bidi_Control, - UNICODE_PROP_Dash, - UNICODE_PROP_Deprecated, - UNICODE_PROP_Diacritic, - UNICODE_PROP_Extender, - UNICODE_PROP_Hex_Digit, - UNICODE_PROP_IDS_Binary_Operator, - UNICODE_PROP_IDS_Trinary_Operator, - UNICODE_PROP_Ideographic, - UNICODE_PROP_Join_Control, - UNICODE_PROP_Logical_Order_Exception, - UNICODE_PROP_Noncharacter_Code_Point, - UNICODE_PROP_Pattern_Syntax, - UNICODE_PROP_Pattern_White_Space, - UNICODE_PROP_Quotation_Mark, - UNICODE_PROP_Radical, - UNICODE_PROP_Regional_Indicator, - UNICODE_PROP_Sentence_Terminal, - UNICODE_PROP_Soft_Dotted, - UNICODE_PROP_Terminal_Punctuation, - UNICODE_PROP_Unified_Ideograph, - UNICODE_PROP_Variation_Selector, - UNICODE_PROP_White_Space, - UNICODE_PROP_Bidi_Mirrored, - UNICODE_PROP_Emoji, - UNICODE_PROP_Emoji_Component, - UNICODE_PROP_Emoji_Modifier, - UNICODE_PROP_Emoji_Modifier_Base, - UNICODE_PROP_Emoji_Presentation, - UNICODE_PROP_Extended_Pictographic, - UNICODE_PROP_Default_Ignorable_Code_Point, - UNICODE_PROP_ID_Start, - UNICODE_PROP_Case_Ignorable, - UNICODE_PROP_ASCII, - UNICODE_PROP_Alphabetic, - UNICODE_PROP_Any, - UNICODE_PROP_Assigned, - UNICODE_PROP_Cased, - UNICODE_PROP_Changes_When_Casefolded, - UNICODE_PROP_Changes_When_Casemapped, - UNICODE_PROP_Changes_When_Lowercased, - UNICODE_PROP_Changes_When_NFKC_Casefolded, - UNICODE_PROP_Changes_When_Titlecased, - UNICODE_PROP_Changes_When_Uppercased, - UNICODE_PROP_Grapheme_Base, - UNICODE_PROP_Grapheme_Extend, - UNICODE_PROP_ID_Continue, - UNICODE_PROP_Lowercase, - UNICODE_PROP_Math, - UNICODE_PROP_Uppercase, - UNICODE_PROP_XID_Continue, - UNICODE_PROP_XID_Start, - UNICODE_PROP_Cased1, - UNICODE_PROP_COUNT, -} UnicodePropertyEnum; - -static const char unicode_prop_name_table[] = - "ASCII_Hex_Digit,AHex" - "\0" - "Bidi_Control,Bidi_C" - "\0" - "Dash" - "\0" - "Deprecated,Dep" - "\0" - "Diacritic,Dia" - "\0" - "Extender,Ext" - "\0" - "Hex_Digit,Hex" - "\0" - "IDS_Binary_Operator,IDSB" - "\0" - "IDS_Trinary_Operator,IDST" - "\0" - "Ideographic,Ideo" - "\0" - "Join_Control,Join_C" - "\0" - "Logical_Order_Exception,LOE" - "\0" - "Noncharacter_Code_Point,NChar" - "\0" - "Pattern_Syntax,Pat_Syn" - "\0" - "Pattern_White_Space,Pat_WS" - "\0" - "Quotation_Mark,QMark" - "\0" - "Radical" - "\0" - "Regional_Indicator,RI" - "\0" - "Sentence_Terminal,STerm" - "\0" - "Soft_Dotted,SD" - "\0" - "Terminal_Punctuation,Term" - "\0" - "Unified_Ideograph,UIdeo" - "\0" - "Variation_Selector,VS" - "\0" - "White_Space,space" - "\0" - "Bidi_Mirrored,Bidi_M" - "\0" - "Emoji" - "\0" - "Emoji_Component" - "\0" - "Emoji_Modifier" - "\0" - "Emoji_Modifier_Base" - "\0" - "Emoji_Presentation" - "\0" - "Extended_Pictographic" - "\0" - "Default_Ignorable_Code_Point,DI" - "\0" - "ID_Start,IDS" - "\0" - "Case_Ignorable,CI" - "\0" - "ASCII" - "\0" - "Alphabetic,Alpha" - "\0" - "Any" - "\0" - "Assigned" - "\0" - "Cased" - "\0" - "Changes_When_Casefolded,CWCF" - "\0" - "Changes_When_Casemapped,CWCM" - "\0" - "Changes_When_Lowercased,CWL" - "\0" - "Changes_When_NFKC_Casefolded,CWKCF" - "\0" - "Changes_When_Titlecased,CWT" - "\0" - "Changes_When_Uppercased,CWU" - "\0" - "Grapheme_Base,Gr_Base" - "\0" - "Grapheme_Extend,Gr_Ext" - "\0" - "ID_Continue,IDC" - "\0" - "Lowercase,Lower" - "\0" - "Math" - "\0" - "Uppercase,Upper" - "\0" - "XID_Continue,XIDC" - "\0" - "XID_Start,XIDS" - "\0"; - -static const uint8_t* const unicode_prop_table[] = { - unicode_prop_Hyphen_table, - unicode_prop_Other_Math_table, - unicode_prop_Other_Alphabetic_table, - unicode_prop_Other_Lowercase_table, - unicode_prop_Other_Uppercase_table, - unicode_prop_Other_Grapheme_Extend_table, - unicode_prop_Other_Default_Ignorable_Code_Point_table, - unicode_prop_Other_ID_Start_table, - unicode_prop_Other_ID_Continue_table, - unicode_prop_Prepended_Concatenation_Mark_table, - unicode_prop_ID_Continue1_table, - unicode_prop_XID_Start1_table, - unicode_prop_XID_Continue1_table, - unicode_prop_Changes_When_Titlecased1_table, - unicode_prop_Changes_When_Casefolded1_table, - unicode_prop_Changes_When_NFKC_Casefolded1_table, - unicode_prop_ASCII_Hex_Digit_table, - unicode_prop_Bidi_Control_table, - unicode_prop_Dash_table, - unicode_prop_Deprecated_table, - unicode_prop_Diacritic_table, - unicode_prop_Extender_table, - unicode_prop_Hex_Digit_table, - unicode_prop_IDS_Binary_Operator_table, - unicode_prop_IDS_Trinary_Operator_table, - unicode_prop_Ideographic_table, - unicode_prop_Join_Control_table, - unicode_prop_Logical_Order_Exception_table, - unicode_prop_Noncharacter_Code_Point_table, - unicode_prop_Pattern_Syntax_table, - unicode_prop_Pattern_White_Space_table, - unicode_prop_Quotation_Mark_table, - unicode_prop_Radical_table, - unicode_prop_Regional_Indicator_table, - unicode_prop_Sentence_Terminal_table, - unicode_prop_Soft_Dotted_table, - unicode_prop_Terminal_Punctuation_table, - unicode_prop_Unified_Ideograph_table, - unicode_prop_Variation_Selector_table, - unicode_prop_White_Space_table, - unicode_prop_Bidi_Mirrored_table, - unicode_prop_Emoji_table, - unicode_prop_Emoji_Component_table, - unicode_prop_Emoji_Modifier_table, - unicode_prop_Emoji_Modifier_Base_table, - unicode_prop_Emoji_Presentation_table, - unicode_prop_Extended_Pictographic_table, - unicode_prop_Default_Ignorable_Code_Point_table, - unicode_prop_ID_Start_table, - unicode_prop_Case_Ignorable_table, -}; - -static const uint16_t unicode_prop_len_table[] = { - countof(unicode_prop_Hyphen_table), - countof(unicode_prop_Other_Math_table), - countof(unicode_prop_Other_Alphabetic_table), - countof(unicode_prop_Other_Lowercase_table), - countof(unicode_prop_Other_Uppercase_table), - countof(unicode_prop_Other_Grapheme_Extend_table), - countof(unicode_prop_Other_Default_Ignorable_Code_Point_table), - countof(unicode_prop_Other_ID_Start_table), - countof(unicode_prop_Other_ID_Continue_table), - countof(unicode_prop_Prepended_Concatenation_Mark_table), - countof(unicode_prop_ID_Continue1_table), - countof(unicode_prop_XID_Start1_table), - countof(unicode_prop_XID_Continue1_table), - countof(unicode_prop_Changes_When_Titlecased1_table), - countof(unicode_prop_Changes_When_Casefolded1_table), - countof(unicode_prop_Changes_When_NFKC_Casefolded1_table), - countof(unicode_prop_ASCII_Hex_Digit_table), - countof(unicode_prop_Bidi_Control_table), - countof(unicode_prop_Dash_table), - countof(unicode_prop_Deprecated_table), - countof(unicode_prop_Diacritic_table), - countof(unicode_prop_Extender_table), - countof(unicode_prop_Hex_Digit_table), - countof(unicode_prop_IDS_Binary_Operator_table), - countof(unicode_prop_IDS_Trinary_Operator_table), - countof(unicode_prop_Ideographic_table), - countof(unicode_prop_Join_Control_table), - countof(unicode_prop_Logical_Order_Exception_table), - countof(unicode_prop_Noncharacter_Code_Point_table), - countof(unicode_prop_Pattern_Syntax_table), - countof(unicode_prop_Pattern_White_Space_table), - countof(unicode_prop_Quotation_Mark_table), - countof(unicode_prop_Radical_table), - countof(unicode_prop_Regional_Indicator_table), - countof(unicode_prop_Sentence_Terminal_table), - countof(unicode_prop_Soft_Dotted_table), - countof(unicode_prop_Terminal_Punctuation_table), - countof(unicode_prop_Unified_Ideograph_table), - countof(unicode_prop_Variation_Selector_table), - countof(unicode_prop_White_Space_table), - countof(unicode_prop_Bidi_Mirrored_table), - countof(unicode_prop_Emoji_table), - countof(unicode_prop_Emoji_Component_table), - countof(unicode_prop_Emoji_Modifier_table), - countof(unicode_prop_Emoji_Modifier_Base_table), - countof(unicode_prop_Emoji_Presentation_table), - countof(unicode_prop_Extended_Pictographic_table), - countof(unicode_prop_Default_Ignorable_Code_Point_table), - countof(unicode_prop_ID_Start_table), - countof(unicode_prop_Case_Ignorable_table), -}; - -#endif /* CONFIG_ALL_UNICODE */ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/primjs_monitor.h b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/primjs_monitor.h deleted file mode 100644 index d26cdc79..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/primjs_monitor.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -#ifndef SRC_INTERPRETER_QUICKJS_INCLUDE_PRIMJS_MONITOR_H_ -#define SRC_INTERPRETER_QUICKJS_INCLUDE_PRIMJS_MONITOR_H_ - -#define MODULE_PRIMJS "primjs" -#define MODULE_QUICK "quickjs" - -#define MODULE_NAPI "napi" -#define DEFAULT_BIZ_NAME "unknown_biz_name" - -void MonitorEvent(const char* moduleName, const char* bizName, - const char* dataKey, const char* dataValue); -bool GetSettingsWithKey(const char* key); -int GetSettingsFlag(); - -#endif // SRC_INTERPRETER_QUICKJS_INCLUDE_PRIMJS_MONITOR_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs-atom.h b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs-atom.h deleted file mode 100644 index c6c6367d..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs-atom.h +++ /dev/null @@ -1,286 +0,0 @@ -/* - * QuickJS atom definitions - * - * Copyright (c) 2017-2018 Fabrice Bellard - * Copyright (c) 2017-2018 Charlie Gordon - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -#ifdef DEF - -/* Note: first atoms are considered as keywords in the parser */ -DEF(null, "null") /* must be first */ -DEF(false, "false") -DEF(true, "true") -DEF(if, "if") -DEF(else, "else") -DEF(return, "return") -DEF(var, "var") -DEF(this, "this") -DEF(delete, "delete") -DEF(void, "void") -DEF(typeof, "typeof") -DEF(new, "new") -DEF(in, "in") -DEF(instanceof, "instanceof") -DEF(do, "do") -DEF(while, "while") -DEF(for, "for") -DEF(break, "break") -DEF(continue, "continue") -DEF(switch, "switch") -DEF(case, "case") -DEF(default, "default") -DEF(throw, "throw") -DEF(try, "try") -DEF(catch, "catch") -DEF(finally, "finally") -DEF(function, "function") -DEF(debugger, "debugger") -DEF(with, "with") -/* FutureReservedWord */ -DEF(class, "class") -DEF(const, "const") -DEF(enum, "enum") -DEF(export, "export") -DEF(extends, "extends") -DEF(import, "import") -DEF(super, "super") -/* FutureReservedWords when parsing strict mode code */ -DEF(implements, "implements") -DEF(interface, "interface") -DEF(let, "let") -DEF(package, "package") -DEF(private, "private") -DEF(protected, "protected") -DEF(public, "public") -DEF(static, "static") -DEF(yield, "yield") -DEF(await, "await") - -/* empty string */ -DEF(empty_string, "") -/* identifiers */ -DEF(length, "length") -DEF(fileName, "fileName") -DEF(lineNumber, "lineNumber") -DEF(message, "message") -DEF(stack, "stack") -DEF(name, "name") -DEF(toString, "toString") -DEF(toLocaleString, "toLocaleString") -DEF(valueOf, "valueOf") -DEF(eval, "eval") -DEF(prototype, "prototype") -DEF(constructor, "constructor") -DEF(configurable, "configurable") -DEF(writable, "writable") -DEF(enumerable, "enumerable") -DEF(value, "value") -DEF(get, "get") -DEF(set, "set") -DEF(of, "of") -DEF(__proto__, "__proto__") -DEF(undefined, "undefined") -DEF(number, "number") -DEF(boolean, "boolean") -DEF(string, "string") -DEF(object, "object") -DEF(symbol, "symbol") -DEF(integer, "integer") -DEF(unknown, "unknown") -DEF(arguments, "arguments") -DEF(callee, "callee") -DEF(caller, "caller") -DEF(_eval_, "") -DEF(_ret_, "") -DEF(_var_, "") -DEF(_with_, "") -DEF(lastIndex, "lastIndex") -DEF(target, "target") -DEF(index, "index") -DEF(input, "input") -DEF(defineProperties, "defineProperties") -DEF(apply, "apply") -DEF(join, "join") -DEF(concat, "concat") -DEF(split, "split") -DEF(construct, "construct") -DEF(getPrototypeOf, "getPrototypeOf") -DEF(setPrototypeOf, "setPrototypeOf") -DEF(isExtensible, "isExtensible") -DEF(preventExtensions, "preventExtensions") -DEF(has, "has") -DEF(deleteProperty, "deleteProperty") -DEF(defineProperty, "defineProperty") -DEF(getOwnPropertyDescriptor, "getOwnPropertyDescriptor") -DEF(ownKeys, "ownKeys") -DEF(add, "add") -DEF(done, "done") -DEF(next, "next") -DEF(values, "values") -DEF(source, "source") -DEF(flags, "flags") -DEF(global, "global") -DEF(unicode, "unicode") -DEF(raw, "raw") -DEF(new_target, "new.target") -DEF(this_active_func, "this.active_func") -DEF(home_object, "") -DEF(computed_field, "") -DEF(static_computed_field, - "") /* must come after computed_fields */ -DEF(class_fields_init, "") -DEF(brand, "") -DEF(hash_constructor, "#constructor") -DEF(as, "as") -DEF(from, "from") -DEF(_default_, "*default*") -DEF(_star_, "*") -DEF(Module, "Module") -DEF(then, "then") -DEF(resolve, "resolve") -DEF(reject, "reject") -DEF(promise, "promise") -DEF(proxy, "proxy") -DEF(revoke, "revoke") -DEF(async, "async") -DEF(exec, "exec") -DEF(groups, "groups") -DEF(status, "status") -DEF(reason, "reason") -#ifdef CONFIG_BIGNUM -DEF(bigint, "bigint") -DEF(bigfloat, "bigfloat") -#endif -#ifdef CONFIG_ATOMICS -DEF(not_equal, "not-equal") -DEF(timed_out, "timed-out") -DEF(ok, "ok") -#endif -DEF(toJSON, "toJSON") -/* class names */ -DEF(Object, "Object") -DEF(Array, "Array") -DEF(Error, "Error") -DEF(Number, "Number") -DEF(String, "String") -DEF(Boolean, "Boolean") -DEF(Symbol, "Symbol") -DEF(Arguments, "Arguments") -DEF(Math, "Math") -DEF(JSON, "JSON") -DEF(Date, "Date") -DEF(Function, "Function") -DEF(GeneratorFunction, "GeneratorFunction") -DEF(ForInIterator, "ForInIterator") -DEF(RegExp, "RegExp") -DEF(ArrayBuffer, "ArrayBuffer") -DEF(SharedArrayBuffer, "SharedArrayBuffer") -/* must keep same order as class IDs for typed arrays */ -DEF(Uint8ClampedArray, "Uint8ClampedArray") -DEF(Int8Array, "Int8Array") -DEF(Uint8Array, "Uint8Array") -DEF(Int16Array, "Int16Array") -DEF(Uint16Array, "Uint16Array") -DEF(Int32Array, "Int32Array") -DEF(Uint32Array, "Uint32Array") -#ifdef CONFIG_BIGNUM -DEF(BigInt64Array, "BigInt64Array") -DEF(BigUint64Array, "BigUint64Array") -#endif -DEF(Float32Array, "Float32Array") -DEF(Float64Array, "Float64Array") -DEF(DataView, "DataView") -#ifdef CONFIG_BIGNUM -DEF(BigInt, "BigInt") -DEF(BigFloat, "BigFloat") -DEF(BigFloatEnv, "BigFloatEnv") -#endif -DEF(Map, "Map") -DEF(Set, "Set") /* Map + 1 */ -DEF(WeakMap, "WeakMap") /* Map + 2 */ -DEF(WeakSet, "WeakSet") /* Map + 3 */ -DEF(Map_Iterator, "Map Iterator") -DEF(Set_Iterator, "Set Iterator") -DEF(Array_Iterator, "Array Iterator") -DEF(String_Iterator, "String Iterator") -DEF(RegExp_String_Iterator, "RegExp String Iterator") -DEF(Generator, "Generator") -DEF(Proxy, "Proxy") -DEF(Promise, "Promise") -DEF(PromiseResolveFunction, "PromiseResolveFunction") -DEF(PromiseRejectFunction, "PromiseRejectFunction") -DEF(AsyncFunction, "AsyncFunction") -DEF(AsyncFunctionResolve, "AsyncFunctionResolve") -DEF(AsyncFunctionReject, "AsyncFunctionReject") -DEF(AsyncGeneratorFunction, "AsyncGeneratorFunction") -DEF(AsyncGenerator, "AsyncGenerator") -DEF(EvalError, "EvalError") -DEF(RangeError, "RangeError") -DEF(ReferenceError, "ReferenceError") -DEF(SyntaxError, "SyntaxError") -DEF(TypeError, "TypeError") -DEF(URIError, "URIError") -DEF(InternalError, "InternalError") -/* private symbols */ -DEF(Private_brand, "") -/* symbols */ -DEF(Symbol_toPrimitive, "Symbol.toPrimitive") -DEF(Symbol_iterator, "Symbol.iterator") -DEF(Symbol_match, "Symbol.match") -DEF(Symbol_matchAll, "Symbol.matchAll") -DEF(Symbol_replace, "Symbol.replace") -DEF(Symbol_search, "Symbol.search") -DEF(Symbol_split, "Symbol.split") -DEF(Symbol_toStringTag, "Symbol.toStringTag") -DEF(Symbol_isConcatSpreadable, "Symbol.isConcatSpreadable") -DEF(Symbol_hasInstance, "Symbol.hasInstance") -DEF(Symbol_species, "Symbol.species") -DEF(Symbol_unscopables, "Symbol.unscopables") -DEF(Symbol_asyncIterator, "Symbol.asyncIterator") -#ifdef CONFIG_BIGNUM -DEF(Symbol_operatorOrder, "Symbol.operatorOrder") -DEF(Symbol_operatorAdd, "Symbol.operatorAdd") -DEF(Symbol_operatorSub, "Symbol.operatorSub") -DEF(Symbol_operatorMul, "Symbol.operatorMul") -DEF(Symbol_operatorDiv, "Symbol.operatorDiv") -DEF(Symbol_operatorMod, "Symbol.operatorMod") -DEF(Symbol_operatorPow, "Symbol.operatorPow") -DEF(Symbol_operatorShl, "Symbol.operatorShl") -DEF(Symbol_operatorShr, "Symbol.operatorShr") -DEF(Symbol_operatorAnd, "Symbol.operatorAnd") -DEF(Symbol_operatorOr, "Symbol.operatorOr") -DEF(Symbol_operatorXor, "Symbol.operatorXor") -DEF(Symbol_operatorCmpLT, "Symbol.operatorCmpLT") -DEF(Symbol_operatorCmpLE, "Symbol.operatorCmpLE") -DEF(Symbol_operatorCmpEQ, "Symbol.operatorCmpEQ") -DEF(Symbol_operatorPlus, "Symbol.operatorPlus") -DEF(Symbol_operatorNeg, "Symbol.operatorNeg") -DEF(Symbol_operatorNot, "Symbol.operatorNot") -DEF(Symbol_operatorInc, "Symbol.operatorInc") -DEF(Symbol_operatorDec, "Symbol.operatorDec") -DEF(Symbol_operatorMathMod, "Symbol.operatorMathMod") -#endif - -#endif /* DEF */ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs-inner.h b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs-inner.h deleted file mode 100644 index c3dd6e48..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs-inner.h +++ /dev/null @@ -1,3204 +0,0 @@ -/* - * QuickJS Javascript Engine - * - * Copyright (c) 2017-2019 Fabrice Bellard - * Copyright (c) 2017-2019 Charlie Gordon - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. -#ifndef SRC_INTERPRETER_QUICKJS_INCLUDE_QUICKJS_INNER_H_ -#define SRC_INTERPRETER_QUICKJS_INCLUDE_QUICKJS_INNER_H_ - -#include "quickjs/include/base_export.h" -#ifdef __cplusplus -extern "C" { -#endif - -#include "quickjs/include/cutils.h" -#include "quickjs/include/list.h" -#include "quickjs/include/quickjs.h" - -#ifdef CONFIG_BIGNUM -#include "quickjs/include/libbf.h" -#endif - -#ifdef __cplusplus -} -#endif - -#include "gc/allocator.h" -#include "quickjs/include/primjs_monitor.h" -#include "quickjs/include/quickjs_queue.h" - -#ifndef _WIN32 -#include - -#include -#endif -#include - -#ifdef ENABLE_GC_DEBUG_TOOLS -#include -#ifndef DCHECK -#define DCHECK(condition) \ - if (!(condition)) abort(); -#endif -#else -#ifndef DCHECK -#define DCHECK(condition) ((void)0) -#endif -#endif - -typedef int BOOL; -#define SYSCALL_CHECK(condition) \ - if ((condition) == -1) { \ - /*abort()*/ \ - } - -#ifdef ENABLE_QUICKJS_DEBUGGER -#include "inspector/debugger_inner.h" -#endif - -#include "gc/qjsvaluevalue-space.h" - -#if defined(CONFIG_BIGNUM) and defined(ENABLE_LEPUSNG) -#error bignum and lepusng are now conflict! -#endif -#if defined(QJS_UNITTEST) || defined(__WASI_SDK__) -#define QJS_STATIC -#else -#define QJS_STATIC static -#endif - -#define OPTIMIZE 1 -#define SHORT_OPCODES 1 - -#if !defined(__aarch64__) -#if defined(ENABLE_PRIMJS_SNAPSHOT) -#undef ENABLE_PRIMJS_SNAPSHOT -#endif -#if defined(ENABLE_COMPATIBLE_MM) -#undef ENABLE_COMPATIBLE_MM -#endif -#endif - -#ifdef ENABLE_COMPATIBLE_MM -#undef DUMP_LEAKS -#undef DEBUG_MEMORY -#endif - -#define KB (1024) -#define MB (1024 * KB) -#define MS (1000) - -#define BUF_LEN (100) - -#ifdef ENABLE_GC_DEBUG_TOOLS -size_t get_cur_cnt(void *runtime, void *ptr); -size_t get_del_cnt(void *runtime, void *ptr); -#endif - -#define __exception __attribute__((warn_unused_result)) - -enum JS_CLASS_ID { - /* classid tag */ /* union usage | properties */ - JS_CLASS_OBJECT = 1, /* must be first */ - JS_CLASS_ARRAY, /* u.array | length */ - JS_CLASS_ERROR, - JS_CLASS_NUMBER, /* u.object_data */ - JS_CLASS_STRING, /* u.object_data */ - JS_CLASS_BOOLEAN, /* u.object_data */ - JS_CLASS_SYMBOL, /* u.object_data */ - JS_CLASS_ARGUMENTS, /* u.array | length */ - JS_CLASS_MAPPED_ARGUMENTS, /* | length */ - JS_CLASS_DATE, /* u.object_data */ - JS_CLASS_MODULE_NS, - JS_CLASS_C_FUNCTION, /* u.cfunc */ - JS_CLASS_BYTECODE_FUNCTION, /* u.func */ - JS_CLASS_BOUND_FUNCTION, /* u.bound_function */ - JS_CLASS_C_FUNCTION_DATA, /* u.c_function_data_record */ - JS_CLASS_GENERATOR_FUNCTION, /* u.func */ - JS_CLASS_FOR_IN_ITERATOR, /* u.for_in_iterator */ - JS_CLASS_REGEXP, /* u.regexp */ - JS_CLASS_ARRAY_BUFFER, /* u.array_buffer */ - JS_CLASS_SHARED_ARRAY_BUFFER, /* u.array_buffer */ - JS_CLASS_UINT8C_ARRAY, /* u.array (typed_array) */ - JS_CLASS_INT8_ARRAY, /* u.array (typed_array) */ - JS_CLASS_UINT8_ARRAY, /* u.array (typed_array) */ - JS_CLASS_INT16_ARRAY, /* u.array (typed_array) */ - JS_CLASS_UINT16_ARRAY, /* u.array (typed_array) */ - JS_CLASS_INT32_ARRAY, /* u.array (typed_array) */ - JS_CLASS_UINT32_ARRAY, /* u.array (typed_array) */ -#ifdef CONFIG_BIGNUM - JS_CLASS_BIG_INT64_ARRAY, /* u.array (typed_array) */ - JS_CLASS_BIG_UINT64_ARRAY, /* u.array (typed_array) */ -#endif - JS_CLASS_FLOAT32_ARRAY, /* u.array (typed_array) */ - JS_CLASS_FLOAT64_ARRAY, /* u.array (typed_array) */ - JS_CLASS_DATAVIEW, /* u.typed_array */ -#ifdef CONFIG_BIGNUM - JS_CLASS_BIG_INT, /* u.object_data */ - JS_CLASS_BIG_FLOAT, /* u.object_data */ - JS_CLASS_FLOAT_ENV, /* u.float_env */ -#endif - JS_CLASS_MAP, /* u.map_state */ - JS_CLASS_SET, /* u.map_state */ - JS_CLASS_WEAKMAP, /* u.map_state */ - JS_CLASS_WEAKSET, /* u.map_state */ - JS_CLASS_MAP_ITERATOR, /* u.map_iterator_data */ - JS_CLASS_SET_ITERATOR, /* u.map_iterator_data */ - JS_CLASS_ARRAY_ITERATOR, /* u.array_iterator_data */ - JS_CLASS_STRING_ITERATOR, /* u.array_iterator_data */ - JS_CLASS_REGEXP_STRING_ITERATOR, /* u.regexp_string_iterator_data */ - JS_CLASS_GENERATOR, /* u.generator_data */ - JS_CLASS_PROXY, /* u.proxy_data */ - JS_CLASS_PROMISE, /* u.promise_data */ - JS_CLASS_PROMISE_RESOLVE_FUNCTION, /* u.promise_function_data */ - JS_CLASS_PROMISE_REJECT_FUNCTION, /* u.promise_function_data */ - JS_CLASS_ASYNC_FUNCTION, /* u.func */ - JS_CLASS_ASYNC_FUNCTION_RESOLVE, /* u.async_function_data */ - JS_CLASS_ASYNC_FUNCTION_REJECT, /* u.async_function_data */ - JS_CLASS_ASYNC_FROM_SYNC_ITERATOR, /* u.async_from_sync_iterator_data */ - JS_CLASS_ASYNC_GENERATOR_FUNCTION, /* u.func */ - JS_CLASS_ASYNC_GENERATOR, /* u.async_generator_data */ - JS_CLASS_WeakRef, - JS_CLASS_FinalizationRegistry, - - JS_CLASS_INIT_COUNT, /* last entry for predefined classes */ -}; - -typedef enum JSErrorEnum { - JS_EVAL_ERROR, - JS_RANGE_ERROR, - JS_REFERENCE_ERROR, - JS_SYNTAX_ERROR, - JS_TYPE_ERROR, - JS_URI_ERROR, - JS_INTERNAL_ERROR, - JS_AGGREGATE_ERROR, - - JS_NATIVE_ERROR_COUNT, /* number of different NativeError objects */ -} JSErrorEnum; - -#define BUILD_ASYNC_STACK - -typedef struct JSShape JSShape; -typedef struct JSString JSString; -typedef struct JSString JSAtomStruct; - -typedef struct JSLepusType { - int32_t array_typeid_; - int32_t table_typeid_; - int32_t refcounted_typeid_; - LEPUSClassID refcounted_cid_; -} JSLepusType; - -typedef struct PrimjsCallbacks { - void (*print_by_alog)(char *msg); - int32_t (*js_has_property)(LEPUSContext *, LEPUSValue, JSAtom, int32_t); - int32_t (*js_delete_property)(LEPUSContext *, LEPUSValue, JSAtom, int32_t); - int32_t (*js_get_own_property_names)(LEPUSContext *, LEPUSValue, uint32_t *, - struct LEPUSPropertyEnum **, int32_t); - int32_t (*js_deep_equal_callback)(LEPUSContext *, LEPUSValue, LEPUSValue); - LEPUSValue (*jsarray_push)(LEPUSContext *, LEPUSValue, int32_t, - LEPUSValueConst *, int32_t); - LEPUSValue (*jsarray_pop)(LEPUSContext *, LEPUSValue, int32_t); - int64_t (*jsarray_find)(LEPUSContext *, LEPUSValue, LEPUSValue, int64_t, - int32_t); - LEPUSValue (*jsarray_reverse)(LEPUSContext *, LEPUSValue); - LEPUSValue (*jsarray_slice)(LEPUSContext *, LEPUSValue, size_t, size_t, - size_t, LEPUSValue *, int32_t); -} PrimjsCallbacks; - -typedef struct JSMallocState { - size_t malloc_count; - // - uint64_t malloc_size; - uint64_t malloc_limit; - struct malloc_state allocate_state; - // - void *opaque; /* user opaque */ -} JSMallocState; - -typedef struct LEPUSMallocFunctions { - void *(*lepus_malloc)(JSMallocState *s, size_t size, int alloc_tag); - void (*lepus_free)(JSMallocState *s, void *ptr); - void *(*lepus_realloc)(JSMallocState *s, void *ptr, size_t size, - int alloc_tag); - size_t (*lepus_malloc_usable_size)(const void *ptr); -} LEPUSMallocFunctions; - -#ifdef ENABLE_QUICKJS_DEBUGGER -typedef struct QJSDebuggerCallbacks2 { - // callbacks for quickjs debugger - void (*run_message_loop_on_pause)(LEPUSContext *ctx); - void (*quit_message_loop_on_pause)(LEPUSContext *ctx); - void (*get_messages)(LEPUSContext *ctx); - void (*send_response)(LEPUSContext *ctx, int32_t message_id, - const char *message); - void (*send_notification)(LEPUSContext *ctx, const char *message); - void (*free_messages)(LEPUSContext *ctx, char **messages, int32_t size); - - void (*inspector_check)(LEPUSContext *ctx); - void (*debugger_exception)(LEPUSContext *ctx); - void (*console_message)(LEPUSContext *ctx, int tag, LEPUSValueConst *argv, - int argc); - void (*script_parsed_ntfy)(LEPUSContext *ctx, LEPUSScriptSource *source); - void (*console_api_called_ntfy)(LEPUSContext *ctx, LEPUSValue *msg); - void (*script_fail_parse_ntfy)(LEPUSContext *ctx, LEPUSScriptSource *source); - void (*debugger_paused)(LEPUSContext *ctx, const uint8_t *cur_pc); - uint8_t (*is_devtool_on)(LEPUSRuntime *rt); - void (*send_response_with_view_id)(LEPUSContext *ctx, int32_t message_id, - const char *message, int32_t view_id); - void (*send_ntfy_with_view_id)(LEPUSContext *ctx, const char *message, - int32_t view_id); - void (*script_parsed_ntfy_with_view_id)(LEPUSContext *ctx, - LEPUSScriptSource *source, - int32_t view_id); - void (*script_fail_parse_ntfy_with_view_id)(LEPUSContext *ctx, - LEPUSScriptSource *source, - int32_t view_id); - void (*set_session_enable_state)(LEPUSContext *ctx, int32_t view_id, - int32_t protocol_type); - void (*get_session_state)(LEPUSContext *ctx, int32_t view_id, - bool *is_already_enabled, bool *is_paused); - void (*console_api_called_ntfy_with_rid)(LEPUSContext *ctx, LEPUSValue *msg); - void (*get_session_enable_state)(LEPUSContext *ctx, int32_t view_id, - int32_t protocol_type, bool *ret); - void (*get_console_stack_trace)(LEPUSContext *ctx, LEPUSValue *ret); - void (*on_console_message)(LEPUSContext *ctx, LEPUSValue console_message, - int32_t); -} QJSDebuggerCallbacks2; -#endif - -typedef struct SettingsOption { - /* - If this value is true, quickjs will not adjust stack size - when stack size is unconsistent. - */ - bool disable_adjust_stacksize; - bool disable_json_opt; - bool disable_deepclone_opt; - bool disable_separable_string; -} SettingsOption; -class GlobalHandles; -class GarbageCollector; -class PtrHandles; -class ByteThreadPool; -class napi_handle_scope__; - -struct LEPUSRuntime { - LEPUSMallocFunctions mf; - const char *rt_info; - - // for trace gc - - int atom_hash_size; /* power of two */ - int atom_count; - int atom_size; - int atom_count_resize; /* resize hash table at this count */ - uint32_t *atom_hash; - JSAtomStruct **atom_array; - int atom_free_index; /* 0 = none */ - - int class_count; /* size of class_array */ - LEPUSClass *class_array; - - struct list_head context_list; /* list of LEPUSContext.link */ - /* list of JSGCObjectHeader.link. List of allocated GC objects (used - by the garbage collector) */ - /* list of allocated objects (used by the garbage collector) */ - struct list_head obj_list; /* list of LEPUSObject.link */ - // - struct list_head gc_bytecode_list; - struct list_head gc_obj_list; - // - struct list_head tmp_obj_list; /* used during gc */ - struct list_head free_obj_list; /* used during gc */ - struct list_head *el_next; /* used during gc */ - BOOL in_gc_sweep : 8; - int c_stack_depth; - uint64_t malloc_gc_threshold; - /* stack limitation */ - const uint8_t *stack_top; - size_t stack_size; /* in bytes */ - - LEPUSValue current_exception; - /* true if a backtrace needs to be added to the current exception - (the backtrace generation cannot be done immediately in a bytecode - function) */ - BOOL exception_needs_backtrace; - /* true if inside an out of memory error, to avoid recursing */ - BOOL in_out_of_memory : 8; - - struct LEPUSStackFrame *current_stack_frame; - - LEPUSInterruptHandler *interrupt_handler; - void *interrupt_opaque; - - struct list_head job_list; /* list of JSJobEntry.link */ - - LEPUSModuleNormalizeFunc *module_normalize_func; - LEPUSModuleLoaderFunc *module_loader_func; - void *module_loader_opaque; - - BOOL can_block : 8; /* TRUE if Atomics.wait can block */ - - /* Shape hash table */ - int shape_hash_bits; - int shape_hash_size; - int shape_hash_count; /* number of hashed shapes */ - JSShape **shape_hash; - PrimjsCallbacks primjs_callbacks_; - - struct list_head - unhandled_rejections; // record the first unhandled rejection error - struct list_head async_func_sf; // record all async functions' stack frame. - -#ifdef BUILD_ASYNC_STACK - LEPUSValue *current_micro_task; -#endif - -#ifdef ENABLE_LEPUSNG - LEPUSLepusRefCallbacks js_callbacks_; - JSLepusType js_type_; -#endif - -#ifdef ENABLE_QUICKJS_DEBUGGER - QJSDebuggerCallbacks2 debugger_callbacks_; - int32_t next_script_id; // next script id that can be used -#endif -#ifdef CONFIG_BIGNUM - bf_context_t bf_ctx; -#endif - // -#ifdef ENABLE_PRIMJS_SNAPSHOT - bool use_primjs; -#endif -#ifdef DUMP_LEAKS - struct list_head string_list; /* list of JSString.link */ -#endif - // - void (*update_gc_info)(const char *, int); - char gc_info_start_[BUF_LEN]; - char gc_info_end_[BUF_LEN]; - int64_t init_time; - - ByteThreadPool *workerThreadPool; - GlobalHandles *global_handles_ = nullptr; - - QJSValueValueSpace *qjsvaluevalue_allocator = nullptr; - PtrHandles *ptr_handles; - GarbageCollector *gc; - size_t gc_cnt; - void *mem_for_oom; - bool gc_enable; - bool is_lepusng; - void *user_opaque; - // Primjs begin - SettingsOption settings_option; - // Primjs end - JSMallocState malloc_state; -#ifdef ENABLE_TRACING_GC - LEPUSObject *boilerplateArg0; - LEPUSObject *boilerplateArg1; - LEPUSObject *boilerplateArg2; - LEPUSObject *boilerplateArg3; -#endif -}; - -static const char *const native_error_name[JS_NATIVE_ERROR_COUNT] = { - "EvalError", "RangeError", "ReferenceError", "SyntaxError", - "TypeError", "URIError", "InternalError", "AggregateError"}; - -/* Set/Map/WeakSet/WeakMap */ - -typedef struct JSMapState { - BOOL is_weak; /* TRUE if WeakSet/WeakMap */ - struct list_head records; /* list of JSMapRecord.link */ - uint32_t record_count; - struct list_head *hash_table; - uint32_t hash_size; /* must be a power of two */ - uint32_t record_count_threshold; /* count at which a hash table - resize is needed */ -} JSMapState; - -typedef struct JSUnhandledRejectionEntry { - struct list_head link; - LEPUSValue error; - LEPUSValue promise; -} JSUnhandledRejectionEntry; - -struct LEPUSClass { - uint32_t class_id; /* 0 means free entry */ - JSAtom class_name; - LEPUSClassFinalizer *finalizer; - LEPUSClassGCMark *gc_mark; - LEPUSClassCall *call; - /* pointers for exotic behavior, can be NULL if none are present */ - const LEPUSClassExoticMethods *exotic; -}; - -#define JS_MODE_STRICT (1 << 0) -#define JS_MODE_STRIP (1 << 1) -#define JS_MODE_BIGINT (1 << 2) -#define JS_MODE_MATH (1 << 3) - -typedef struct LEPUSStackFrame { - struct LEPUSStackFrame *prev_frame; /* NULL if first stack frame */ - LEPUSValue - cur_func; /* current function, LEPUS_UNDEFINED if the frame is detached */ - LEPUSValue *arg_buf; /* arguments */ - LEPUSValue *var_buf; /* variables */ - struct list_head var_ref_list; /* list of JSVarRef.link */ - const uint8_t *cur_pc; /* only used in bytecode functions : PC of the - instruction after the call */ - int arg_count; - int js_mode; /* for C functions: 0 */ - /* only used in generators. Current stack pointer value. NULL if - the function is running. */ - LEPUSValue *cur_sp; - LEPUSValue *sp = nullptr; -#ifdef ENABLE_QUICKJS_DEBUGGER - // for debugger: this_obj of the stack frame - LEPUSValue pthis; -#endif - struct JSVarRef **var_refs = nullptr; - uint32_t ref_size = 0; -} LEPUSStackFrame; - -enum TOK { - TOK_NUMBER = -128, - TOK_STRING, - TOK_TEMPLATE, - TOK_IDENT, - TOK_REGEXP, - /* warning: order matters (see js_parse_assign_expr) */ - TOK_MUL_ASSIGN, - TOK_DIV_ASSIGN, - TOK_MOD_ASSIGN, - TOK_PLUS_ASSIGN, - TOK_MINUS_ASSIGN, - TOK_SHL_ASSIGN, - TOK_SAR_ASSIGN, - TOK_SHR_ASSIGN, - TOK_AND_ASSIGN, - TOK_XOR_ASSIGN, - TOK_OR_ASSIGN, -#ifdef CONFIG_BIGNUM - TOK_MATH_POW_ASSIGN, -#endif - TOK_POW_ASSIGN, - TOK_DOUBLE_QUESTION_MARK_ASSIGN, - TOK_DEC, - TOK_INC, - TOK_SHL, - TOK_SAR, - TOK_SHR, - TOK_LT, - TOK_LTE, - TOK_GT, - TOK_GTE, - TOK_EQ, - TOK_STRICT_EQ, - TOK_NEQ, - TOK_STRICT_NEQ, - TOK_LAND, - TOK_LOR, -#ifdef CONFIG_BIGNUM - TOK_MATH_POW, -#endif - TOK_POW, - TOK_ARROW, - TOK_ELLIPSIS, - TOK_DOUBLE_QUESTION_MARK, - TOK_QUESTION_MARK_DOT, - TOK_ERROR, - TOK_PRIVATE_NAME, - TOK_EOF, - /* keywords: WARNING: same order as atoms */ - TOK_NULL, /* must be first */ - TOK_FALSE, - TOK_TRUE, - TOK_IF, - TOK_ELSE, - TOK_RETURN, - TOK_VAR, - TOK_THIS, - TOK_DELETE, - TOK_VOID, - TOK_TYPEOF, - TOK_NEW, - TOK_IN, - TOK_INSTANCEOF, - TOK_DO, - TOK_WHILE, - TOK_FOR, - TOK_BREAK, - TOK_CONTINUE, - TOK_SWITCH, - TOK_CASE, - TOK_DEFAULT, - TOK_THROW, - TOK_TRY, - TOK_CATCH, - TOK_FINALLY, - TOK_FUNCTION, - TOK_DEBUGGER, - TOK_WITH, - /* FutureReservedWord */ - TOK_CLASS, - TOK_CONST, - TOK_ENUM, - TOK_EXPORT, - TOK_EXTENDS, - TOK_IMPORT, - TOK_SUPER, - /* FutureReservedWords when parsing strict mode code */ - TOK_IMPLEMENTS, - TOK_INTERFACE, - TOK_LET, - TOK_PACKAGE, - TOK_PRIVATE, - TOK_PROTECTED, - TOK_PUBLIC, - TOK_STATIC, - TOK_YIELD, - TOK_AWAIT, /* must be last */ - TOK_OF, /* only used for js_parse_skip_parens_token() */ -}; -#define TOK_FIRST_KEYWORD TOK_NULL -#define TOK_LAST_KEYWORD TOK_AWAIT -struct JSString { - LEPUSRefCountHeader header; /* must come first, 32-bit */ - uint32_t len : 31; - uint8_t is_wide_char : 1; /* 0 = 8 bits, 1 = 16 bits characters */ - /* for JS_ATOM_TYPE_SYMBOL: hash = 0, atom_type = 3, - for JS_ATOM_TYPE_PRIVATE: hash = 1, atom_type = 3 - XXX: could change encoding to have one more bit in hash */ - uint32_t hash : 30; - uint8_t atom_type : 2; /* != 0 if atom, JS_ATOM_TYPE_x */ - uint32_t hash_next; /* atom_index for JS_ATOM_TYPE_SYMBOL */ -#ifdef DUMP_LEAKS - struct list_head link; /* string list */ -#endif - -#ifdef ENABLE_LEPUSNG - // Primjs add - void *cache_; // add to convert to jsString -#endif - union { - uint8_t str8[0]; /* 8 bit strings will get an extra null terminator */ - uint16_t str16[0]; - } u; -}; - -typedef struct JSGCHeader { - uint8_t mark; -} JSGCHeader; - -typedef struct JSVarRef { - LEPUSRefCountHeader header; /* must come first, 32-bit */ - JSGCHeader gc_header; /* must come after LEPUSRefCountHeader, 8-bit */ - uint8_t is_arg : 1; - /* - * 0: the VarRef is on the stack. - * 1: the VarRef is detached, pvalue == &value; - */ - uint8_t is_detached : 1; - int var_idx; /* index of the corresponding function variable on - the stack */ - struct list_head link; - LEPUSValue *pvalue; /* pointer to the value, either on the stack or - to 'value' */ - LEPUSValue value; /* used when the variable is no longer on the stack */ -} JSVarRef; - -#ifdef CONFIG_BIGNUM -typedef struct JSFloatEnv { - limb_t prec; - bf_flags_t flags; - unsigned int status; -} JSFloatEnv; - -typedef struct JSBigFloat { - LEPUSRefCountHeader header; /* must come first, 32-bit */ - bf_t num; -} JSBigFloat; - -/* the same structure is used for big integers and big floats. Big - integers are never infinite or NaNs */ -#else -#ifdef ENABLE_LEPUSNG -// -typedef struct JSBigFloat { - LEPUSRefCountHeader header; /* must come first, 32-bit */ - uint64_t num; -} JSBigFloat; - -// -#endif -#endif - -/* must be large enough to have a negligible runtime cost and small - enough to call the interrupt callback often. */ -#define JS_INTERRUPT_COUNTER_INIT 10000 -// -#define DEFAULT_VIRTUAL_STACK_SIZE 1024 * 1024 * 4 -#define FALLBACK_VIRTUAL_STACK_SIZE 1024 * 1024 * 1 -#define MINIFY_VIRTUAL_STACK_SIZE 1024 * 1024 * 2 -// - -// -typedef unsigned char u_char; -typedef u_char *address; -// - -typedef enum OPCodeFormat { -#define FMT(f) OP_FMT_##f, -#define DEF(id, size, n_pop, n_push, f) -#include "quickjs/include/quickjs-opcode.h" -#undef DEF -#undef FMT -} OPCodeFormat; - -typedef enum OPCodeEnum { -#define FMT(f) -#define DEF(id, size, n_pop, n_push, f) OP_##id, -#define def(id, size, n_pop, n_push, f) -#include "quickjs/include/quickjs-opcode.h" -#undef def -#undef DEF -#undef FMT - OP_COUNT, /* excluding temporary opcodes */ - /* temporary opcodes : overlap with the short opcodes */ - OP_TEMP_START = OP_nop + 1, - OP___dummy = OP_TEMP_START - 1, -#define FMT(f) -#define DEF(id, size, n_pop, n_push, f) -#define def(id, size, n_pop, n_push, f) OP_##id, -#include "quickjs/include/quickjs-opcode.h" -#undef def -#undef DEF -#undef FMT - OP_TEMP_END, - -// The following opcode cannot be dumped into the bianry production. -#define COMPILE_TIME_OPCODE(id, size, n_pop, n_push, f) OP_##id, -#include "quickjs/include/quickjs-opcode.h" -#undef COMPILE_TIME_OPCODE - -} OPCodeEnum; - -struct FinalizationRegistryContext; - -struct LEPUSContext { -#ifdef ENABLE_PRIMJS_SNAPSHOT - address (*dispatch_table)[OP_COUNT]; -#endif -// -#ifndef ALLOCATE_WINDOWS - mstate allocate_state; -#endif - LEPUSRuntime *rt; - struct list_head link; - - uint16_t binary_object_count; - int binary_object_size; - - JSShape *array_shape; /* initial shape for Array objects */ - - LEPUSValue *class_proto; - LEPUSValue function_proto; - LEPUSValue function_ctor; - LEPUSValue regexp_ctor; - LEPUSValue promise_ctor; - LEPUSValue native_error_proto[JS_NATIVE_ERROR_COUNT]; - LEPUSValue iterator_proto; - LEPUSValue async_iterator_proto; - LEPUSValue array_proto_values; - LEPUSValue throw_type_error; - LEPUSValue eval_obj; - - LEPUSValue global_obj; /* global object */ - LEPUSValue global_var_obj; /* contains the global let/const definitions */ - - uint64_t random_state; -#ifdef CONFIG_BIGNUM - bf_context_t *bf_ctx; /* points to rt->bf_ctx, shared by all contexts */ - JSFloatEnv fp_env; /* global FP environment */ -#endif - /* when the counter reaches zero, JSRutime.interrupt_handler is called */ - int interrupt_counter; - BOOL is_error_property_enabled; - - struct list_head loaded_modules; /* list of LEPUSModuleDef.link */ - - /* if NULL, RegExp compilation is not supported */ - LEPUSValue (*compile_regexp)(LEPUSContext *ctx, LEPUSValueConst pattern, - LEPUSValueConst flags); - /* if NULL, eval is not supported */ - LEPUSValue (*eval_internal)(LEPUSContext *ctx, LEPUSValueConst this_obj, - const char *input, size_t input_len, - const char *filename, int flags, int scope_idx, - bool debugger_eval, LEPUSStackFrame *sf); - - void *user_opaque; - // - int64_t napi_env; - BOOL no_lepus_strict_mode; -#if defined(__APPLE__) && !defined(GEN_ANDROID_EMBEDDED) - uint32_t stack_pos; - uint8_t *stack; -#endif -#ifdef ENABLE_QUICKJS_DEBUGGER - LEPUSDebuggerInfo *debugger_info; // structure for quickjs debugger -#endif - uint32_t next_function_id; // for lepusng debugger encode. - uint8_t - debuginfo_outside; // for lepusng debugger encode to avoid break change. - char *lynx_target_sdk_version; - BOOL debugger_mode; - BOOL debugger_parse_script; // for shared context debugger - BOOL debugger_need_polling; - BOOL console_inspect; - // - - PtrHandles *ptr_handles; - napi_handle_scope__ *napi_scope; - bool gc_enable; - bool is_lepusng; - uint64_t binary_version; - struct FinalizationRegistryContext *fg_ctx = nullptr; -}; - -typedef union JSFloat64Union { - double d; - uint64_t u64; - uint32_t u32[2]; -} JSFloat64Union; - -enum { - JS_ATOM_TYPE_STRING = 1, - JS_ATOM_TYPE_GLOBAL_SYMBOL, - JS_ATOM_TYPE_SYMBOL, - JS_ATOM_TYPE_PRIVATE, -}; - -enum { - JS_ATOM_HASH_SYMBOL, - JS_ATOM_HASH_PRIVATE, -}; - -typedef enum { - JS_ATOM_KIND_STRING, - JS_ATOM_KIND_SYMBOL, - JS_ATOM_KIND_PRIVATE, -} JSAtomKindEnum; - -#define JS_ATOM_HASH_MASK ((1 << 30) - 1) - -typedef struct LEPUSClosureVar { - uint8_t is_local : 1; - uint8_t is_arg : 1; - uint8_t is_const : 1; - uint8_t is_lexical : 1; - uint8_t var_kind : 4; /* see JSVarKindEnum */ - /* 9 bits available */ - uint16_t var_idx; /* is_local = TRUE: index to a normal variable of the - parent function. otherwise: index to a closure - variable of the parent function */ - JSAtom var_name; -} LEPUSClosureVar; - -#define ARG_SCOPE_INDEX 1 -#define ARG_SCOPE_END (-2) -#define DEBUG_SCOPE_INDEX (-3) - -typedef struct JSVarScope { - int parent; /* index into fd->scopes of the enclosing scope */ - int first; /* index into fd->vars of the last variable in this scope */ -} JSVarScope; - -typedef enum { - /* XXX: add more variable kinds here instead of using bit fields */ - JS_VAR_NORMAL, - JS_VAR_FUNCTION_DECL, /* lexical var with function declaration */ - JS_VAR_NEW_FUNCTION_DECL, /* lexical var with async/generator function - declaration */ - JS_VAR_CATCH, - JS_VAR_FUNCTION_NAME, - JS_VAR_PRIVATE_FIELD, - JS_VAR_PRIVATE_METHOD, - JS_VAR_PRIVATE_GETTER, - JS_VAR_PRIVATE_SETTER, /* must come after JS_VAR_PRIVATE_GETTER */ - JS_VAR_PRIVATE_GETTER_SETTER, /* must come after JS_VAR_PRIVATE_SETTER - */ -} JSVarKindEnum; - -typedef struct JSVarDef { - JSAtom var_name; - int scope_level; /* index into fd->scopes of this variable lexical scope */ - int scope_next; /* index into fd->vars of the next variable in the - * same or enclosing lexical scope */ - uint8_t is_const : 1; - uint8_t is_lexical : 1; - uint8_t is_captured : 1; - uint8_t var_kind : 4; /* see JSVarKindEnum */ - int func_pool_idx : 24; /* only used during compilation */ -} JSVarDef; - -/* for the encoding of the pc2line table */ -#define PC2LINE_BASE (-1) -#define PC2LINE_RANGE 5 -#define PC2LINE_OP_FIRST 1 -#define PC2LINE_DIFF_PC_MAX ((255 - PC2LINE_OP_FIRST) / PC2LINE_RANGE) - -// -#define LINE_NUMBER_BITS_COUNT 24 -#define COLUMN_NUMBER_BITS_COUNT 40 -// for compatibility -#define OLD_LINE_NUMBER_BITS_COUNT 12 -// use 2 bits for type. -#define LINE_COLUMN_TYPE_SHIFT 62 -// - -typedef enum JSFunctionKindEnum { - JS_FUNC_NORMAL = 0, - JS_FUNC_GENERATOR = (1 << 0), - JS_FUNC_ASYNC = (1 << 1), - JS_FUNC_ASYNC_GENERATOR = (JS_FUNC_GENERATOR | JS_FUNC_ASYNC), -} JSFunctionKindEnum; - -// -enum class EntryMode { INTERPRETER, BASELINE }; - -#define JIT_THRESHOLD 6 - -// - -// settings key opt - -enum { - PRIMJS_SNAPSHOT_ENABLE = 0b000000001, - JSON_OPT_DISABLE = 0b000000010, - GC_INFO_ENABLE = 0b000000100, - DEEPCLONE_OPT_DISABLE = 0b000001000, - LEPUSNG_HEAP_20 = 0b000010000, - LEPUSNG_HEAP_24 = 0b000100000, - DISABLE_ADJUST_STACKSIZE = 0b001000000, - DISABLE_SEPARABLE_STRING = 0b010000000, - GC_ENABLE = 0b100000000, - EFFECT_ENABLE = 0b1000000000, - MINIFY_STACK_ENABLE = 0b10000000000, - ENABLE_LEPUSNG_STRAGETY = 0b100000000000, - LEPUSNG_HEAP_12 = 0b1000000000000, - LEPUSNG_GC_DISABLE = 0b10000000000000, -}; - -inline int settingsFlag = 0; -// settings key opt end - -typedef struct CallerStrSlot { - uint32_t pc; - uint32_t size : 31; - uint32_t is_str : 1; - union { - const char *str; - uint32_t off; - }; -} CallerStrSlot; - -typedef struct LEPUSFunctionBytecode { - LEPUSRefCountHeader header; /* must come first, 32-bit */ - JSGCHeader gc_header; /* must come after header, 8-bit */ - uint8_t js_mode; - uint8_t has_prototype : 1; /* true if a prototype field is necessary */ - uint8_t has_simple_parameter_list : 1; - uint8_t is_derived_class_constructor : 1; - /* true if home_object needs to be initialized */ - uint8_t need_home_object : 1; - uint8_t func_kind : 2; - uint8_t new_target_allowed : 1; - uint8_t super_call_allowed : 1; - uint8_t super_allowed : 1; - uint8_t arguments_allowed : 1; - uint8_t has_debug : 1; - uint8_t read_only_bytecode : 1; - /* XXX: 4 bits available */ - uint8_t *byte_code_buf; /* (self pointer) */ - int byte_code_len; - JSAtom func_name; - JSVarDef *vardefs; /* arguments + local variables (arg_count + var_count) - (self pointer) */ - LEPUSClosureVar - *closure_var; /* list of variables in the closure (self pointer) */ - uint16_t arg_count; - uint16_t var_count; - uint16_t defined_arg_count; /* for length function property */ - uint16_t stack_size; /* maximum stack size */ - LEPUSValue *cpool; /* constant pool (self pointer) */ - int cpool_count; - int closure_var_count; - -#ifdef ENABLE_QUICKJS_DEBUGGER - DebuggerFuncLevelState func_level_state; - struct list_head link; /*ctx->debugger_info->bytecode_list*/ - LEPUSScriptSource *script; - int32_t bp_num; -#endif - // - struct list_head gc_link; - uint32_t function_id; // for lepusNG debugger encode - // - struct { - /* debug info, move to separate structure to save memory? */ - JSAtom filename; - int line_num; - int source_len; - int pc2line_len; -#ifdef ENABLE_QUICKJS_DEBUGGER - int64_t column_num; -#endif - uint8_t *pc2line_buf; - char *source; - struct list_head link; - // for cpu profiler to use. - JSString *file_name; - JSString *func_name; - - CallerStrSlot *caller_slots; - size_t caller_size; - // end. - } debug; - // ATTENTION: NEW MEMBERS MUST BE ADDED IN FRONT OF DEBUG FIELD! -} LEPUSFunctionBytecode; - -typedef struct JSBoundFunction { - LEPUSValue func_obj; - LEPUSValue this_val; - int argc; - LEPUSValue argv[0]; -} JSBoundFunction; - -typedef enum JSIteratorKindEnum { - JS_ITERATOR_KIND_KEY, - JS_ITERATOR_KIND_VALUE, - JS_ITERATOR_KIND_KEY_AND_VALUE, -} JSIteratorKindEnum; - -typedef struct JSForInIterator { - LEPUSValue obj; - BOOL is_array; - uint32_t array_length; - uint32_t idx; -} JSForInIterator; - -typedef struct JSRegExp { - JSString *pattern; - JSString *bytecode; /* also contains the flags */ -} JSRegExp; - -typedef struct JSProxyData { - LEPUSValue target; - LEPUSValue handler; - LEPUSValue proto; - uint8_t is_func; - uint8_t is_revoked; -} JSProxyData; - -typedef struct JSArrayBuffer { - int byte_length; /* 0 if detached */ - uint8_t detached; - uint8_t shared; /* if shared, the array buffer cannot be detached */ - uint8_t *data; /* NULL if detached */ - struct list_head array_list; - void *opaque; - LEPUSFreeArrayBufferDataFunc *free_func; - BOOL from_js_heap; -} JSArrayBuffer; - -typedef struct JSTypedArray { - struct list_head link; /* link to arraybuffer */ - LEPUSObject *obj; /* back pointer to the TypedArray/DataView object */ - LEPUSObject *buffer; /* based array buffer */ - uint32_t offset; /* offset in the array buffer */ - uint32_t length; /* length in the array buffer */ -} JSTypedArray; - -typedef struct JSAsyncFunctionState { - LEPUSValue this_val; /* 'this' generator argument */ - int argc; /* number of function arguments */ - BOOL throw_flag; /* used to throw an exception in JS_CallInternal() */ - LEPUSStackFrame frame; - list_head link; -#ifdef ENABLE_PRIMJS_SNAPSHOT - LEPUSValue *_arg_buf; -#endif -} JSAsyncFunctionState; - -/* XXX: could use an object instead to avoid the - LEPUS_TAG_ASYNC_FUNCTION tag for the GC */ -typedef struct JSAsyncFunctionData { - LEPUSRefCountHeader header; /* must come first, 32-bit */ - JSGCHeader gc_header; /* must come after LEPUSRefCountHeader, 8-bit */ - LEPUSValue resolving_funcs[2]; - BOOL is_active; /* true if the async function state is valid */ - JSAsyncFunctionState func_state; -} JSAsyncFunctionData; - -typedef struct JSReqModuleEntry { - JSAtom module_name; - LEPUSModuleDef *module; /* used using resolution */ -} JSReqModuleEntry; - -typedef enum JSExportTypeEnum { - JS_EXPORT_TYPE_LOCAL, - JS_EXPORT_TYPE_INDIRECT, -} JSExportTypeEnum; - -typedef struct JSExportEntry { - union { - struct { - int var_idx; /* closure variable index */ - JSVarRef *var_ref; /* if != NULL, reference to the variable */ - } local; /* for local export */ - int req_module_idx; /* module for indirect export */ - } u; - JSExportTypeEnum export_type; - JSAtom local_name; /* '*' if export ns from. not used for local - export after compilation */ - JSAtom export_name; /* exported variable name */ -} JSExportEntry; - -typedef struct JSStarExportEntry { - int req_module_idx; /* in req_module_entries */ -} JSStarExportEntry; - -typedef struct JSImportEntry { - int var_idx; /* closure variable index */ - JSAtom import_name; - int req_module_idx; /* in req_module_entries */ -} JSImportEntry; - -struct LEPUSModuleDef { - LEPUSRefCountHeader header; /* must come first, 32-bit */ - JSAtom module_name; - struct list_head link; - - JSReqModuleEntry *req_module_entries; - int req_module_entries_count; - int req_module_entries_size; - - JSExportEntry *export_entries; - int export_entries_count; - int export_entries_size; - - JSStarExportEntry *star_export_entries; - int star_export_entries_count; - int star_export_entries_size; - - JSImportEntry *import_entries; - int import_entries_count; - int import_entries_size; - - LEPUSValue module_ns; - LEPUSValue func_obj; /* only used for LEPUS modules */ - LEPUSModuleInitFunc *init_func; /* only used for C modules */ - BOOL resolved : 8; - BOOL instantiated : 8; - BOOL evaluated : 8; - BOOL eval_mark : 8; /* temporary use during js_evaluate_module() */ - /* true if evaluation yielded an exception. It is saved in - eval_exception */ - BOOL eval_has_exception : 8; - LEPUSValue eval_exception; -}; - -typedef struct JSJobEntry { - struct list_head link; - LEPUSContext *ctx; - LEPUSJobFunc *job_func; - int argc; - LEPUSValue argv[0]; -} JSJobEntry; - -typedef enum { - WEAK_REF_KIND_WEAK_MAP, - WEAK_REF_KIND_WEAK_REF, - WEAK_REF_KIND_FINALIZATION_REGISTRY, -} WeakRefRecordKind; - -typedef struct FinalizationRegistryContext { - int32_t ref_count; - LEPUSContext *ctx; -} FinalizationRegistryContext; - -typedef struct FinalizationRegistryData { - struct FinalizationRegistryContext *fg_ctx; - list_head entries; - LEPUSValue cbs; -} FinalizationRegistryData; - -typedef struct FinalizationRegistryEntry { - struct list_head link; - FinalizationRegistryData *data; // FinalizationRegistryObj - LEPUSValue target; // registerd object - LEPUSValue held_value; - LEPUSValue token; -} FinalizationRegistryEntry; - -typedef struct WeakRefData { - LEPUSValue target; -} WeakRefData; - -typedef struct WeakRefRecord { - WeakRefRecordKind kind; - struct WeakRefRecord *next_weak_ref; - union { - JSMapRecord *map_record; - FinalizationRegistryEntry *fin_node; - WeakRefData *weak_ref; - void *ptr; - } u; -} WeakRefRecord; - -typedef enum JSGeneratorStateEnum { - JS_GENERATOR_STATE_SUSPENDED_START, - JS_GENERATOR_STATE_SUSPENDED_YIELD, - JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR, - JS_GENERATOR_STATE_EXECUTING, - JS_GENERATOR_STATE_COMPLETED, -} JSGeneratorStateEnum; - -typedef struct JSGeneratorData { - JSGeneratorStateEnum state; - JSAsyncFunctionState func_state; -} JSGeneratorData; - -typedef struct JSProperty { - union { - LEPUSValue value; /* LEPUS_PROP_NORMAL */ - struct { /* LEPUS_PROP_GETSET */ - LEPUSObject *getter; /* NULL if undefined */ - LEPUSObject *setter; /* NULL if undefined */ - } getset; - JSVarRef *var_ref; /* LEPUS_PROP_VARREF */ - struct { /* LEPUS_PROP_AUTOINIT */ - LEPUSValue (*init_func)(LEPUSContext *ctx, LEPUSObject *obj, JSAtom prop, - void *opaque); - void *opaque; - } init; - } u; -} JSProperty; - -#define JS_PROP_INITIAL_SIZE 2 -#define JS_PROP_INITIAL_HASH_SIZE 4 /* must be a power of two */ -#define JS_ARRAY_INITIAL_SIZE 2 - -typedef struct JSShapeProperty { - uint32_t hash_next : 26; /* 0 if last in list */ - uint32_t flags : 6; /* JS_PROP_XXX */ - JSAtom atom; /* JS_ATOM_NULL = free property entry */ -} JSShapeProperty; - -struct JSShape { - uint32_t prop_hash_end[0]; /* hash table of size hash_mask + 1 - before the start of the structure. */ - LEPUSRefCountHeader header; /* must come first, 32-bit */ - JSGCHeader gc_header; /* must come after LEPUSRefCountHeader, 8-bit */ - /* true if the shape is inserted in the shape hash table. If not, - JSShape.hash is not valid */ - uint8_t is_hashed; - /* If true, the shape may have small array index properties 'n' with 0 - <= n <= 2^31-1. If false, the shape is guaranteed not to have - small array index properties */ - uint8_t has_small_array_index; - uint32_t hash; /* current hash value */ - uint32_t prop_hash_mask; - int prop_size; /* allocated properties */ - int prop_count; - JSShape *shape_hash_next; /* in LEPUSRuntime.shape_hash[h] list */ - LEPUSObject *proto; - JSShapeProperty prop[0]; /* prop_size elements */ -}; -struct LEPUSObject { - LEPUSRefCountHeader header; /* must come first, 32-bit */ - JSGCHeader gc_header; /* must come after LEPUSRefCountHeader, 8-bit */ - uint8_t extensible : 1; - uint8_t free_mark : 1; /* only used when freeing objects with cycles */ - uint8_t is_exotic : 1; /* TRUE if object has exotic property handlers */ - uint8_t fast_array : 1; /* TRUE if u.array is used for get/put */ - uint8_t is_constructor : 1; /* TRUE if object is a constructor function */ - uint8_t is_uncatchable_error : 1; /* if TRUE, error is not catchable */ - uint8_t is_class : 1; /* TRUE if object is a class constructor */ - uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */ - uint16_t class_id; /* see JS_CLASS_x */ - /* byte offsets: 8/8 */ - struct list_head link; /* object list */ - /* byte offsets: 16/24 */ - JSShape *shape; /* prototype and property names + flag */ - JSProperty *prop; /* array of properties */ - /* byte offsets: 24/40 */ - struct WeakRefRecord - *first_weak_ref; /* XXX: use a bit and an external hash table? */ - /* byte offsets: 28/48 */ - union { - void *opaque; - struct JSBoundFunction *bound_function; /* JS_CLASS_BOUND_FUNCTION */ - struct JSCFunctionDataRecord - *c_function_data_record; /* JS_CLASS_C_FUNCTION_DATA */ - struct JSForInIterator *for_in_iterator; /* JS_CLASS_FOR_IN_ITERATOR */ - struct JSArrayBuffer *array_buffer; /* JS_CLASS_ARRAY_BUFFER, - JS_CLASS_SHARED_ARRAY_BUFFER */ - struct JSTypedArray - *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_DATAVIEW */ -#ifdef CONFIG_BIGNUM - struct JSFloatEnv *float_env; /* JS_CLASS_FLOAT_ENV */ -#endif - struct JSMapState *map_state; /* JS_CLASS_MAP..JS_CLASS_WEAKSET */ - struct JSMapIteratorData *map_iterator_data; /* JS_CLASS_MAP_ITERATOR, - JS_CLASS_SET_ITERATOR */ - struct JSArrayIteratorData - *array_iterator_data; /* JS_CLASS_ARRAY_ITERATOR, - JS_CLASS_STRING_ITERATOR */ - struct JSRegExpStringIteratorData - *regexp_string_iterator_data; /* JS_CLASS_REGEXP_STRING_ITERATOR */ - struct JSGeneratorData *generator_data; /* JS_CLASS_GENERATOR */ - struct JSProxyData *proxy_data; /* JS_CLASS_PROXY */ - struct JSPromiseData *promise_data; /* JS_CLASS_PROMISE */ - struct JSPromiseFunctionData - *promise_function_data; /* JS_CLASS_PROMISE_RESOLVE_FUNCTION, - JS_CLASS_PROMISE_REJECT_FUNCTION */ - struct JSAsyncFunctionData - *async_function_data; /* JS_CLASS_ASYNC_FUNCTION_RESOLVE, - JS_CLASS_ASYNC_FUNCTION_REJECT */ - struct JSAsyncFromSyncIteratorData - *async_from_sync_iterator_data; /* JS_CLASS_ASYNC_FROM_SYNC_ITERATOR - */ - struct JSAsyncGeneratorData - *async_generator_data; /* JS_CLASS_ASYNC_GENERATOR */ - struct FinalizationRegistryData - *fin_reg_data; // JS_CLASS_FinalizationRegistry - struct WeakRefData *weak_ref_data; - struct { /* JS_CLASS_BYTECODE_FUNCTION: 12/24 - bytes */ - /* also used by JS_CLASS_GENERATOR_FUNCTION, JS_CLASS_ASYNC_FUNCTION - * and JS_CLASS_ASYNC_GENERATOR_FUNCTION */ - struct LEPUSFunctionBytecode *function_bytecode; - JSVarRef **var_refs; - LEPUSObject *home_object; /* for 'super' access */ - } func; - struct { /* JS_CLASS_C_FUNCTION: 12/20 bytes */ - LEPUSCFunctionType c_function; - uint8_t length; - uint8_t cproto; - int16_t magic; - } cfunc; - /* array part for fast arrays and typed arrays */ - struct { /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, - JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ - union { - uint32_t size; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ - struct JSTypedArray - *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY - */ - } u1; - union { - LEPUSValue *values; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ - void *ptr; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ - int8_t *int8_ptr; /* JS_CLASS_INT8_ARRAY */ - uint8_t *uint8_ptr; /* JS_CLASS_UINT8_ARRAY, JS_CLASS_UINT8C_ARRAY */ - int16_t *int16_ptr; /* JS_CLASS_INT16_ARRAY */ - uint16_t *uint16_ptr; /* JS_CLASS_UINT16_ARRAY */ - int32_t *int32_ptr; /* JS_CLASS_INT32_ARRAY */ - uint32_t *uint32_ptr; /* JS_CLASS_UINT32_ARRAY */ - int64_t *int64_ptr; /* JS_CLASS_INT64_ARRAY */ - uint64_t *uint64_ptr; /* JS_CLASS_UINT64_ARRAY */ - float *float_ptr; /* JS_CLASS_FLOAT32_ARRAY */ - double *double_ptr; /* JS_CLASS_FLOAT64_ARRAY */ - } u; - uint32_t count; /* <= 2^31-1. 0 for a detached typed array */ - } array; /* 12/20 bytes */ - JSRegExp regexp; /* JS_CLASS_REGEXP: 8/16 bytes */ - LEPUSValue object_data; /* for JS_SetObjectData(): 8/16/16 bytes */ - } u; - /* byte sizes: 40/48/72 */ -}; - -constexpr const char *lepusjs_filename = "file://lepus.js"; -constexpr const char *lepusng_functionid_str = "__lepusNG_function_id__"; - -enum { - JS_ATOM_NULL, -#define DEF(name, str) JS_ATOM_##name, -#include "quickjs/include/quickjs-atom.h" -#undef DEF - JS_ATOM_END, -}; -#define JS_ATOM_LAST_KEYWORD JS_ATOM_super -#define JS_ATOM_LAST_STRICT_KEYWORD JS_ATOM_yield - -static const char js_atom_init[] = -#define DEF(name, str) str "\0" -#include "quickjs/include/quickjs-atom.h" -#undef DEF - ; - -typedef struct JSOpCode { -#if defined(ENABLE_PRIMJS_SNAPSHOT) || defined(DUMP_BYTECODE) - const char *name; -#endif - - uint8_t size; /* in bytes */ - /* the opcodes remove n_pop items from the top of the stack, then - pushes n_push items */ - uint8_t n_pop; - uint8_t n_push; - uint8_t fmt; -} JSOpCode; - -extern const JSOpCode opcode_info[]; - -#if SHORT_OPCODES -/* After the final compilation pass, short opcodes are used. Their - opcodes overlap with the temporary opcodes which cannot appear in - the final bytecode. Their description is after the temporary - opcodes in opcode_info[]. */ -#define short_opcode_info(op) \ - opcode_info[(op) >= OP_TEMP_START ? (op) + (OP_TEMP_END - OP_TEMP_START) \ - : (op)] -#else -#define short_opcode_info(op) opcode_info[op] -#endif - -// - -#if defined(ANDROID) || defined(__ANDROID__) -#include - -#define LOG_TAG "primjs" - -#ifndef LOGD -#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) -#endif -#ifndef LOGE -#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) -#endif -#ifndef LOGI -#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -#endif -#endif - -#define PRINT_LOG_TO_FILE 0 - -#ifdef ENABLE_PRIMJS_TRACE -#if defined(ANDROID) || defined(__ANDROID__) -#if PRINT_LOG_TO_FILE -extern FILE *log_f; -#define PRIM_LOG(...) \ - do { \ - fprintf(log_f, __VA_ARGS__); \ - fflush(log_f); \ - } while (0) -#else -#define PRIM_LOG(...) \ - __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) -#endif // PRINT_LOG_TO_FILE -#else -#define PRIM_LOG printf -#endif // ANDROID -#else -#define PRIM_LOG(...) -#endif // ENABLE_PRIMJS_TRACE - -#define OP_DEFINE_METHOD_METHOD 0 -#define OP_DEFINE_METHOD_GETTER 1 -#define OP_DEFINE_METHOD_SETTER 2 -#define OP_DEFINE_METHOD_ENUMERABLE 4 - -#define JS_THROW_VAR_RO 0 -#define JS_THROW_VAR_REDECL 1 -#define JS_THROW_VAR_UNINITIALIZED 2 -#define JS_THROW_ERROR_DELETE_SUPER 3 - -#define LEPUS_CALL_FLAG_CONSTRUCTOR (1 << 0) -#define JS_CALL_FLAG_COPY_ARGV (1 << 1) -#define JS_CALL_FLAG_GENERATOR (1 << 2) - -#define __exception __attribute__((warn_unused_result)) - -/* JSAtom support */ -#define JS_ATOM_TAG_INT (1U << 31) -#define JS_ATOM_MAX_INT (JS_ATOM_TAG_INT - 1) -#define JS_ATOM_MAX ((1U << 30) - 1) - -/* return the max count from the hash size */ -#define JS_ATOM_COUNT_RESIZE(n) ((n) * 2) - -/* argument of OP_special_object */ -typedef enum { - OP_SPECIAL_OBJECT_ARGUMENTS, - OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS, - OP_SPECIAL_OBJECT_THIS_FUNC, - OP_SPECIAL_OBJECT_NEW_TARGET, - OP_SPECIAL_OBJECT_HOME_OBJECT, - OP_SPECIAL_OBJECT_VAR_OBJECT, -} OPSpecialObjectEnum; - -#define FUNC_RET_AWAIT 0 -#define FUNC_RET_YIELD 1 -#define FUNC_RET_YIELD_STAR 2 - -#define HINT_STRING 0 -#define HINT_NUMBER 1 -#define HINT_NONE 2 -#ifdef CONFIG_BIGNUM -#define HINT_INTEGER 3 -#endif -/* don't try Symbol.toPrimitive */ -#define HINT_FORCE_ORDINARY (1 << 4) - -#define prim_abort() \ - { \ - printf("[%s:%d] Abort\n", __FILE__, __LINE__); \ - abort(); \ - } - -#ifdef __cplusplus -extern "C" { -#endif - -inline void *system_malloc(size_t size) { - void *ptr; - ptr = malloc(size); - if (!ptr) return NULL; - return ptr; -} -inline void *system_mallocz(size_t size) { - void *ptr; - ptr = system_malloc(size); - if (!ptr) return NULL; - return memset(ptr, 0, size); -} -inline __attribute__((unused)) void *system_realloc(void *ptr, size_t size) { - if (!ptr) { - if (size == 0) return NULL; - return system_malloc(size); - } - if (size == 0) { - free(ptr); - return NULL; - } - - ptr = realloc(ptr, size); - if (!ptr) return NULL; - return ptr; -} -inline void system_free(void *ptr) { - if (!ptr) return; - free(ptr); -} - -typedef struct JSSeparableString { - LEPUSRefCountHeader header; /* ref count for gc*/ - uint32_t len : 31; - uint8_t is_wide_char : 1; - uint32_t depth; - LEPUSValue left_op; - LEPUSValue right_op; - LEPUSValue flat_content; -} JSSeparableString; - -class CStack { - using element = JSSeparableString *; - element *base_ = nullptr; - element *top_ = nullptr; - size_t stack_size_ = 0; - LEPUSRuntime *runtime_ = nullptr; - static constexpr size_t STACK_INIT_SIZE = 64; - - public: - explicit CStack(LEPUSRuntime *rt, uint32_t depth = STACK_INIT_SIZE) { - runtime_ = rt; - base_ = static_cast(system_malloc(sizeof(element) * depth)); - if (!base_) return; - top_ = base_; - stack_size_ = depth; - } - - ~CStack() { system_free(base_); } - - void Push(element node) { - if (static_cast(top_ - base_) >= stack_size_) { - base_ = static_cast( - system_realloc(base_, 2 * stack_size_ * sizeof(element))); - if (!base_) { - stack_size_ = 0; - top_ = nullptr; - return; - } - top_ = base_ + stack_size_; - stack_size_ *= 2; - } - *top_++ = node; - } - - void Pop() { - if (!Empty()) { - --top_; - } - } - - element Top() { - if (!Empty()) { - return *(top_ - 1); - } - return nullptr; - } - - int32_t Empty() { return top_ == base_; } -}; - -QJS_STATIC inline int32_t JS_IsSeparableString(LEPUSValue val) { - return LEPUS_VALUE_IS_SEPARABLE_STRING(val); -} - -QJS_STATIC inline JSSeparableString *JS_GetSeparableString(LEPUSValue val) { - return reinterpret_cast(LEPUS_VALUE_GET_PTR(val)); -} - -LEPUSValue JS_GetSeparableStringContent(LEPUSContext *ctx, LEPUSValue val); -LEPUSValue JS_GetSeparableStringContentNotDup(LEPUSContext *ctx, - LEPUSValue val); - -QJS_HIDE LEPUSValue JS_GetPropertyInternalImpl(LEPUSContext *ctx, - LEPUSValueConst obj, JSAtom prop, - LEPUSValueConst this_obj, - BOOL throw_ref_error); -QJS_HIDE LEPUSValue JS_GetPropertyInternalImpl_GC(LEPUSContext *ctx, - LEPUSValueConst obj, - JSAtom prop, - LEPUSValueConst this_obj, - BOOL throw_ref_error); -QJS_HIDE void prim_js_print(const char *msg); -QJS_HIDE void prim_js_print_gc(const char *msg); - -QJS_HIDE void prim_js_print_register(uint64_t reg_val); - -QJS_HIDE void prim_js_print_trace(int bytecode, int tos); -QJS_HIDE void prim_js_print_trace_gc(int bytecode, int tos); - -QJS_HIDE void prim_js_print_func(LEPUSContext *ctx, LEPUSValue func_obj); -QJS_HIDE void prim_js_print_func_gc(LEPUSContext *ctx, LEPUSValue func_obj); - -QJS_HIDE void JS_FreeValueRef(LEPUSContext *ctx, LEPUSValue v); - -QJS_HIDE LEPUSValue js_closure(LEPUSContext *ctx, LEPUSValue bfunc, - JSVarRef **cur_var_refs, LEPUSStackFrame *sf); -LEPUSValue js_closure_gc(LEPUSContext *ctx, LEPUSValue bfunc, - JSVarRef **cur_var_refs, LEPUSStackFrame *sf); - -QJS_HIDE void DebuggerPause(LEPUSContext *ctx, LEPUSValue val, - const uint8_t *pc); - -QJS_HIDE void DebuggerCallEachOp(LEPUSContext *ctx, const uint8_t *pc, - LEPUSFunctionBytecode *b); - -QJS_HIDE void DebuggerCallEachFunc(LEPUSContext *ctx, const uint8_t *pc); - -QJS_HIDE LEPUSValue __JS_AtomToValue(LEPUSContext *ctx, JSAtom atom, - BOOL force_string); -QJS_HIDE LEPUSValue __JS_AtomToValue_GC(LEPUSContext *ctx, JSAtom atom, - BOOL force_string); -QJS_HIDE BOOL js_check_stack_overflow(LEPUSContext *ctx, size_t alloca_size); -QJS_HIDE LEPUSValue JS_ThrowStackOverflow(LEPUSContext *ctx); -QJS_HIDE LEPUSValue JS_ThrowStackOverflow_GC(LEPUSContext *ctx); -QJS_HIDE void build_backtrace( - LEPUSContext *ctx, LEPUSValueConst error_obj, const char *filename, - /* */ int64_t line_num, /* */ - const uint8_t *cur_pc, int backtrace_flags, uint8_t is_parse_error = 0); -QJS_HIDE LEPUSValue JS_NewSymbolFromAtom(LEPUSContext *ctx, JSAtom descr, - int atom_type); -QJS_HIDE LEPUSValue JS_NewSymbolFromAtom_GC(LEPUSContext *ctx, JSAtom descr, - int atom_type); -QJS_HIDE LEPUSValue JS_ToObject_GC(LEPUSContext *ctx, LEPUSValueConst val); -QJS_HIDE LEPUSValue PRIM_JS_NewObject(LEPUSContext *ctx); -QJS_HIDE LEPUSValue PRIM_JS_NewObject_GC(LEPUSContext *ctx); -QJS_HIDE LEPUSValue js_build_arguments(LEPUSContext *ctx, int argc, - LEPUSValueConst *argv); -QJS_HIDE LEPUSValue js_build_arguments_gc(LEPUSContext *ctx, int argc, - LEPUSValueConst *argv); -QJS_HIDE LEPUSValue js_build_mapped_arguments(LEPUSContext *ctx, int argc, - LEPUSValueConst *argv, - LEPUSStackFrame *sf, - int arg_count); -QJS_HIDE LEPUSValue js_build_mapped_arguments_gc(LEPUSContext *ctx, int argc, - LEPUSValueConst *argv, - LEPUSStackFrame *sf, - int arg_count); -QJS_HIDE void prim_close_var_refs(LEPUSContext *ctx, LEPUSStackFrame *sf); -QJS_HIDE void prim_close_var_refs_gc(LEPUSContext *ctx, LEPUSStackFrame *sf); -QJS_HIDE LEPUSValue js_build_rest(LEPUSContext *ctx, int first, int argc, - LEPUSValueConst *argv); -QJS_HIDE LEPUSValue js_build_rest_gc(LEPUSContext *ctx, int first, int argc, - LEPUSValueConst *argv); -QJS_HIDE LEPUSValue js_function_apply(LEPUSContext *ctx, - LEPUSValueConst this_val, int argc, - LEPUSValueConst *argv, int magic); -QJS_HIDE LEPUSValue js_function_apply_gc(LEPUSContext *ctx, - LEPUSValueConst this_val, int argc, - LEPUSValueConst *argv, int magic); -QJS_HIDE int JS_CheckBrand(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst func); -QJS_HIDE int JS_CheckBrand_GC(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst func); -QJS_HIDE int JS_AddBrand(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst home_obj); -QJS_HIDE int JS_AddBrand_GC(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst home_obj); -QJS_HIDE int JS_ThrowTypeErrorReadOnly(LEPUSContext *ctx, int flags, - JSAtom atom); -QJS_HIDE LEPUSValue JS_ThrowSyntaxErrorVarRedeclaration(LEPUSContext *ctx, - JSAtom prop); -QJS_HIDE LEPUSValue JS_ThrowSyntaxErrorVarRedeclaration_GC(LEPUSContext *ctx, - JSAtom prop); -QJS_HIDE LEPUSValue JS_ThrowReferenceErrorUninitialized(LEPUSContext *ctx, - JSAtom name); -QJS_HIDE LEPUSValue JS_ThrowReferenceErrorUninitialized_GC(LEPUSContext *ctx, - JSAtom name); -QJS_HIDE int JS_IteratorClose(LEPUSContext *ctx, LEPUSValueConst enum_obj, - BOOL is_exception_pending); - -QJS_HIDE LEPUSValue JS_CallConstructorInternal(LEPUSContext *ctx, - LEPUSValueConst func_obj, - LEPUSValueConst new_target, - int argc, LEPUSValue *argv, - int flags); -QJS_HIDE LEPUSValue JS_CallConstructorInternal_GC(LEPUSContext *ctx, - LEPUSValueConst func_obj, - LEPUSValueConst new_target, - int argc, LEPUSValue *argv, - int flags); -QJS_HIDE int JS_CheckGlobalVar(LEPUSContext *ctx, JSAtom prop); -QJS_HIDE int JS_CheckGlobalVar_GC(LEPUSContext *ctx, JSAtom prop); -QJS_HIDE LEPUSValue JS_GetPropertyValue(LEPUSContext *ctx, - LEPUSValueConst this_obj, - LEPUSValue prop); - -QJS_HIDE LEPUSValue JS_GetPropertyValue_GC(LEPUSContext *ctx, - LEPUSValueConst this_obj, - LEPUSValue prop); -QJS_HIDE int JS_DefineGlobalVar(LEPUSContext *ctx, JSAtom prop, int def_flags); -QJS_HIDE int JS_DefineGlobalVar_GC(LEPUSContext *ctx, JSAtom prop, - int def_flags); -QJS_HIDE LEPUSValue PRIM_JS_NewArray(LEPUSContext *ctx); -QJS_HIDE LEPUSValue PRIM_JS_NewArray_GC(LEPUSContext *ctx); - -QJS_HIDE LEPUSValue js_regexp_constructor_internal(LEPUSContext *ctx, - LEPUSValueConst ctor, - LEPUSValue pattern, - LEPUSValue bc); -QJS_HIDE LEPUSValue js_regexp_constructor_internal_gc(LEPUSContext *ctx, - LEPUSValueConst ctor, - LEPUSValue pattern, - LEPUSValue bc); -QJS_HIDE int JS_SetPropertyValue(LEPUSContext *ctx, LEPUSValueConst this_obj, - LEPUSValue prop, LEPUSValue val, int flags); -QJS_HIDE int JS_SetPropertyValue_GC(LEPUSContext *ctx, LEPUSValueConst this_obj, - LEPUSValue prop, LEPUSValue val, int flags); -QJS_HIDE int JS_CheckDefineGlobalVar(LEPUSContext *ctx, JSAtom prop, int flags); -QJS_HIDE int JS_CheckDefineGlobalVar_GC(LEPUSContext *ctx, JSAtom prop, - int flags); -QJS_HIDE int JS_DefineGlobalFunction(LEPUSContext *ctx, JSAtom prop, - LEPUSValueConst func, int def_flags); -QJS_HIDE int JS_DefineGlobalFunction_GC(LEPUSContext *ctx, JSAtom prop, - LEPUSValueConst func, int def_flags); -QJS_HIDE LEPUSValue JS_GetPrivateField(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst name); -QJS_HIDE LEPUSValue JS_GetPrivateField_GC(LEPUSContext *ctx, - LEPUSValueConst obj, - LEPUSValueConst name); -QJS_HIDE int JS_DefinePrivateField(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst name, LEPUSValue val); -QJS_HIDE int JS_DefinePrivateField_GC(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst name, LEPUSValue val); -QJS_HIDE int JS_DefineObjectName(LEPUSContext *ctx, LEPUSValueConst obj, - JSAtom name, int flags); -QJS_HIDE int JS_DefineObjectNameComputed(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst str, int flags); -QJS_HIDE int JS_DefineObjectNameComputed_GC(LEPUSContext *ctx, - LEPUSValueConst obj, - LEPUSValueConst str, int flags); -QJS_HIDE int JS_SetPrototypeInternal(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst proto_val, - BOOL throw_flag); -QJS_HIDE int JS_SetPrototypeInternal_GC(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst proto_val, - BOOL throw_flag); -QJS_HIDE void js_method_set_home_object(LEPUSContext *ctx, - LEPUSValueConst func_obj, - LEPUSValueConst home_obj); -QJS_HIDE void js_method_set_home_object_gc(LEPUSContext *ctx, - LEPUSValueConst func_obj, - LEPUSValueConst home_obj); -QJS_HIDE int JS_DefinePropertyValueValue(LEPUSContext *ctx, - LEPUSValueConst this_obj, - LEPUSValue prop, LEPUSValue val, - int flags); -QJS_HIDE int JS_DefinePropertyValueValue_GC(LEPUSContext *ctx, - LEPUSValueConst this_obj, - LEPUSValue prop, LEPUSValue val, - int flags); -QJS_HIDE __exception int js_append_enumerate(LEPUSContext *ctx, LEPUSValue *sp); -QJS_HIDE __exception int js_append_enumerate_gc(LEPUSContext *ctx, - LEPUSValue *sp); -QJS_HIDE int js_method_set_properties(LEPUSContext *ctx, - LEPUSValueConst func_obj, JSAtom name, - int flags, LEPUSValueConst home_obj); -QJS_HIDE int js_method_set_properties_gc(LEPUSContext *ctx, - LEPUSValueConst func_obj, JSAtom name, - int flags, LEPUSValueConst home_obj); -QJS_HIDE int prim_js_copy_data_properties(LEPUSContext *ctx, LEPUSValue *sp, - int mask); -QJS_HIDE int prim_js_copy_data_properties_gc(LEPUSContext *ctx, LEPUSValue *sp, - int mask); -QJS_HIDE int JS_ToBoolFree(LEPUSContext *ctx, LEPUSValue val); -QJS_HIDE int JS_ToBoolFree_GC(LEPUSContext *ctx, LEPUSValue val); -QJS_HIDE int js_op_define_class(LEPUSContext *ctx, LEPUSValue *sp, - JSAtom class_name, int class_flags, - JSVarRef **cur_var_refs, LEPUSStackFrame *sf); -QJS_HIDE void close_lexical_var(LEPUSContext *ctx, LEPUSStackFrame *sf, - int idx); -QJS_HIDE int JS_SetPropertyGeneric(LEPUSContext *ctx, LEPUSObject *p, - JSAtom prop, LEPUSValue val, - LEPUSValueConst this_obj, int flags); -QJS_HIDE int JS_SetPropertyGeneric_GC(LEPUSContext *ctx, LEPUSObject *p, - JSAtom prop, LEPUSValue val, - LEPUSValueConst this_obj, int flags); -QJS_HIDE int JS_SetPrivateField(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst name, LEPUSValue val); -QJS_HIDE int JS_SetPrivateField_GC(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst name, LEPUSValue val); -QJS_HIDE LEPUSValue JS_ThrowTypeErrorNotAnObject(LEPUSContext *ctx); -QJS_HIDE int prim_js_with_op_gc(LEPUSContext *ctx, LEPUSValue *sp, JSAtom atom, - int is_with, int opcode); -QJS_HIDE JSVarRef *get_var_ref(LEPUSContext *ctx, LEPUSStackFrame *sf, - int var_idx, BOOL is_arg); -QJS_HIDE JSVarRef *get_var_ref_gc(LEPUSContext *ctx, LEPUSStackFrame *sf, - int var_idx, BOOL is_arg); -QJS_HIDE void free_var_ref(LEPUSRuntime *rt, JSVarRef *var_ref); - -QJS_HIDE JSProperty *add_property(LEPUSContext *ctx, LEPUSObject *p, - JSAtom prop, int prop_flags); -QJS_HIDE JSProperty *add_property_gc(LEPUSContext *ctx, LEPUSObject *p, - JSAtom prop, int prop_flags); -QJS_HIDE LEPUSValue prim_js_op_eval(LEPUSContext *ctx, int scope_idx, - LEPUSValue op1); -QJS_HIDE LEPUSValue prim_js_op_eval_gc(LEPUSContext *ctx, int scope_idx, - LEPUSValue op1); -QJS_HIDE int prim_js_with_op(LEPUSContext *ctx, LEPUSValue *sp, JSAtom atom, - int is_with, int opcode); - -QJS_HIDE LEPUSValue JS_GetGlobalVarImpl(LEPUSContext *ctx, JSAtom prop, - BOOL throw_ref_error); -QJS_HIDE LEPUSValue JS_GetGlobalVarImpl_GC(LEPUSContext *ctx, JSAtom prop, - BOOL throw_ref_error); -QJS_HIDE int JS_GetGlobalVarRef(LEPUSContext *ctx, JSAtom prop, LEPUSValue *sp); -QJS_HIDE int JS_GetGlobalVarRef_GC(LEPUSContext *ctx, JSAtom prop, - LEPUSValue *sp); -QJS_HIDE LEPUSValue prim_js_for_in_start(LEPUSContext *ctx, LEPUSValue op); -QJS_HIDE LEPUSValue prim_js_for_in_start_gc(LEPUSContext *ctx, LEPUSValue op); -QJS_HIDE int js_for_in_next(LEPUSContext *ctx, LEPUSValue *sp); -QJS_HIDE int js_for_in_next_gc(LEPUSContext *ctx, LEPUSValue *sp); -QJS_HIDE int js_for_await_of_next(LEPUSContext *ctx, LEPUSValue *sp); -QJS_HIDE int js_for_await_of_next_gc(LEPUSContext *ctx, LEPUSValue *sp); -QJS_HIDE int js_iterator_get_value_done(LEPUSContext *ctx, LEPUSValue *sp); -QJS_HIDE int js_iterator_get_value_done_gc(LEPUSContext *ctx, LEPUSValue *sp); -QJS_HIDE int js_for_of_start(LEPUSContext *ctx, LEPUSValue *sp, BOOL is_async); -QJS_HIDE int js_for_of_start_gc(LEPUSContext *ctx, LEPUSValue *sp, - BOOL is_async); -QJS_HIDE int js_for_of_next(LEPUSContext *ctx, LEPUSValue *sp, int offset); -QJS_HIDE int js_for_of_next_gc(LEPUSContext *ctx, LEPUSValue *sp, int offset); -QJS_HIDE LEPUSValue *prim_js_iterator_close_return(LEPUSContext *ctx, - LEPUSValue *sp, - LEPUSValue *stack_buf); -QJS_HIDE LEPUSValue *prim_js_iterator_close_return_gc(LEPUSContext *ctx, - LEPUSValue *sp); -QJS_HIDE int prim_js_async_iterator_close(LEPUSContext *ctx, LEPUSValue *sp); -QJS_HIDE int prim_js_async_iterator_close_gc(LEPUSContext *ctx, LEPUSValue *sp); -QJS_HIDE int prim_js_async_iterator_get(LEPUSContext *ctx, LEPUSValue *sp, - int flags); -QJS_HIDE int prim_js_async_iterator_get_gc(LEPUSContext *ctx, LEPUSValue *sp, - int flags); -QJS_HIDE LEPUSValue primjs_get_super_ctor(LEPUSContext *ctx, LEPUSValue op); -QJS_HIDE LEPUSValue primjs_get_super_ctor_gc(LEPUSContext *ctx, LEPUSValue op); -QJS_HIDE int prim_js_iterator_call(LEPUSContext *ctx, LEPUSValue *sp, - int flags); - -QJS_HIDE LEPUSValue JS_ToPrimitiveFree(LEPUSContext *ctx, LEPUSValue val, - int hint); -QJS_HIDE LEPUSValue JS_ToPrimitiveFree_GC(LEPUSContext *ctx, LEPUSValue val, - int hint); -QJS_HIDE LEPUSValue JS_ConcatString(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2); -QJS_HIDE LEPUSValue JS_ConcatString_GC(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2); -QJS_HIDE LEPUSValue prim_js_unary_arith_slow(LEPUSContext *ctx, LEPUSValue op1, - OPCodeEnum op); -QJS_HIDE LEPUSValue prim_js_unary_arith_slow_gc(LEPUSContext *ctx, - LEPUSValue op1, OPCodeEnum op); -QJS_HIDE LEPUSValue prim_js_add_slow(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2); -QJS_HIDE LEPUSValue prim_js_add_slow_gc(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2); -QJS_HIDE no_inline LEPUSValue prim_js_not_slow(LEPUSContext *ctx, - LEPUSValue op); -QJS_HIDE no_inline LEPUSValue prim_js_not_slow_gc(LEPUSContext *ctx, - LEPUSValue op); -QJS_HIDE LEPUSValue prim_js_binary_arith_slow(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2, OPCodeEnum op); -QJS_HIDE LEPUSValue prim_js_binary_arith_slow_gc(LEPUSContext *ctx, - LEPUSValue op1, LEPUSValue op2, - OPCodeEnum op); -QJS_HIDE double prim_js_fmod_double(double a, double b); -QJS_HIDE double prim_js_fmod_double_gc(double a, double b); -QJS_HIDE int js_post_inc_slow(LEPUSContext *ctx, LEPUSValue *sp, OPCodeEnum op); -QJS_HIDE int js_post_inc_slow_gc(LEPUSContext *ctx, LEPUSValue *sp, - OPCodeEnum op); -QJS_HIDE LEPUSValue prim_js_binary_logic_slow(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2, OPCodeEnum op); -QJS_HIDE LEPUSValue prim_js_binary_logic_slow_gc(LEPUSContext *ctx, - LEPUSValue op1, LEPUSValue op2, - OPCodeEnum op); -QJS_HIDE LEPUSValue prim_js_shr_slow(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2); -QJS_HIDE LEPUSValue prim_js_shr_slow_gc(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2); -QJS_HIDE LEPUSValue prim_js_relation_slow(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2, OPCodeEnum op); -QJS_HIDE LEPUSValue prim_js_relation_slow_gc(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2, OPCodeEnum op); -QJS_HIDE LEPUSValue prim_js_eq_slow(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2, int is_neq); -QJS_HIDE LEPUSValue prim_js_eq_slow_gc(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2, int is_neq); -QJS_HIDE LEPUSValue prim_js_strict_eq_slow(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2, BOOL is_neq); -QJS_HIDE LEPUSValue prim_js_strict_eq_slow_gc(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2, BOOL is_neq); -QJS_HIDE LEPUSValue prim_js_operator_instanceof(LEPUSContext *ctx, - LEPUSValue op1, LEPUSValue op2); -QJS_HIDE LEPUSValue prim_js_operator_instanceof_gc(LEPUSContext *ctx, - LEPUSValue op1, - LEPUSValue op2); -QJS_HIDE LEPUSValue prim_js_operator_in(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2); -QJS_HIDE LEPUSValue prim_js_operator_in_gc(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2); -QJS_HIDE __exception int js_operator_typeof(LEPUSContext *ctx, LEPUSValue op1); -QJS_HIDE __exception int js_operator_typeof_gc(LEPUSContext *ctx, - LEPUSValue op1); -QJS_HIDE LEPUSValue prim_js_operator_delete(LEPUSContext *ctx, LEPUSValue op1, - LEPUSValue op2); -QJS_HIDE LEPUSValue prim_js_operator_delete_gc(LEPUSContext *ctx, - LEPUSValue op1, LEPUSValue op2); -QJS_HIDE int JS_SetPropertyInternalImpl(LEPUSContext *ctx, - LEPUSValueConst this_obj, JSAtom prop, - LEPUSValue val, int flags); -QJS_HIDE int JS_SetPropertyInternalImpl_GC(LEPUSContext *ctx, - LEPUSValueConst this_obj, - JSAtom prop, LEPUSValue val, - int flags); - -QJS_HIDE int set_array_length(LEPUSContext *ctx, LEPUSObject *p, - JSProperty *prop, LEPUSValue val, int flags); - -QJS_HIDE BOOL JS_IsUncatchableError(LEPUSContext *ctx, LEPUSValueConst val); -QJS_HIDE BOOL JS_IsUncatchableError_GC(LEPUSContext *ctx, LEPUSValueConst val); -QJS_HIDE JSAtom js_value_to_atom(LEPUSContext *ctx, LEPUSValueConst val); -QJS_HIDE JSAtom js_value_to_atom_gc(LEPUSContext *ctx, LEPUSValueConst val); -QJS_HIDE LEPUSValue JS_ThrowReferenceErrorNotDefined(LEPUSContext *ctx, - JSAtom name); -QJS_HIDE LEPUSValue JS_ThrowReferenceErrorNotDefined_GC(LEPUSContext *ctx, - JSAtom name); -LEPUSValue JS_ThrowTypeErrorNotFunction(LEPUSContext *ctx); - -#ifdef ENABLE_PRIMJS_SNAPSHOT -typedef LEPUSValue (*QuickJsCallStub)(LEPUSValue this_arg, - LEPUSValue new_target, - LEPUSValue func_obj, address entry_point, - int argc, LEPUSValue *argv, int flags); - -extern QuickJsCallStub entry; -QJS_HIDE void compile_function(LEPUSContext *, LEPUSFunctionBytecode *bytecode); -#endif - -// - -typedef struct JSToken { - int val; - int line_num; /* line number of token start */ - const uint8_t *ptr; - union { - struct { - LEPUSValue str; - int sep; - } str; - struct { - LEPUSValue val; -#ifdef CONFIG_BIGNUM - slimb_t exponent; /* may be != 0 only if val is a float */ -#endif - } num; - struct { - JSAtom atom; - BOOL has_escape; - BOOL is_reserved; - } ident; - struct { - LEPUSValue body; - LEPUSValue flags; - } regexp; - } u; -} JSToken; - -#ifndef NO_QUICKJS_COMPILER -LEPUSValue js_dynamic_import(LEPUSContext *ctx, LEPUSValueConst specifier); -#endif - -#ifdef __cplusplus -} -#endif - -/* */ -static __attribute__((unused)) int JS_DefineProperty_RC( - LEPUSContext *ctx, LEPUSValueConst this_obj, JSAtom prop, - LEPUSValueConst val, LEPUSValueConst getter, LEPUSValueConst setter, - int flags); -static __attribute__((unused)) int JS_DefinePropertyValue_RC( - LEPUSContext *ctx, LEPUSValueConst this_obj, JSAtom prop, LEPUSValue val, - int flags); -static __attribute__((unused)) void JS_MarkValue_RC(LEPUSRuntime *rt, - LEPUSValueConst val, - LEPUS_MarkFunc *mark_func, - int local_idx = -1); -static __attribute__((unused)) int JS_ToBoolFree_RC(LEPUSContext *ctx, - LEPUSValue val); -static __attribute__((unused)) int JS_IsInstanceOf_RC(LEPUSContext *ctx, - LEPUSValueConst val, - LEPUSValueConst obj); -static __attribute__((unused)) LEPUSValue JS_ToString_RC(LEPUSContext *ctx, - LEPUSValueConst val); -/* */ - -/* */ -LEPUSValue JS_GetSeparableStringContent_GC(LEPUSContext *ctx, LEPUSValue val); -LEPUSValue JS_GetSeparableStringContentNotDup_GC(LEPUSContext *ctx, - LEPUSValue val); -QJS_HIDE int set_array_length_gc(LEPUSContext *ctx, LEPUSObject *p, - JSProperty *prop, LEPUSValue val, int flags); -bool gc_enabled(); -LEPUSRuntime *JS_NewRuntime_GC(); -LEPUSRuntime *JS_NewRuntime2_GC(const LEPUSMallocFunctions *mf, void *opaque); -void JS_FreeRuntime_GC(LEPUSRuntime *rt); -void JS_FreeRuntimeForEffect(LEPUSRuntime *rt); -LEPUSContext *JS_NewContext_GC(LEPUSRuntime *rt); -void JS_FreeContext_GC(LEPUSContext *ctx); -LEPUSContext *JS_NewContextRaw_GC(LEPUSRuntime *rt); - -void JS_SetMemoryLimit_GC(LEPUSRuntime *rt, size_t limit); -void JS_RunGC_GC(LEPUSRuntime *rt); - -void JS_AddIntrinsicBaseObjects_GC(LEPUSContext *ctx); -void JS_AddIntrinsicDate_GC(LEPUSContext *ctx); -void JS_AddIntrinsicEval_GC(LEPUSContext *ctx); -void JS_AddIntrinsicStringNormalize_GC(LEPUSContext *ctx); -void JS_AddIntrinsicRegExp_GC(LEPUSContext *ctx); -void JS_AddIntrinsicJSON_GC(LEPUSContext *ctx); -void JS_AddIntrinsicProxy_GC(LEPUSContext *ctx); -void JS_AddIntrinsicMapSet_GC(LEPUSContext *ctx); -void JS_AddIntrinsicTypedArrays_GC(LEPUSContext *ctx); -void JS_AddIntrinsicPromise_GC(LEPUSContext *ctx); - -void JS_SetClassProto_GC(LEPUSContext *ctx, LEPUSClassID class_id, - LEPUSValue obj); -LEPUSValue JS_GetClassProto_GC(LEPUSContext *ctx, LEPUSClassID class_id); -int JS_MoveUnhandledRejectionToException_GC(LEPUSContext *ctx); -void JS_AddIntrinsicRegExpCompiler_GC(LEPUSContext *ctx); -#ifdef QJS_UNITTEST -LEPUSValue js_string_codePointRange_GC(LEPUSContext *ctx, - LEPUSValueConst this_val, int argc, - LEPUSValueConst *argv); -#endif - -JSAtom LEPUS_NewAtom(LEPUSContext *ctx, const char *str); -JSAtom JS_NewAtomUInt32_GC(LEPUSContext *ctx, uint32_t n); -LEPUSValue JS_AtomToValue_GC(LEPUSContext *ctx, JSAtom atom); -LEPUSValue JS_AtomToString_GC(LEPUSContext *ctx, JSAtom atom); -typedef struct JSClassShortDef { - JSAtom class_name; - LEPUSClassFinalizer *finalizer; - LEPUSClassGCMark *gc_mark; -} JSClassShortDef; -QJS_HIDE int init_class_range(LEPUSRuntime *rt, JSClassShortDef const *tab, - int start, int count); -const char *JS_AtomToCString_GC(LEPUSContext *ctx, JSAtom atom); - -void JS_MarkValue_GC(LEPUSRuntime *rt, LEPUSValueConst val, - LEPUS_MarkFunc *mark_func, int local_idx = -1); - -LEPUSValue JS_NewInt64_GC(LEPUSContext *ctx, int64_t v); -LEPUSValue JS_NewError_GC(LEPUSContext *ctx); - -void JS_SetVirtualStackSize_GC(LEPUSContext *ctx, uint32_t stack_size); -int JS_ToBool_GC(LEPUSContext *ctx, LEPUSValueConst val); -int JS_ToInt32_GC(LEPUSContext *ctx, int32_t *pres, LEPUSValueConst val); -int JS_ToInt64_GC(LEPUSContext *ctx, int64_t *pres, LEPUSValueConst val); -int JS_ToIndex_GC(LEPUSContext *ctx, uint64_t *plen, LEPUSValueConst val); -int JS_ToFloat64_GC(LEPUSContext *ctx, double *pres, LEPUSValueConst val); -int JS_ToBigInt64_GC(LEPUSContext *ctx, int64_t *pres, LEPUSValueConst val); -LEPUSValue JS_NewStringLen_GC(LEPUSContext *ctx, const char *buf, - size_t buf_len); -LEPUSValue JS_NewString_GC(LEPUSContext *ctx, const char *str); -LEPUSValue JS_NewAtomString_GC(LEPUSContext *ctx, const char *str); -LEPUSValue JS_ToString_GC(LEPUSContext *ctx, LEPUSValueConst val); -LEPUSValue JS_ToPropertyKey_GC(LEPUSContext *ctx, LEPUSValueConst val); -const char *JS_ToCStringLen2_GC(LEPUSContext *ctx, size_t *plen, - LEPUSValueConst val1, BOOL cesu8); - -LEPUSValue __attribute__((always_inline)) -JS_NewObjectProtoClass_GC(LEPUSContext *ctx, LEPUSValueConst proto_val, - LEPUSClassID class_id); -LEPUSValue JS_NewObjectClass_GC(LEPUSContext *ctx, int class_id); -LEPUSValue JS_NewObjectProto_GC(LEPUSContext *ctx, LEPUSValueConst proto); -LEPUSValue JS_NewObject_GC(LEPUSContext *ctx); -LEPUSValue JS_NewArray_GC(LEPUSContext *ctx); -int JS_IsArray_GC(LEPUSContext *ctx, LEPUSValueConst val); - -LEPUSValue JS_GetPropertyInternal_GC(LEPUSContext *ctx, LEPUSValueConst obj, - JSAtom prop, LEPUSValueConst this_obj, - BOOL throw_ref_error); -LEPUSValue JS_GetPropertyStr_GC(LEPUSContext *ctx, LEPUSValueConst this_obj, - const char *prop); -LEPUSValue JS_GetPropertyUint32_GC(LEPUSContext *ctx, LEPUSValueConst this_obj, - uint32_t idx); -int JS_SetPropertyInternal_GC(LEPUSContext *ctx, LEPUSValueConst this_obj, - JSAtom prop, LEPUSValue val, int flags); - -int JS_SetPropertyUint32_GC(LEPUSContext *ctx, LEPUSValueConst this_obj, - uint32_t idx, LEPUSValue val); -int JS_SetPropertyInt64_GC(LEPUSContext *ctx, LEPUSValueConst this_obj, - int64_t idx, LEPUSValue val); - -int JS_SetPropertyStr_GC(LEPUSContext *ctx, LEPUSValueConst this_obj, - const char *prop, LEPUSValue val); -int JS_HasProperty_GC(LEPUSContext *ctx, LEPUSValueConst obj, JSAtom prop); -int JS_IsExtensible_GC(LEPUSContext *ctx, LEPUSValueConst obj); -int JS_PreventExtensions_GC(LEPUSContext *ctx, LEPUSValueConst obj); -int JS_DeleteProperty_GC(LEPUSContext *ctx, LEPUSValueConst obj, JSAtom prop, - int flags); -int JS_SetPrototype_GC(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst proto_val); -LEPUSValueConst JS_GetPrototype_GC(LEPUSContext *ctx, LEPUSValueConst val); -int JS_GetOwnPropertyNames_GC(LEPUSContext *ctx, LEPUSPropertyEnum **ptab, - uint32_t *plen, LEPUSValueConst obj, int flags); -int JS_GetOwnProperty_GC(LEPUSContext *ctx, LEPUSPropertyDescriptor *desc, - LEPUSValueConst obj, JSAtom prop); -LEPUSValue JS_Call_GC(LEPUSContext *ctx, LEPUSValueConst func_obj, - LEPUSValueConst this_obj, int argc, - LEPUSValueConst *argv); -LEPUSValue JS_CallInternalTI_GC(LEPUSContext *caller_ctx, LEPUSValue func_obj, - LEPUSValue this_obj, LEPUSValue new_target, - int argc, LEPUSValue *argv, int flags); - -LEPUSValue JS_Invoke_GC(LEPUSContext *ctx, LEPUSValueConst this_val, - JSAtom atom, int argc, LEPUSValueConst *argv); -LEPUSValue JS_CallConstructor_GC(LEPUSContext *ctx, LEPUSValueConst func_obj, - int argc, LEPUSValueConst *argv); -LEPUSValue JS_CallConstructor2_GC(LEPUSContext *ctx, LEPUSValueConst func_obj, - LEPUSValueConst new_target, int argc, - LEPUSValueConst *argv); -LEPUSValue JS_Eval_GC(LEPUSContext *ctx, const char *input, size_t input_len, - const char *filename, int eval_flags); -LEPUSValue JS_EvalBinary_GC(LEPUSContext *ctx, const uint8_t *buf, - size_t buf_len, int flags); -LEPUSValue JS_GetGlobalObject_GC(LEPUSContext *ctx); -LEPUSValue JS_GetGlobalVar_GC(LEPUSContext *ctx, JSAtom prop, - BOOL throw_ref_error); -void JS_SetStringCache_GC(LEPUSContext *ctx, LEPUSValue val, void *p); -int JS_SetGlobalVar_GC(LEPUSContext *ctx, JSAtom prop, LEPUSValue val, - int flag); -LEPUSValue JS_DeepEqual_GC(LEPUSContext *ctx, LEPUSValueConst obj1, - LEPUSValueConst obj2); -LEPUSValue JS_DeepCopy_GC(LEPUSContext *ctx, LEPUSValueConst obj); -void JS_IterateObject_GC(LEPUSContext *ctx, LEPUSValue obj, - IterateObject callback, void *pfunc, void *raw_data); -int JS_GetLength_GC(LEPUSContext *ctx, LEPUSValue val); - -int JS_IsInstanceOf_GC(LEPUSContext *ctx, LEPUSValueConst val, - LEPUSValueConst obj); - -int JS_DefineProperty_GC(LEPUSContext *ctx, LEPUSValueConst this_obj, - JSAtom prop, LEPUSValueConst val, - LEPUSValueConst getter, LEPUSValueConst setter, - int flags); -int JS_DefinePropertyValue_GC(LEPUSContext *ctx, LEPUSValueConst this_obj, - JSAtom prop, LEPUSValue val, int flags); -int JS_DefinePropertyValueUint32_GC(LEPUSContext *ctx, LEPUSValueConst this_obj, - uint32_t idx, LEPUSValue val, int flags); -int JS_DefinePropertyValueStr_GC(LEPUSContext *ctx, LEPUSValueConst this_obj, - const char *prop, LEPUSValue val, int flags); -int JS_DefinePropertyGetSet_GC(LEPUSContext *ctx, LEPUSValueConst this_obj, - JSAtom prop, LEPUSValue getter, - LEPUSValue setter, int flags); -void *JS_GetOpaque2_GC(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSClassID class_id); -LEPUSValue JS_NewArrayBuffer_GC(LEPUSContext *ctx, uint8_t *buf, size_t len, - LEPUSFreeArrayBufferDataFunc *free_func, - void *opaque, BOOL is_shared); -LEPUSValue JS_NewArrayBufferCopy_GC(LEPUSContext *ctx, const uint8_t *buf, - size_t len); -void JS_DetachArrayBuffer_GC(LEPUSContext *ctx, LEPUSValueConst obj); -uint8_t *JS_GetArrayBuffer_GC(LEPUSContext *ctx, size_t *psize, - LEPUSValueConst obj); -uint8_t *JS_MoveArrayBuffer_GC(LEPUSContext *ctx, size_t *psize, - LEPUSValueConst obj); -LEPUS_BOOL JS_StrictEq_GC(LEPUSContext *ctx, LEPUSValueConst op1, - LEPUSValueConst op2); -LEPUS_BOOL JS_SameValue_GC(LEPUSContext *ctx, LEPUSValueConst op1, - LEPUSValueConst op2); -LEPUSValue JS_NewPromiseCapability_GC(LEPUSContext *ctx, - LEPUSValue *resolving_funcs); -int JS_EnqueueJob_GC(LEPUSContext *ctx, LEPUSJobFunc *job_func, int argc, - LEPUSValueConst *argv); -int JS_ExecutePendingJob_GC(LEPUSRuntime *rt, LEPUSContext **pctx); - -uint8_t *JS_WriteObject_GC(LEPUSContext *ctx, size_t *psize, - LEPUSValueConst obj, int flags); -LEPUSValue JS_EvalFunction_GC(LEPUSContext *ctx, LEPUSValue fun_obj, - LEPUSValueConst this_obj); -LEPUSValue JS_NewWString_GC(LEPUSContext *ctx, const uint16_t *buf, - size_t length); -QJS_HIDE LEPUSValue js_json_stringify_opt_GC(LEPUSContext *, LEPUSValue, - int32_t, LEPUSValue *); -JSAtom JS_ValueToAtom_GC(LEPUSContext *ctx, LEPUSValueConst val); -const uint16_t *JS_GetStringChars_GC(LEPUSContext *ctx, LEPUSValueConst str); -QJS_HIDE LEPUSValue JS_NewArrayWithValue_GC(LEPUSContext *ctx, uint32_t length, - LEPUSValueConst *values); -QJS_HIDE LEPUSValue JS_NewTypedArray_GC(LEPUSContext *ctx, uint32_t length, - LEPUSClassID class_id); -QJS_HIDE LEPUSValue JS_NewTypedArrayWithBuffer_GC(LEPUSContext *ctx, - LEPUSValueConst buffer, - uint32_t byteOffset, - uint32_t length, - LEPUSClassID class_id); - -QJS_HIDE LEPUSValue JS_CallConstructorV_GC(LEPUSContext *ctx, - LEPUSValueConst func_obj, int argc, - LEPUSValue *argv); -QJS_HIDE LEPUSValue JS_NewCFunction2_GC(LEPUSContext *ctx, LEPUSCFunction *func, - const char *name, int length, - LEPUSCFunctionEnum cproto, int magic); -QJS_HIDE LEPUSValue JS_NewCFunctionData_GC(LEPUSContext *ctx, - LEPUSCFunctionData *func, int length, - int magic, int data_len, - LEPUSValueConst *data); -QJS_HIDE void JS_SetPropertyFunctionList_GC(LEPUSContext *ctx, - LEPUSValueConst obj, - const LEPUSCFunctionListEntry *tab, - int len); -QJS_HIDE LEPUSValue js_object_getOwnPropertyDescriptor_GC( - LEPUSContext *ctx, LEPUSValueConst this_val, int argc, - LEPUSValueConst *argv, int magic); -QJS_HIDE int js_get_length32_gc(LEPUSContext *ctx, uint32_t *pres, - LEPUSValueConst obj); - -QJS_HIDE LEPUSValue JS_NewObjectWithArgs_GC(LEPUSContext *ctx, int32_t size, - const char **keys, - LEPUSValue *values); -QJS_HIDE LEPUSValue JS_NewArrayWithArgs_GC(LEPUSContext *ctx, int32_t size, - LEPUSValue *values); - -QJS_HIDE __exception int js_append_enumerate_gc(LEPUSContext *ctx, - LEPUSValue *sp); -QJS_HIDE __exception int js_iterator_get_value_done_gc(LEPUSContext *ctx, - LEPUSValue *sp); - -QJS_HIDE int JS_ToBoolFree_GC(LEPUSContext *ctx, LEPUSValue val); -QJS_HIDE LEPUSValue JS_ToPrimitiveFree_GC(LEPUSContext *ctx, LEPUSValue val, - int hint); -QJS_HIDE LEPUSValue JS_NewBigUint64_GC(LEPUSContext *ctx, uint64_t v); - -QJS_HIDE void JS_VisitLEPUSValue_GC(LEPUSRuntime *rt, LEPUSValue *val, - int local_idx); -QJS_HIDE void DisposeGlobal_GC(LEPUSRuntime *runtime, - LEPUSValue *global_handle); -QJS_HIDE LEPUSValue *GlobalizeReference_GC(LEPUSRuntime *runtime, - LEPUSValue val, bool is_weak); -QJS_HIDE void FreeNapiScope_GC(LEPUSContext *ctx); -QJS_HIDE void ClearGlobalWeak_GC(LEPUSRuntime *runtime, - LEPUSValue *global_handle); -QJS_HIDE void SetGlobalWeak_GC(LEPUSRuntime *runtime, LEPUSValue *global_handle, - void *data, void (*cb)(void *)); -QJS_HIDE void *GetNapiScope_GC(LEPUSContext *ctx); -QJS_HIDE void InitNapiScope_GC(LEPUSContext *ctx); -QJS_HIDE void SetNapiScope_GC(LEPUSContext *ctx, void *scope); -QJS_HIDE void SetWeakState_GC(LEPUSRuntime *runtime, LEPUSValue *global_handle); - -QJS_HIDE void JS_SetGCPauseSuppressionMode_GC(LEPUSRuntime *rt, bool mode); -QJS_HIDE bool JS_GetGCPauseSuppressionMode_GC(LEPUSRuntime *rt); -QJS_HIDE __attribute__((unused)) bool CheckValidPtr_GC(void *runtime, - void *ptr); -QJS_HIDE JSString *js_alloc_string(LEPUSContext *ctx, int max_len, - int is_wide_char); -QJS_HIDE int JS_InitAtoms(LEPUSRuntime *rt); -QJS_HIDE int JS_isConcatSpreadable(LEPUSContext *ctx, LEPUSValueConst obj); -typedef struct StringBuffer { - LEPUSContext *ctx; - JSString *str; - int len; - int size; - int is_wide_char; - int error_status; -} StringBuffer; -QJS_HIDE int string_buffer_write8(StringBuffer *s, const uint8_t *p, int len); -QJS_HIDE int string_buffer_concat(StringBuffer *s, const JSString *p, - uint32_t from, uint32_t to); -QJS_HIDE int string_buffer_putc8(StringBuffer *s, uint32_t c); -QJS_HIDE int string_buffer_putc16(StringBuffer *s, uint32_t c); -QJS_HIDE int string_getc(const JSString *p, int *pidx); -QJS_HIDE BOOL test_final_sigma(JSString *p, int sigma_pos); -QJS_HIDE int string_buffer_putc(StringBuffer *s, uint32_t c); -QJS_HIDE int string_buffer_fill(StringBuffer *s, int c, int count); -QJS_HIDE int seal_template_obj_GC(LEPUSContext *ctx, LEPUSValueConst obj); -struct BCReaderState; -QJS_HIDE LEPUSValue JS_ReadError_GC(BCReaderState *s); -QJS_HIDE LEPUSValue JS_ReadRegExp(BCReaderState *s); -QJS_HIDE LEPUSValue JS_ReadMap_GC(BCReaderState *s); -QJS_HIDE LEPUSValue js_typed_array_constructor_GC(LEPUSContext *ctx, - LEPUSValueConst new_target, - int argc, - LEPUSValueConst *argv, - int classid); -QJS_HIDE LEPUSValue JS_ReadObjectRec(BCReaderState *s); -QJS_HIDE LEPUSValue JS_ReadRegExp_GC(BCReaderState *s); -QJS_HIDE JSAtom __JS_NewAtom(LEPUSRuntime *rt, JSString *str, int atom_type); -QJS_HIDE int js_string_compare(LEPUSContext *ctx, const JSString *p1, - const JSString *p2); - -QJS_HIDE JSAtom JS_NewAtomStr(LEPUSContext *ctx, JSString *p); -QJS_HIDE BOOL JS_AtomIsArrayIndex(LEPUSContext *ctx, uint32_t *pval, - JSAtom atom); - -QJS_HIDE JSAtom js_get_atom_index(LEPUSRuntime *rt, JSAtomStruct *p); -QJS_HIDE LEPUSModuleDef *js_new_module_def(LEPUSContext *ctx, JSAtom name); -struct JSFunctionDef; -QJS_HIDE int resolve_labels(LEPUSContext *ctx, JSFunctionDef *s); -QJS_HIDE int resolve_variables(LEPUSContext *ctx, JSFunctionDef *s); -QJS_HIDE int new_label_fd(JSFunctionDef *fd, int label); -struct JSParseState; -QJS_HIDE int js_parse_unary_GC(JSParseState *s, int parse_flags); -QJS_HIDE int js_parse_array_literal(JSParseState *s); -QJS_HIDE int js_parse_cond_expr(JSParseState *s, int parse_flags); -QJS_HIDE int js_parse_assign_expr(JSParseState *s, int parse_flags); -QJS_HIDE int js_parse_expr(JSParseState *s); -QJS_HIDE int js_parse_expr2(JSParseState *s, int parse_flags); -QJS_HIDE __exception int next_token(JSParseState *s); -struct JSToken; -QJS_HIDE int js_parse_string(JSParseState *s, int sep, BOOL do_throw, - const uint8_t *p, JSToken *token, - const uint8_t **pp); - -QJS_HIDE int cpool_add(JSParseState *s, LEPUSValue val); -QJS_HIDE int emit_push_const(JSParseState *s, LEPUSValueConst val, - BOOL as_atom); -QJS_HIDE void emit_op(JSParseState *s, uint8_t val); -QJS_HIDE int emit_label(JSParseState *s, int label); -QJS_HIDE void emit_return(JSParseState *s, BOOL hasval); -QJS_HIDE int emit_goto(JSParseState *s, int opcode, int label); -QJS_HIDE int emit_break(JSParseState *s, JSAtom name, int is_cont); -QJS_HIDE void optional_chain_test(JSParseState *s, - int *poptional_chaining_label, - int drop_count); -QJS_HIDE int js_parse_template_part(JSParseState *s, const uint8_t *p); -QJS_HIDE int js_parse_template(JSParseState *s, int call, int *argc); -struct JSParsePos; -QJS_HIDE int js_parse_get_pos(JSParseState *s, JSParsePos *sp); -QJS_HIDE int js_parse_seek_token(JSParseState *s, const JSParsePos *sp); -QJS_HIDE int js_parse_regexp(JSParseState *s); -QJS_HIDE int js_parse_skip_parens_token(JSParseState *s, int *pbits, - BOOL no_line_terminator, - BOOL *has_ellipsis = nullptr); -QJS_HIDE int js_resize_array(LEPUSContext *ctx, void **parray, int elem_size, - int *psize, int *pcount, int new_count); -QJS_HIDE JSExportEntry *find_export_entry(LEPUSContext *ctx, LEPUSModuleDef *m, - JSAtom export_name); - -QJS_HIDE JSExportEntry *add_export_entry(JSParseState *s, LEPUSModuleDef *m, - JSAtom local_name, JSAtom export_name, - JSExportTypeEnum export_type); -QJS_HIDE void set_object_name_computed(JSParseState *s); -QJS_HIDE BOOL set_object_name(JSParseState *s, JSAtom name); -QJS_HIDE int add_scope_var(LEPUSContext *ctx, JSFunctionDef *fd, JSAtom name, - JSVarKindEnum var_kind); -QJS_HIDE int add_var(LEPUSContext *ctx, JSFunctionDef *fd, JSAtom name); -typedef struct JSHoistedDef { // called JSGlobalVar in latest version - int cpool_idx; /* -1 means variable global definition */ - uint8_t force_init : 1; /* initialize to undefined */ - uint8_t is_lexical : 1; /* global let/const definition */ - uint8_t is_const : 1; /* const definition */ - int var_idx; /* function object index if cpool_idx >= 0 */ - int scope_level; /* scope of definition */ - JSAtom var_name; /* variable name if cpool_idx < 0 */ -} JSHoistedDef; -QJS_HIDE JSHoistedDef *add_hoisted_def(LEPUSContext *ctx, JSFunctionDef *s, - int cpool_idx, JSAtom name, int var_idx, - BOOL is_lexical); -QJS_HIDE int peek_token(JSParseState *s, BOOL no_line_terminator); -QJS_HIDE int push_scope(JSParseState *s); -QJS_HIDE int find_private_class_field(LEPUSContext *ctx, JSFunctionDef *fd, - JSAtom name, int scope_level); -typedef enum JSParseFunctionEnum { - JS_PARSE_FUNC_STATEMENT, - JS_PARSE_FUNC_VAR, - JS_PARSE_FUNC_EXPR, - JS_PARSE_FUNC_ARROW, - JS_PARSE_FUNC_GETTER, - JS_PARSE_FUNC_SETTER, - JS_PARSE_FUNC_METHOD, - JS_PARSE_FUNC_CLASS_CONSTRUCTOR, - JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR, -} JSParseFunctionEnum; -typedef enum JSParseExportEnum { - JS_PARSE_EXPORT_NONE, - JS_PARSE_EXPORT_NAMED, - JS_PARSE_EXPORT_DEFAULT, -} JSParseExportEnum; -typedef enum { - JS_VAR_DEF_WITH, - JS_VAR_DEF_LET, - JS_VAR_DEF_CONST, - JS_VAR_DEF_FUNCTION_DECL, /* function declaration */ - JS_VAR_DEF_NEW_FUNCTION_DECL, /* async/generator function declaration */ - JS_VAR_DEF_CATCH, - JS_VAR_DEF_VAR, -} JSVarDefEnum; -QJS_HIDE int js_parse_function_decl2_GC( - JSParseState *s, JSParseFunctionEnum func_type, - JSFunctionKindEnum func_kind, JSAtom func_name, const uint8_t *ptr, - int function_line_num, JSParseExportEnum export_flag, JSFunctionDef **pfd); -QJS_HIDE int js_parse_class_default_ctor(JSParseState *s, BOOL has_super, - JSFunctionDef **pfd); - -QJS_HIDE int define_var_GC(JSParseState *s, JSFunctionDef *fd, JSAtom name, - JSVarDefEnum var_def_type); - -QJS_HIDE uint64_t compute_column(JSParseState *s, BOOL is_get_var); -QJS_HIDE BOOL js_is_live_code(JSParseState *s); -QJS_HIDE int js_parse_directives(JSParseState *s); -QJS_HIDE int add_closure_var(LEPUSContext *ctx, JSFunctionDef *s, BOOL is_local, - BOOL is_arg, int var_idx, JSAtom var_name, - BOOL is_const, BOOL is_lexical, - JSVarKindEnum var_kind); -QJS_HIDE BOOL is_var_in_arg_scope(LEPUSContext *ctx, const JSVarDef *vd); -QJS_HIDE LEPUSValue js_create_function(LEPUSContext *ctx, JSFunctionDef *fd); -QJS_HIDE void skip_shebang(JSParseState *s); -QJS_HIDE const char *JS_AtomGetStrRT(LEPUSRuntime *rt, char *buf, int buf_size, - JSAtom atom); -QJS_HIDE const char *JS_AtomGetStr(LEPUSContext *ctx, char *buf, int buf_size, - JSAtom atom); -QJS_HIDE int js_parse_error_reserved_identifier(JSParseState *s); -QJS_HIDE BOOL token_is_pseudo_keyword(JSParseState *s, JSAtom atom); -QJS_HIDE BOOL token_is_ident(int tok); -QJS_HIDE int js_parse_expect(JSParseState *s, int tok); -QJS_HIDE int js_parse_object_literal_GC(JSParseState *s); -QJS_HIDE int js_parse_expr_paren(JSParseState *s); -QJS_HIDE __exception JSAtom js_parse_from_clause(JSParseState *s); -QJS_HIDE int add_req_module_entry(LEPUSContext *ctx, LEPUSModuleDef *m, - JSAtom module_name); -QJS_HIDE int js_parse_expect_semi(JSParseState *s); -QJS_HIDE __exception int js_parse_export(JSParseState *s); -QJS_HIDE __exception int js_parse_import(JSParseState *s); -QJS_HIDE LEPUSValue JS_CallFree_GC(LEPUSContext *ctx, LEPUSValue func_obj, - LEPUSValueConst this_obj, int argc, - LEPUSValueConst *argv); -QJS_HIDE int add_star_export_entry(LEPUSContext *ctx, LEPUSModuleDef *m, - int req_module_idx); -QJS_HIDE int js_define_var(JSParseState *s, JSAtom name, int tok); -QJS_HIDE int get_prev_opcode(JSFunctionDef *fd); -QJS_HIDE int update_label(JSFunctionDef *s, int label, int delta); -QJS_HIDE int get_lvalue(JSParseState *s, int *popcode, int *pscope, - JSAtom *pname, int *plabel, int *pdepth, BOOL keep, - int tok); -typedef enum { - PUT_LVALUE_NOKEEP, /* [depth] v -> */ - PUT_LVALUE_NOKEEP_DEPTH, /* [depth] v -> , keep depth (currently - just disable optimizations) */ - PUT_LVALUE_KEEP_TOP, /* [depth] v -> v */ - PUT_LVALUE_KEEP_SECOND, /* [depth] v0 v -> v0 */ - PUT_LVALUE_NOKEEP_BOTTOM, /* v [depth] -> */ -} PutLValueEnum; -QJS_HIDE void put_lvalue(JSParseState *s, int opcode, int scope, JSAtom name, - int label, PutLValueEnum special, BOOL is_let); -QJS_HIDE JSAtom js_parse_destructing_var(JSParseState *s, int tok, int is_arg); -QJS_HIDE int js_parse_check_duplicate_parameter(JSParseState *s, JSAtom name); -QJS_HIDE int js_parse_destructing_element_GC(JSParseState *s, int tok, - int is_arg, int hasval, - int has_ellipsis, - BOOL allow_initializer); -QJS_HIDE int js_parse_var(JSParseState *s, int parse_flags, int tok, - BOOL export_flag); -QJS_HIDE LEPUSValue js_evaluate_module(LEPUSContext *ctx, LEPUSModuleDef *m); -QJS_HIDE JSVarRef *js_create_module_var(LEPUSContext *ctx, BOOL is_lexical); -QJS_HIDE int js_create_module_function(LEPUSContext *ctx, LEPUSModuleDef *m); -QJS_HIDE void set_value_gc(LEPUSContext *ctx, LEPUSValue *pval, - LEPUSValue new_val); -QJS_HIDE int JS_DefineAutoInitProperty_GC( - LEPUSContext *ctx, LEPUSValueConst this_obj, JSAtom prop, - LEPUSValue (*init_func)(LEPUSContext *ctx, LEPUSObject *obj, JSAtom prop, - void *opaque), - void *opaque, int flags); -QJS_HIDE int js_link_module(LEPUSContext *ctx, LEPUSModuleDef *m); -QJS_HIDE int skip_spaces(const char *pc); -int JS_DefineObjectName_GC(LEPUSContext *ctx, LEPUSValueConst obj, JSAtom name, - int flags); -QJS_HIDE LEPUSValue js_atod(LEPUSContext *ctx, const char *str, const char **pp, - int radix, int flags); -QJS_HIDE int js_resolve_module(LEPUSContext *ctx, LEPUSModuleDef *m); -QJS_HIDE void close_scopes(JSParseState *s, int scope, int scope_stop); -QJS_HIDE JSFunctionDef *js_new_function_def_GC(LEPUSContext *ctx, - JSFunctionDef *parent, - BOOL is_eval, BOOL is_func_expr, - const char *filename, - int line_num); -QJS_HIDE void pop_scope(JSParseState *s); -QJS_HIDE JSHoistedDef *find_hoisted_def(JSFunctionDef *fd, JSAtom name); -QJS_HIDE BOOL is_child_scope(LEPUSContext *ctx, JSFunctionDef *fd, int scope, - int parent_scope); -QJS_HIDE int find_lexical_decl(LEPUSContext *ctx, JSFunctionDef *fd, - JSAtom name, int scope_idx, - BOOL check_catch_var); -QJS_HIDE int find_arg(LEPUSContext *ctx, JSFunctionDef *fd, JSAtom name); -QJS_HIDE int find_var(LEPUSContext *ctx, JSFunctionDef *fd, JSAtom name); -QJS_HIDE int js_parse_class(JSParseState *s, BOOL is_class_expr, - JSParseExportEnum export_flag); -QJS_HIDE int js_parse_left_hand_side_expr_GC(JSParseState *s); -QJS_HIDE int js_parse_property_name_GC(JSParseState *s, JSAtom *pname, - BOOL allow_method, BOOL allow_var, - BOOL allow_private); -QJS_HIDE int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd, - JSAtom func_name); -QJS_HIDE int is_let(JSParseState *s, int decl_mask); -QJS_HIDE int __attribute__((format(printf, 2, 3))) QJS_HIDE js_parse_error( - JSParseState *s, const char *fmt, ...); -QJS_HIDE int find_var_in_child_scope(LEPUSContext *ctx, JSFunctionDef *fd, - JSAtom name, int scope_level); -QJS_HIDE int add_arg(LEPUSContext *ctx, JSFunctionDef *fd, JSAtom name); -#ifndef NO_QUICKJS_COMPILER -typedef struct JSParseState { - LEPUSContext *ctx; - int last_line_num; /* line number of last token */ - int line_num; /* line number of current offset */ - const char *filename; - JSToken token; - BOOL got_lf; /* true if got line feed before the current token */ - const uint8_t *last_ptr; - const uint8_t *buf_ptr; - const uint8_t *buf_end; - // - int debugger_last_line_num; - const uint8_t *line_begin_ptr; - const uint8_t *last_line_begin_ptr; - const uint8_t *last_emit_ptr; - const uint8_t *func_call_ptr; - const uint8_t *utf8_parse_front; - int utf8_adapte_size; - int func_call_adapte_size; - int last_utf8_adapte_size; - const uint8_t *last_last_ptr; - // - /* current function code */ - JSFunctionDef *cur_func; - BOOL is_module; /* parsing a module */ - BOOL allow_html_comments; -} JSParseState; -#endif -QJS_HIDE LEPUSValue js_finalizationRegistry_unregister(LEPUSContext *ctx, - LEPUSValueConst this_val, - int argc, - LEPUSValueConst *argv); -QJS_HIDE LEPUSValue js_finalizationRegistry_unregister_gc( - LEPUSContext *ctx, LEPUSValueConst this_val, int argc, - LEPUSValueConst *argv); - -QJS_HIDE LEPUSValue js_finalizationRegistry_register(LEPUSContext *ctx, - LEPUSValueConst this_val, - int argc, - LEPUSValueConst *argv); -QJS_HIDE LEPUSValue -js_finalizationRegistry_register_gc(LEPUSContext *ctx, LEPUSValueConst this_val, - int argc, LEPUSValueConst *argv); - -QJS_HIDE void AddReferenceRecord(LEPUSContext *ctx, LEPUSObject *obj, - LEPUSValue val); -QJS_HIDE const char *generate_json_str(LEPUSContext *ctx, LEPUSValue obj, - size_t &str_len, const char ***str_arr, - size_t &ts, size_t &cs); -typedef union json_val_uni { - int64_t i64; - double f64; - const char *str; - size_t ofs; - LEPUSValue bigf; // for JSON.stringify bigfloat - LEPUSValue num; // for JSON.parse number -} json_val_uni; - -struct json_val { - uint64_t tag; /**< type, subtype and length */ - json_val_uni uni; /**< payload */ -}; -QJS_HIDE int make_json_val_incr(LEPUSContext *ctx, size_t &alc_len, - json_val **val_hdr, json_val **val, - json_val **ctn, json_val **val_end); -QJS_HIDE uint8_t *json_val_write_format(LEPUSContext *ctx, json_val *root, - const char *gap_str); -QJS_HIDE uint8_t *json_val_write(LEPUSContext *ctx, json_val *root); -QJS_HIDE void parse_json_space(JSParseState *s, const uint8_t **cur); -QJS_HIDE bool read_string(JSParseState *s, uint8_t **ptr, json_val *val); -QJS_HIDE json_val *json_parse_value(JSParseState *s, size_t dat_len); -QJS_HIDE void js_parse_init(LEPUSContext *ctx, JSParseState *s, - const char *input, size_t input_len, - const char *filename); -QJS_HIDE LEPUSValue JS_ParseJSONOPT(LEPUSContext *ctx, const char *buf, - size_t buf_len, const char *filename); -QJS_HIDE LEPUSObject *get_typed_array(LEPUSContext *ctx, - LEPUSValueConst this_val, - int is_dataview); -QJS_HIDE BOOL typed_array_is_detached(LEPUSContext *ctx, LEPUSObject *p); -QJS_HIDE LEPUSValue js_dataview_getValue(LEPUSContext *ctx, - LEPUSValueConst this_obj, int argc, - LEPUSValueConst *argv, int class_id); -QJS_HIDE LEPUSValue js_dataview_setValue(LEPUSContext *ctx, - LEPUSValueConst this_obj, int argc, - LEPUSValueConst *argv, int class_id); -QJS_HIDE JSArrayBuffer *js_get_array_buffer(LEPUSContext *ctx, - LEPUSValueConst obj); -QJS_HIDE LEPUSValue js_create_from_ctor_GC(LEPUSContext *ctx, - LEPUSValueConst ctor, int class_id); -QJS_HIDE LEPUSValue js_dataview_constructor(LEPUSContext *ctx, - LEPUSValueConst new_target, - int argc, LEPUSValueConst *argv); -QJS_HIDE LEPUSValue js_typed_array_get_buffer(LEPUSContext *ctx, - LEPUSValueConst this_val, - int is_dataview); -QJS_HIDE LEPUSValue js_typed_array_get_length(LEPUSContext *ctx, - LEPUSValueConst this_val); -QJS_HIDE LEPUSValue js_typed_array_get_byteLength(LEPUSContext *ctx, - LEPUSValueConst this_val, - int is_dataview); -QJS_HIDE LEPUSValue js_typed_array_get_byteOffset(LEPUSContext *ctx, - LEPUSValueConst this_val, - int is_dataview); -const LEPUSCFunctionListEntry js_dataview_proto_funcs[] = { - LEPUS_CGETSET_MAGIC_DEF("buffer", js_typed_array_get_buffer, NULL, 1), - LEPUS_CGETSET_MAGIC_DEF("byteLength", js_typed_array_get_byteLength, NULL, - 1), - LEPUS_CGETSET_MAGIC_DEF("byteOffset", js_typed_array_get_byteOffset, NULL, - 1), - LEPUS_CFUNC_MAGIC_DEF("getInt8", 1, js_dataview_getValue, - JS_CLASS_INT8_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("getUint8", 1, js_dataview_getValue, - JS_CLASS_UINT8_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("getInt16", 1, js_dataview_getValue, - JS_CLASS_INT16_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("getUint16", 1, js_dataview_getValue, - JS_CLASS_UINT16_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("getInt32", 1, js_dataview_getValue, - JS_CLASS_INT32_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("getUint32", 1, js_dataview_getValue, - JS_CLASS_UINT32_ARRAY), -#ifdef CONFIG_BIGNUM - LEPUS_CFUNC_MAGIC_DEF("getBigInt64", 1, js_dataview_getValue, - JS_CLASS_BIG_INT64_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("getBigUint64", 1, js_dataview_getValue, - JS_CLASS_BIG_UINT64_ARRAY), -#endif - LEPUS_CFUNC_MAGIC_DEF("getFloat32", 1, js_dataview_getValue, - JS_CLASS_FLOAT32_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("getFloat64", 1, js_dataview_getValue, - JS_CLASS_FLOAT64_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("setInt8", 2, js_dataview_setValue, - JS_CLASS_INT8_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("setUint8", 2, js_dataview_setValue, - JS_CLASS_UINT8_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("setInt16", 2, js_dataview_setValue, - JS_CLASS_INT16_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("setUint16", 2, js_dataview_setValue, - JS_CLASS_UINT16_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("setInt32", 2, js_dataview_setValue, - JS_CLASS_INT32_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("setUint32", 2, js_dataview_setValue, - JS_CLASS_UINT32_ARRAY), -#ifdef CONFIG_BIGNUM - LEPUS_CFUNC_MAGIC_DEF("setBigInt64", 2, js_dataview_setValue, - JS_CLASS_BIG_INT64_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("setBigUint64", 2, js_dataview_setValue, - JS_CLASS_BIG_UINT64_ARRAY), -#endif - LEPUS_CFUNC_MAGIC_DEF("setFloat32", 2, js_dataview_setValue, - JS_CLASS_FLOAT32_ARRAY), - LEPUS_CFUNC_MAGIC_DEF("setFloat64", 2, js_dataview_setValue, - JS_CLASS_FLOAT64_ARRAY), - LEPUS_PROP_STRING_DEF("[Symbol.toStringTag]", "DataView", - LEPUS_PROP_CONFIGURABLE), -}; -QJS_HIDE void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags); -QJS_HIDE LEPUSValue js_closure2(LEPUSContext *ctx, LEPUSValue func_obj, - LEPUSFunctionBytecode *b, - JSVarRef **cur_var_refs, LEPUSStackFrame *sf); -QJS_HIDE void js_random_init(LEPUSContext *ctx); -QJS_HIDE LEPUSValue js_math_random(LEPUSContext *ctx, LEPUSValueConst this_val, - int argc, LEPUSValueConst *argv); -QJS_HIDE int getTimezoneOffset(int64_t time); -QJS_HIDE int JS_SetPrototypeInternal_GC(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst proto_val, - BOOL throw_flag); -QJS_HIDE LEPUSValue js_reflect_setPrototypeOf(LEPUSContext *ctx, - LEPUSValueConst this_val, - int argc, LEPUSValueConst *argv); -QJS_HIDE LEPUSValue js_reflect_has(LEPUSContext *ctx, LEPUSValueConst this_val, - int argc, LEPUSValueConst *argv); -QJS_HIDE LEPUSValue js_reflect_set(LEPUSContext *ctx, LEPUSValueConst this_val, - int argc, LEPUSValueConst *argv); -QJS_HIDE LEPUSValue js_reflect_get(LEPUSContext *ctx, LEPUSValueConst this_val, - int argc, LEPUSValueConst *argv); -QJS_HIDE LEPUSValue js_reflect_deleteProperty(LEPUSContext *ctx, - LEPUSValueConst this_val, - int argc, LEPUSValueConst *argv); -QJS_HIDE int JS_SetPropertyGeneric_GC(LEPUSContext *ctx, LEPUSObject *p, - JSAtom prop, LEPUSValue val, - LEPUSValueConst this_obj, int flags); -QJS_HIDE void js_shape_hash_unlink(LEPUSRuntime *rt, JSShape *sh); -QJS_HIDE void js_shape_hash_link(LEPUSRuntime *rt, JSShape *sh); -QJS_HIDE int resize_shape_hash(LEPUSRuntime *rt, int new_shape_hash_bits); -QJS_HIDE int resize_properties(LEPUSContext *ctx, JSShape **psh, LEPUSObject *p, - uint32_t count); -QJS_HIDE BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size); -QJS_HIDE void build_backtrace_frame(LEPUSContext *ctx, LEPUSStackFrame *sf, - DynBuf *dbuf, const uint8_t *cur_pc, - BOOL is_async, BOOL is_debug_mode, - LEPUSValueConst error_obj); -QJS_HIDE void get_backtrace(LEPUSContext *ctx, DynBuf *dbuf, BOOL is_debug_mode, - LEPUSValueConst error_obj, const uint8_t *cur_pc, - int backtrace_flags); -QJS_HIDE LEPUSValue JS_GetIterator(LEPUSContext *ctx, LEPUSValueConst obj, - BOOL is_async); -QJS_HIDE LEPUSValue JS_GetIterator2(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSValueConst method); -QJS_HIDE LEPUSValue JS_IteratorNext2(LEPUSContext *ctx, - LEPUSValueConst enum_obj, - LEPUSValueConst method, int argc, - LEPUSValueConst *argv, int *pdone); -QJS_HIDE LEPUSValue JS_IteratorNext(LEPUSContext *ctx, LEPUSValueConst enum_obj, - LEPUSValueConst method, int argc, - LEPUSValueConst *argv, BOOL *pdone); -QJS_HIDE JSShapeProperty *find_own_property1(LEPUSObject *p, JSAtom atom); -QJS_HIDE LEPUSValue JS_ThrowError(LEPUSContext *ctx, JSErrorEnum error_num, - const char *fmt, va_list ap); -QJS_HIDE int __attribute__((format(printf, 3, 4))) -JS_ThrowTypeErrorOrFalse(LEPUSContext *ctx, int flags, const char *fmt, ...); -QJS_HIDE int __attribute__((format(printf, 2, 3))) QJS_HIDE js_throw_URIError( - LEPUSContext *ctx, const char *fmt, ...); -QJS_HIDE void *LEPUS_GetOpaque2(LEPUSContext *ctx, LEPUSValueConst obj, - LEPUSClassID class_id); -QJS_HIDE JSRegExp *js_get_regexp(LEPUSContext *ctx, LEPUSValueConst obj, - BOOL throw_error); -QJS_HIDE LEPUSValue __attribute__((format(printf, 3, 4))) -__JS_ThrowTypeErrorAtom(LEPUSContext *ctx, JSAtom atom, const char *fmt, ...); -QJS_HIDE LEPUSValue JS_ThrowTypeErrorPrivateNotFound(LEPUSContext *ctx, - JSAtom atom); -typedef struct BlockEnv { - struct BlockEnv *prev; - JSAtom label_name; /* JS_ATOM_NULL if none */ - int label_break; /* -1 if none */ - int label_cont; /* -1 if none */ - int drop_count; /* number of stack elements to drop */ - int label_finally; /* -1 if none */ - int scope_level; - int has_iterator; -} BlockEnv; - -typedef struct RelocEntry { - struct RelocEntry *next; - uint32_t addr; /* address to patch */ - int size; /* address size: 1, 2 or 4 bytes */ -} RelocEntry; - -typedef struct JumpSlot { - int op; - int size; - int pos; - int label; -} JumpSlot; - -typedef struct LabelSlot { - int ref_count; - int pos; /* phase 1 address, -1 means not resolved yet */ - int pos2; /* phase 2 address, -1 means not resolved yet */ - int addr; /* phase 3 address, -1 means not resolved yet */ - RelocEntry *first_reloc; -} LabelSlot; - -typedef struct LineNumberSlot { - uint32_t pc; - // - uint64_t line_num; - // -} LineNumberSlot; - -typedef struct JSFunctionDef { - LEPUSContext *ctx; - struct JSFunctionDef *parent; - int parent_cpool_idx; /* index in the constant pool of the parent - or -1 if none */ - int parent_scope_level; /* scope level in parent at point of definition */ - struct list_head child_list; /* list of JSFunctionDef.link */ - struct list_head link; - - BOOL is_eval; /* TRUE if eval code */ - int eval_type; /* only valid if is_eval = TRUE */ - BOOL is_global_var; /* TRUE if variables are not defined locally: - eval global, eval module or non strict eval */ - BOOL is_func_expr; /* TRUE if function expression */ - BOOL has_home_object; /* TRUE if the home object is available */ - BOOL has_prototype; /* true if a prototype field is necessary */ - BOOL has_simple_parameter_list; - BOOL has_parameter_expressions; /* if true, an argument scope is created */ - BOOL has_use_strict; /* to reject directive in special cases */ - BOOL has_eval_call; /* true if the function contains a call to eval() */ - BOOL has_arguments_binding; /* true if the 'arguments' binding is - available in the function */ - BOOL has_this_binding; /* true if the 'this' and new.target binding are - available in the function */ - BOOL new_target_allowed; /* true if the 'new.target' does not - throw a syntax error */ - BOOL super_call_allowed; /* true if super() is allowed */ - BOOL super_allowed; /* true if super. or super[] is allowed */ - BOOL arguments_allowed; /* true if the 'arguments' identifier is allowed */ - BOOL is_derived_class_constructor; - BOOL in_function_body; - JSFunctionKindEnum func_kind : 8; - JSParseFunctionEnum func_type : 8; - uint8_t js_mode; /* bitmap of JS_MODE_x */ - JSAtom func_name; /* JS_ATOM_NULL if no name */ - - JSVarDef *vars; - int var_size; /* allocated size for vars[] */ - int var_count; - JSVarDef *args; - int arg_size; /* allocated size for args[] */ - int arg_count; /* number of arguments */ - int defined_arg_count; - int var_object_idx; /* -1 if none */ - int arg_var_object_idx; /* -1 if none (var object for the argument scope) */ - int arguments_var_idx; /* -1 if none */ - int arguments_arg_idx; /* argument variable definition in argument scope, -1 - if none */ - int func_var_idx; /* variable containing the current function (-1 - if none, only used if is_func_expr is true) */ - int eval_ret_idx; /* variable containing the return value of the eval, -1 if - none */ - int this_var_idx; /* variable containg the 'this' value, -1 if none */ - int new_target_var_idx; /* variable containg the 'new.target' value, -1 if - none */ - int this_active_func_var_idx; /* variable containg the 'this.active_func' - value, -1 if none */ - int home_object_var_idx; - BOOL need_home_object; - - int scope_level; /* index into fd->scopes if the current lexical scope */ - int scope_first; /* index into vd->vars of first lexically scoped variable */ - int scope_size; /* allocated size of fd->scopes array */ - int scope_count; /* number of entries used in the fd->scopes array */ - JSVarScope *scopes; - JSVarScope def_scope_array[4]; - int body_scope; /* scope of the body of the function or eval */ - - int hoisted_def_count; - int hoisted_def_size; - JSHoistedDef *hoisted_def; - - DynBuf byte_code; - int last_opcode_pos; /* -1 if no last opcode */ - int last_opcode_line_num; - BOOL use_short_opcodes; /* true if short opcodes are used in byte_code */ - - LabelSlot *label_slots; - int label_size; /* allocated size for label_slots[] */ - int label_count; - BlockEnv *top_break; /* break/continue label stack */ - - /* constant pool (strings, functions, numbers) */ - LEPUSValue *cpool; - uint32_t cpool_count; - uint32_t cpool_size; - - /* list of variables in the closure */ - int closure_var_count; - int closure_var_size; - LEPUSClosureVar *closure_var; - - JumpSlot *jump_slots; - int jump_size; - int jump_count; - - LineNumberSlot *line_number_slots; - int line_number_size; - int line_number_count; - // - int64_t line_number_last; - int64_t line_number_last_pc; - // - - /* pc2line table */ - JSAtom filename; - int line_num; -#ifdef ENABLE_QUICKJS_DEBUGGER - int64_t column_num; - LEPUSScriptSource *script; -#endif - DynBuf pc2line; - - CallerStrSlot *caller_slots; - int32_t caller_size; - int32_t caller_count; - int32_t resolve_caller_count; - bool should_add_slot; - - const char *src_start; - char *source; /* raw source, utf-8 encoded */ - int source_len; - - LEPUSModuleDef *module; /* != NULL when parsing a module */ -} JSFunctionDef; - -QJS_HIDE int add_closure_variables(LEPUSContext *ctx, JSFunctionDef *s, - LEPUSFunctionBytecode *b, int scope_idx); -QJS_HIDE int JS_DefinePropertyValueInt64_GC(LEPUSContext *ctx, - LEPUSValueConst this_obj, - int64_t idx, LEPUSValue val, - int flags); -QJS_HIDE LEPUSValue js_error_constructor(LEPUSContext *ctx, - LEPUSValueConst new_target, int argc, - LEPUSValueConst *argv, int magic); - -QJS_HIDE BOOL JS_AtomIsString(LEPUSContext *ctx, JSAtom v); - -QJS_HIDE LEPUSValue JS_NewObjectFromShape(LEPUSContext *, JSShape *, - LEPUSClassID); - -QJS_HIDE LEPUSValue JS_NewObjectFromShape_GC(LEPUSContext *, JSShape *, - LEPUSClassID); - -QJS_HIDE LEPUSFunctionBytecode *JS_GetFunctionBytecode(LEPUSValueConst); -QJS_HIDE JSAtom js_symbol_to_atom(LEPUSContext *, LEPUSValue); -QJS_HIDE LEPUSValueConst JS_GetActiveFunction(LEPUSContext *ctx); -QJS_HIDE LEPUSValue js_array_buffer_get_byteLength(LEPUSContext *, - LEPUSValueConst, int32_t); -#ifndef NO_QUICKJS_COMPILER -// the last two parameters are needed for qjs debugger, default value: false, -// NULL -QJS_HIDE LEPUSValue JS_EvalInternal(LEPUSContext *, LEPUSValue, const char *, - size_t, const char *, int, int, - bool = false, LEPUSStackFrame * = nullptr); -#endif - -LEPUSValue js_array_reduce_gc(LEPUSContext *ctx, LEPUSValueConst this_val, - int argc, LEPUSValueConst *argv, int special); - -LEPUSValue js_array_concat_gc(LEPUSContext *ctx, LEPUSValueConst this_val, - int argc, LEPUSValueConst *argv); -/* Shape support */ -QJS_STATIC inline JSShapeProperty *get_shape_prop(JSShape *sh) { - return sh->prop; -} - -QJS_STATIC inline size_t get_shape_size(size_t hash_size, size_t prop_size) { - return hash_size * sizeof(uint32_t) + sizeof(JSShape) + - prop_size * sizeof(JSShapeProperty); -} - -QJS_STATIC inline JSShape *get_shape_from_alloc(void *sh_alloc, - size_t hash_size) { - return (JSShape *)(void *)((uint32_t *)sh_alloc + hash_size); -} - -QJS_STATIC inline void *get_alloc_from_shape(JSShape *sh) { - return sh->prop_hash_end - ((intptr_t)sh->prop_hash_mask + 1); -} - -QJS_STATIC inline BOOL atom_is_free(const JSAtomStruct *p) { - return (uintptr_t)p & 1; -} - -QJS_STATIC inline BOOL __JS_AtomIsTaggedInt(JSAtom v) { - return (v & JS_ATOM_TAG_INT) != 0; -} - -QJS_STATIC inline JSAtom __JS_AtomFromUInt32(uint32_t v) { - return v | JS_ATOM_TAG_INT; -} - -QJS_STATIC inline uint32_t __JS_AtomToUInt32(JSAtom atom) { - return atom & ~JS_ATOM_TAG_INT; -} - -QJS_HIDE JSAtomKindEnum JS_AtomGetKind(LEPUSContext *, JSAtom); -QJS_HIDE LEPUS_BOOL JS_LepusRefIsArray(LEPUSRuntime *rt, LEPUSValue v); -QJS_HIDE LEPUS_BOOL JS_LepusRefIsTable(LEPUSRuntime *rt, LEPUSValue v); -QJS_HIDE JSShape *js_dup_shape(JSShape *sh); - -typedef struct JSCFunctionDataRecord { - LEPUSCFunctionData *func; - uint8_t length; - uint8_t data_len; - uint16_t magic; - LEPUSValue data[0]; -} JSCFunctionDataRecord; - -typedef struct ValueBuffer { - LEPUSContext *ctx; - LEPUSValue *arr; - LEPUSValue def[4]; - int len; - int size; - int error_status; -} ValueBuffer; - -typedef enum JSPromiseStateEnum { - JS_PROMISE_PENDING, - JS_PROMISE_FULFILLED, - JS_PROMISE_REJECTED, -} JSPromiseStateEnum; - -typedef struct JSPromiseData { - JSPromiseStateEnum promise_state; - /* 0=fulfill, 1=reject, list of JSPromiseReactionData.link */ - struct list_head promise_reactions[2]; - BOOL is_handled; /* Note: only useful to debug */ - LEPUSValue promise_result; -} JSPromiseData; - -typedef struct JSPromiseFunctionDataResolved { - int ref_count; - BOOL already_resolved; -} JSPromiseFunctionDataResolved; - -typedef struct JSPromiseFunctionData { - LEPUSValue promise; - JSPromiseFunctionDataResolved *presolved; -} JSPromiseFunctionData; - -typedef struct JSPromiseReactionData { - struct list_head link; /* not used in promise_reaction_job */ - LEPUSValue resolving_funcs[2]; - LEPUSValue handler; -} JSPromiseReactionData; - -typedef struct ReferenceRecord { - int max_size; - LEPUSValue *references; - int length; -} ReferenceRecord; - -typedef struct RegistryRecord { - struct ReferenceRecord *registra; - struct ReferenceRecord *heldvalue; - struct ReferenceRecord *target; - struct ReferenceRecord *token; - struct JSFinalizationRegistryEntry *entry; - int *idx; -} RegistryRecord; - -typedef struct JSMapRecord { - int ref_count; /* used during enumeration to avoid freeing the record */ - BOOL empty; /* TRUE if the record is deleted */ - struct JSMapState *map; - struct list_head link; - struct list_head hash_link; - LEPUSValue key; - LEPUSValue value; -} JSMapRecord; - -typedef struct ValueSlot { - LEPUSValue val; - JSString *str; - int64_t pos; -} ValueSlot; - -struct array_sort_context { - LEPUSContext *ctx; - int exception; - int has_method; - LEPUSValueConst method; -}; - -typedef struct FinalizerOpaque { - LEPUSContext *ctx; -} FinalizerOpaque; - -/* */ -#define BC_NEW_PREFIX 0x8 -#define VERSION_PLACEHOLDER 0xCAB00000 -#define NEW_DEBUGINFO_FLAG 0x100000000 - -bool JS_IsNewVersion(LEPUSContext *ctx); -bool JS_CheckBytecodeVersion(uint64_t v64); - -QJS_HIDE bool primjs_snapshot_enabled(); - -QJS_HIDE void DeleteCurNode(LEPUSRuntime *rt, void *node, int type); -QJS_HIDE bool CheckValidNode(LEPUSRuntime *rt, void *node, int type); - -// #sec-tointgerorinfinity -inline double DoubleToInteger(double x) { - if (isnan(x) || x == 0.0) return 0; - if (!isfinite(x)) return x; - return ((x > 0) ? floor(x) : ceil(x)) + 0.0; -} - -inline void insert_weakref_record(LEPUSObject *p, - struct WeakRefRecord *record) { - record->next_weak_ref = p->first_weak_ref; - p->first_weak_ref = record; - return; -} - -char *js_strmalloc(const char *s, size_t n); -void AddLepusRefCount(LEPUSContext *ctx); - -class LynxTraceInstance { - public: - using BeginPtr = void *(*)(const char *); - using EndPtr = void (*)(void *); - static auto &GetInstance() { - static LynxTraceInstance instance; - return instance; - } - void InitBeginPtr(BeginPtr begin) { trace_start_ = begin; } - void InitEndPtr(EndPtr end) { trace_end_ = end; } - - auto GetBeginPtr() const { return trace_start_; } - auto GetEndPtr() const { return trace_end_; } - - private: - BeginPtr trace_start_{nullptr}; - EndPtr trace_end_{nullptr}; -}; - -class TraceManager { - public: - explicit TraceManager(const char *name) { - if (auto call_begin = LynxTraceInstance::GetInstance().GetBeginPtr()) { - ptr = call_begin(name); - } - } - - ~TraceManager() { - if (auto call_end = LynxTraceInstance::GetInstance().GetEndPtr()) { - call_end(ptr); - } - } - - private: - void *ptr{nullptr}; -}; - -#define JS_OBJECT_IS_OUTER(obj) (obj->class_id >= JS_CLASS_INIT_COUNT) - -#ifdef ENABLE_QUICKJS_DEBUGGER -#define TRACE_EVENT(name) auto tracer = TraceManager{name}; - -#ifdef ENABLE_COMPATIBLE_MM -#define DEBUGGER_COMPATIBLE_CALL_RET(ctx, name, args...) \ - (ctx->rt->gc_enable) ? (name##_GC(args)) : (name(args)) -#else -#define DEBUGGER_COMPATIBLE_CALL_RET(ctx, name, args...) (name(args)) -#endif /* ENABLE_COMPATIBLE_MM */ - -#else -#define TRACE_EVENT(name) -#define DEBUGGER_COMPATIBLE_CALL_RET -#endif /* ENABLE_QUICKJS_DEBUGGER */ - -int64_t date_now(); - -inline bool json_opt_disabled() { return JSON_OPT_DISABLE & settingsFlag; } -inline bool json_opt_disabled(LEPUSRuntime *rt) { - return rt->settings_option.disable_json_opt; -} -inline bool deepclone_opt_disabled() { - return DEEPCLONE_OPT_DISABLE & settingsFlag; -} - -inline bool deepclone_opt_disabled(LEPUSRuntime *rt) { - return rt->settings_option.disable_deepclone_opt; -} - -inline bool separable_string_disabled() { - return DISABLE_SEPARABLE_STRING & settingsFlag; -} - -inline bool minify_virtual_stack_size_enabled() { - return settingsFlag & MINIFY_STACK_ENABLE; -} - -inline bool separable_string_disabled(LEPUSRuntime *rt) { - return rt->settings_option.disable_separable_string; -} - -inline bool adjust_stacksize_disabled() { - return DISABLE_ADJUST_STACKSIZE & settingsFlag; -} - -inline void js_init_settings_options(LEPUSRuntime *rt) { - rt->settings_option.disable_adjust_stacksize = adjust_stacksize_disabled(); - rt->settings_option.disable_json_opt = json_opt_disabled(); - rt->settings_option.disable_deepclone_opt = deepclone_opt_disabled(); - rt->settings_option.disable_separable_string = separable_string_disabled(); - return; -} - -inline bool js_is_bytecode_function(LEPUSValue obj) { - return (LEPUS_VALUE_IS_OBJECT(obj)) && - (LEPUS_VALUE_GET_OBJ(obj)->class_id == JS_CLASS_BYTECODE_FUNCTION); -} - -bool emit_name_str(JSParseState *s, const uint8_t *start, const uint8_t *end); -void get_caller_string(JSFunctionDef *s); - -#endif // SRC_INTERPRETER_QUICKJS_INCLUDE_QUICKJS_INNER_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs-opcode.h b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs-opcode.h deleted file mode 100644 index 871b32af..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs-opcode.h +++ /dev/null @@ -1,385 +0,0 @@ -/* - * QuickJS opcode definitions - * - * Copyright (c) 2017-2018 Fabrice Bellard - * Copyright (c) 2017-2018 Charlie Gordon - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. -// -// clang-format off -#ifdef FMT -FMT(none) -FMT(none_int) -FMT(none_loc) -FMT(none_arg) -FMT(none_var_ref) -FMT(u8) -FMT(i8) -FMT(loc8) -FMT(const8) -FMT(label8) -FMT(u16) -FMT(i16) -FMT(label16) -FMT(npop) -FMT(npopx) -FMT(loc) -FMT(arg) -FMT(var_ref) -FMT(u32) -FMT(i32) -FMT(const) -FMT(label) -FMT(atom) -FMT(atom_u8) -FMT(atom_u16) -FMT(atom_label_u8) -FMT(atom_label_u16) -FMT(label_u16) -// -FMT(u64) -// -#undef FMT -#endif /* FMT */ - -#ifdef DEF - -#ifndef def -#define def(id, size, n_pop, n_push, f) DEF(id, size, n_pop, n_push, f) -#endif - -DEF(invalid, 1, 0, 0, none) /* never emitted */ - -/* push values */ -DEF(push_i32, 5, 0, 1, i32) -DEF(push_const, 5, 0, 1, const) -DEF(fclosure, 5, 0, 1, const) /* must follow push_const */ -DEF(push_atom_value, 5, 0, 1, atom) -DEF(private_symbol, 5, 0, 1, atom) -DEF(undefined, 1, 0, 1, none) -DEF(null, 1, 0, 1, none) -DEF(push_this, 1, 0, 1, none) /* only used at the start of a function */ -DEF(push_false, 1, 0, 1, none) -DEF(push_true, 1, 0, 1, none) -DEF(object, 1, 0, 1, none) -DEF(special_object, 2, 0, 1, u8) /* only used at the start of a function */ -DEF(rest, 3, 0, 1, u16) /* only used at the start of a function */ - -DEF(drop, 1, 1, 0, none) /* a -> */ -DEF(nip, 1, 2, 1, none) /* a b -> b */ -DEF(nip1, 1, 3, 2, none) /* a b c -> b c */ -DEF(dup, 1, 1, 2, none) /* a -> a a */ -DEF(dup1, 1, 2, 3, none) /* a b -> a a b */ -DEF(dup2, 1, 2, 4, none) /* a b -> a b a b */ -DEF(dup3, 1, 3, 6, none) /* a b c -> a b c a b c */ -DEF(insert2, 1, 2, 3, none) /* obj a -> a obj a (dup_x1) */ -DEF(insert3, 1, 3, 4, none) /* obj prop a -> a obj prop a (dup_x2) */ -DEF(insert4, 1, 4, 5, none) /* this obj prop a -> a this obj prop a */ -DEF(perm3, 1, 3, 3, none) /* obj a b -> a obj b */ -DEF(perm4, 1, 4, 4, none) /* obj prop a b -> a obj prop b */ -DEF(perm5, 1, 5, 5, none) /* this obj prop a b -> a this obj prop b */ -DEF(swap, 1, 2, 2, none) /* a b -> b a */ -DEF(swap2, 1, 4, 4, none) /* a b c d -> c d a b */ -DEF(rot3l, 1, 3, 3, none) /* x a b -> a b x */ -DEF(rot3r, 1, 3, 3, none) /* a b x -> x a b */ -DEF(rot4l, 1, 4, 4, none) /* x a b c -> a b c x */ -DEF(rot5l, 1, 5, 5, none) /* x a b c d -> a b c d x */ - -DEF(call_constructor, 3, 2, 1, - npop) /* func new.target args -> ret. arguments are not counted in n_pop */ -DEF(call, 3, 1, 1, npop) /* arguments are not counted in n_pop */ -DEF(tail_call, 3, 1, 0, npop) /* arguments are not counted in n_pop */ -DEF(call_method, 3, 2, 1, npop) /* arguments are not counted in n_pop */ -DEF(tail_call_method, 3, 2, 0, npop) /* arguments are not counted in n_pop */ -DEF(array_from, 3, 0, 1, npop) /* arguments are not counted in n_pop */ -DEF(apply, 3, 3, 1, u16) -DEF(return, 1, 1, 0, none) -DEF(return_undef, 1, 0, 0, none) -DEF(check_ctor_return, 1, 1, 2, none) -DEF(check_ctor, 1, 0, 0, none) -DEF(check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */ -DEF(add_brand, 1, 2, 0, none) /* this_obj home_obj -> */ -DEF(return_async, 1, 1, 0, none) -DEF(throw, 1, 1, 0, none) -DEF(throw_var, 6, 0, 0, atom_u8) -DEF(eval, 3, 1, 1, u16) -DEF(regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a - bytecode string */ -DEF(get_super_ctor, 1, 1, 1, none) -DEF(get_super, 1, 1, 1, none) -DEF(import, 1, 1, 1, none) /* dynamic module import */ - -DEF(check_var, 5, 0, 1, atom) /* check if a variable exists */ - -DEF(get_var_undef, 5, 0, 1, - atom) /* push undefined if the variable does not exist */ -DEF(get_var, 5, 0, 1, - atom) /* throw an exception if the variable does not exist */ - -DEF(put_var, 5, 1, 0, atom) /* must come after get_var */ -DEF(put_var_init, 5, 1, 0, atom) /* must come after put_var. Used to initialize - a global lexical variable */ -DEF(put_var_strict, 5, 2, 0, atom) /* for strict mode variable write */ - -DEF(get_ref_value, 1, 2, 3, none) -DEF(put_ref_value, 1, 3, 0, none) - -DEF(define_var, 6, 0, 0, atom_u8) -DEF(check_define_var, 6, 0, 0, atom_u8) -DEF(define_func, 6, 1, 0, atom_u8) - -DEF(get_field, 5, 1, 1, atom) -DEF(get_field2, 5, 1, 2, atom) -DEF(put_field, 5, 2, 0, atom) - -DEF(get_private_field, 1, 2, 1, none) /* obj prop -> value */ -DEF(put_private_field, 1, 3, 0, none) /* obj value prop -> */ -DEF(define_private_field, 1, 3, 1, none) /* obj prop value -> obj */ -DEF(get_array_el, 1, 2, 1, none) -DEF(get_array_el2, 1, 2, 2, none) /* obj prop -> obj value */ -DEF(put_array_el, 1, 3, 0, none) -DEF(get_super_value, 1, 3, 1, none) /* this obj prop -> value */ -DEF(put_super_value, 1, 4, 0, none) /* this obj prop value -> */ -DEF(define_field, 5, 2, 1, atom) -DEF(set_name, 5, 1, 1, atom) -DEF(set_name_computed, 1, 2, 2, none) -DEF(set_proto, 1, 2, 1, none) -DEF(set_home_object, 1, 2, 2, none) -DEF(define_array_el, 1, 3, 2, none) -DEF(append, 1, 3, 2, none) /* append enumerated object, update length */ -DEF(copy_data_properties, 2, 3, 3, u8) -DEF(define_method, 6, 2, 1, atom_u8) -DEF(define_method_computed, 2, 3, 1, u8) /* must come after define_method */ -DEF(define_class, 6, 2, 2, atom_u8) - -DEF(get_loc, 3, 0, 1, loc) -DEF(put_loc, 3, 1, 0, loc) /* must come after get_loc */ -DEF(set_loc, 3, 1, 1, loc) /* must come after put_loc */ -DEF(get_arg, 3, 0, 1, arg) -DEF(put_arg, 3, 1, 0, arg) /* must come after get_arg */ -DEF(set_arg, 3, 1, 1, arg) /* must come after put_arg */ -DEF(get_var_ref, 3, 0, 1, var_ref) -DEF(put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */ -DEF(set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */ -DEF(set_loc_uninitialized, 3, 0, 0, loc) -DEF(get_loc_check, 3, 0, 1, loc) -DEF(put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */ -DEF(put_loc_check_init, 3, 1, 0, loc) -DEF(get_var_ref_check, 3, 0, 1, var_ref) -DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */ -DEF(put_var_ref_check_init, 3, 1, 0, var_ref) -DEF(close_loc, 3, 0, 0, loc) -DEF(if_false, 5, 1, 0, label) -DEF(if_true, 5, 1, 0, label) /* must come after if_false */ -DEF(goto, 5, 0, 0, label) /* must come after if_true */ -DEF(catch, 5, 0, 1, label) -DEF(gosub, 5, 0, 0, label) /* used to execute the finally block */ -DEF(ret, 1, 1, 0, none) /* used to return from the finally block */ - -DEF(to_object, 1, 1, 1, none) -// DEF( to_string, 1, 1, 1, none) -DEF(to_propkey, 1, 1, 1, none) -DEF(to_propkey2, 1, 2, 2, none) - -DEF(with_get_var, 10, 1, 0, - atom_label_u8) /* must be in the same order as scope_xxx */ -DEF(with_put_var, 10, 2, 1, - atom_label_u8) /* must be in the same order as scope_xxx */ -DEF(with_delete_var, 10, 1, 0, - atom_label_u8) /* must be in the same order as scope_xxx */ -DEF(with_make_ref, 10, 1, 0, - atom_label_u8) /* must be in the same order as scope_xxx */ -DEF(with_get_ref, 10, 1, 0, - atom_label_u8) /* must be in the same order as scope_xxx */ -DEF(with_get_ref_undef, 10, 1, 0, atom_label_u8) - -DEF(make_loc_ref, 7, 0, 2, atom_u16) -DEF(make_arg_ref, 7, 0, 2, atom_u16) -DEF(make_var_ref_ref, 7, 0, 2, atom_u16) -DEF(make_var_ref, 5, 0, 2, atom) - -DEF(for_in_start, 1, 1, 1, none) -DEF(for_of_start, 1, 1, 3, none) -DEF(for_await_of_start, 1, 1, 3, none) -DEF(for_in_next, 1, 1, 3, none) -DEF(for_of_next, 2, 3, 5, u8) -DEF(for_await_of_next, 1, 3, 4, none) -DEF(iterator_get_value_done, 1, 1, 2, none) -DEF(iterator_close, 1, 3, 0, none) -DEF(iterator_close_return, 1, 4, 4, none) -DEF(async_iterator_close, 1, 3, 2, none) -DEF(async_iterator_next, 1, 4, 4, none) -DEF(async_iterator_get, 2, 4, 5, u8) -DEF(initial_yield, 1, 0, 0, none) -DEF(yield, 1, 1, 2, none) -DEF(yield_star, 1, 2, 2, none) -DEF(async_yield_star, 1, 1, 2, none) -DEF(await, 1, 1, 1, none) - -/* arithmetic/logic operations */ -DEF(neg, 1, 1, 1, none) -DEF(plus, 1, 1, 1, none) -DEF(dec, 1, 1, 1, none) -DEF(inc, 1, 1, 1, none) -DEF(post_dec, 1, 1, 2, none) -DEF(post_inc, 1, 1, 2, none) -DEF(dec_loc, 2, 0, 0, loc8) -DEF(inc_loc, 2, 0, 0, loc8) -DEF(add_loc, 2, 1, 0, loc8) -DEF(not, 1, 1, 1, none) -DEF(lnot, 1, 1, 1, none) -DEF(typeof, 1, 1, 1, none) -DEF(delete, 1, 2, 1, none) -DEF(delete_var, 5, 0, 1, atom) - -DEF(mul, 1, 2, 1, none) -DEF(div, 1, 2, 1, none) -DEF(mod, 1, 2, 1, none) -DEF(add, 1, 2, 1, none) -DEF(sub, 1, 2, 1, none) -DEF(pow, 1, 2, 1, none) -DEF(shl, 1, 2, 1, none) -DEF(sar, 1, 2, 1, none) -DEF(shr, 1, 2, 1, none) -DEF(lt, 1, 2, 1, none) -DEF(lte, 1, 2, 1, none) -DEF(gt, 1, 2, 1, none) -DEF(gte, 1, 2, 1, none) -DEF(instanceof, 1, 2, 1, none) -DEF(in, 1, 2, 1, none) -DEF(eq, 1, 2, 1, none) -DEF(neq, 1, 2, 1, none) -DEF(strict_eq, 1, 2, 1, none) -DEF(strict_neq, 1, 2, 1, none) -DEF(and, 1, 2, 1, none) -DEF(xor, 1, 2, 1, none) -DEF(or, 1, 2, 1, none) -#ifdef CONFIG_BIGNUM -DEF(mul_pow10, 1, 2, 1, none) -DEF(math_div, 1, 2, 1, none) -DEF(math_mod, 1, 2, 1, none) -DEF(math_pow, 1, 2, 1, none) -#endif -/* must be the last non short and non temporary opcode */ -DEF(nop, 1, 0, 0, none) -/* temporary opcodes: never emitted in the final bytecode */ - -def(set_arg_valid_upto, 3, 0, 0, arg) /* emitted in phase 1, removed in phase 2 */ - -def(close_var_object, 1, 0, 0, none) /* emitted in phase 1, removed in phase 2 */ -def(enter_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */ -def(leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */ -def(label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */ -def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ -def(scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ -def(scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */ -def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ -def(scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */ -def(scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */ -def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */ -def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */ -def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */ -def(scope_put_private_field, 7, 1, 1, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */ - -// -def(line_num, 9, 0, 0, u64) /* emitted in phase 1, removed in phase 3 */ - // - -#if SHORT_OPCODES -DEF(push_minus1, 1, 0, 1, none_int) -DEF(push_0, 1, 0, 1, none_int) -DEF(push_1, 1, 0, 1, none_int) -DEF(push_2, 1, 0, 1, none_int) -DEF(push_3, 1, 0, 1, none_int) -DEF(push_4, 1, 0, 1, none_int) -DEF(push_5, 1, 0, 1, none_int) -DEF(push_6, 1, 0, 1, none_int) -DEF(push_7, 1, 0, 1, none_int) -DEF(push_i8, 2, 0, 1, i8) -DEF(push_i16, 3, 0, 1, i16) -DEF(push_const8, 2, 0, 1, const8) -DEF(fclosure8, 2, 0, 1, const8) /* must follow push_const8 */ -DEF(push_empty_string, 1, 0, 1, none) -DEF(get_loc8, 2, 0, 1, loc8) -DEF(put_loc8, 2, 1, 0,loc8) -DEF(set_loc8, 2, 1, 1, loc8) -DEF(get_loc0, 1, 0, 1, none_loc) -DEF(get_loc1, 1, 0, 1, none_loc) -DEF(get_loc2, 1, 0, 1, none_loc) -DEF(get_loc3, 1, 0, 1, none_loc) -DEF(put_loc0, 1, 1, 0, none_loc) -DEF(put_loc1, 1, 1, 0, none_loc) -DEF(put_loc2, 1, 1, 0, none_loc) -DEF(put_loc3, 1, 1, 0, none_loc) -DEF(set_loc0, 1, 1, 1, none_loc) -DEF(set_loc1, 1, 1, 1, none_loc) -DEF(set_loc2, 1, 1, 1, none_loc) -DEF(set_loc3, 1, 1, 1, none_loc) -DEF(get_arg0, 1, 0, 1, none_arg) -DEF(get_arg1, 1, 0, 1, none_arg) -DEF(get_arg2, 1, 0, 1, none_arg) -DEF(get_arg3, 1, 0, 1, none_arg) -DEF(put_arg0, 1, 1, 0, none_arg) -DEF(put_arg1, 1, 1, 0, none_arg) -DEF(put_arg2, 1, 1, 0, none_arg) -DEF(put_arg3, 1, 1, 0, none_arg) -DEF(set_arg0, 1, 1, 1, none_arg) -DEF(set_arg1, 1, 1, 1, none_arg) -DEF(set_arg2, 1, 1, 1, none_arg) -DEF(set_arg3, 1, 1, 1, none_arg) -DEF(get_var_ref0, 1, 0, 1, none_var_ref) -DEF(get_var_ref1, 1, 0, 1, none_var_ref) -DEF(get_var_ref2, 1, 0, 1, none_var_ref) -DEF(get_var_ref3, 1, 0, 1, none_var_ref) -DEF(put_var_ref0, 1, 1, 0, none_var_ref) -DEF(put_var_ref1, 1, 1, 0, none_var_ref) -DEF(put_var_ref2, 1, 1, 0, none_var_ref) -DEF(put_var_ref3, 1, 1, 0, none_var_ref) -DEF(set_var_ref0, 1, 1, 1, none_var_ref) -DEF(set_var_ref1, 1, 1, 1, none_var_ref) -DEF(set_var_ref2, 1, 1, 1, none_var_ref) -DEF(set_var_ref3, 1, 1, 1, none_var_ref) - -DEF(get_length, 1, 1, 1, none) - -DEF(if_false8, 2, 1, 0, label8) -DEF(if_true8, 2, 1, 0, label8) /* must come after if_false8 */ -DEF(goto8, 2, 0, 0, label8) /* must come after if_true8 */ -DEF(goto16, 3, 0, 0, label16) -DEF(call0, 1, 1, 1, npopx) -DEF(call1, 1, 1, 1, npopx) -DEF(call2, 1, 1, 1, npopx) -DEF(call3, 1, 1, 1, npopx) -DEF(is_undefined, 1, 1, 1, none) -DEF(is_null, 1, 1, 1, none) -DEF(is_function, 1, 1, 1, none) -#endif - -#undef DEF -#undef def -#endif /* DEF */ - -#ifdef COMPILE_TIME_OPCODE -COMPILE_TIME_OPCODE(caller_str, 9, 0, 0, none) -#endif diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs_queue.h b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs_queue.h deleted file mode 100644 index b19956fd..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs_queue.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. -#ifndef SRC_INTERPRETER_QUICKJS_INCLUDE_QUICKJS_QUEUE_H_ -#define SRC_INTERPRETER_QUICKJS_INCLUDE_QUICKJS_QUEUE_H_ - -#include - -#define DEFAULT_INIT_SIZE 2048 - -#ifdef ENABLE_GC_DEBUG_TOOLS -#include -#ifdef __cplusplus -extern "C" { -#endif -bool check_valid_ptr(void *runtime, void *ptr); -#ifdef __cplusplus -} -#endif -#endif - -// rear is emptry, capacity == size - 1 -class Queue { - public: - Queue(void *runtime, int initial_size); - explicit Queue(void *runtime); - ~Queue(); - - bool IsEmpty(); - bool IsFull(); - void EnQueue(void *ptr); - void *DeQueue(); - void *Front(); - void ResizeQueue(); - // void Display(); - int GetCount() { return count; } - int GetSize() { return size; } - const void *GetQueue() { return queue; } - void Split(int cnt, Queue *q) { - for (int i = 0; i < cnt; i++) { - q->EnQueue(DeQueue()); - } - } - - private: - void **queue; - void *rt_; - int front; - int rear; - int count; - int size; -}; - -#endif // SRC_INTERPRETER_QUICKJS_INCLUDE_QUICKJS_QUEUE_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs_version.h b/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs_version.h deleted file mode 100644 index 8c7a3292..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/quickjs/include/quickjs_version.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -#ifndef SRC_INTERPRETER_QUICKJS_INCLUDE_QUICKJS_VERSION_H_ -#define SRC_INTERPRETER_QUICKJS_INCLUDE_QUICKJS_VERSION_H_ - -#include -#include -#define FEATURE_LEPUSNG_DEBUGINFO_OUTSIDE "2.5" -#define PRIMJS_ADD_VERSION_CODE "2.14" - -typedef struct Version { - int major, minor, revision, build; -} Version; - -void VersionInit(Version* v, const char* version); -uint8_t VersionLessOrEqual(Version v1, Version other); -uint8_t IsHigherOrEqual(const char* targetV, const char* baseV); - -#endif // SRC_INTERPRETER_QUICKJS_INCLUDE_QUICKJS_VERSION_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/trace-gc.h b/test-app/runtime/src/main/cpp/napi/primjs/include/trace-gc.h similarity index 75% rename from test-app/runtime/src/main/cpp/napi/primjs/include/gc/trace-gc.h rename to test-app/runtime/src/main/cpp/napi/primjs/include/trace-gc.h index c45f2792..00289633 100644 --- a/test-app/runtime/src/main/cpp/napi/primjs/include/gc/trace-gc.h +++ b/test-app/runtime/src/main/cpp/napi/primjs/include/trace-gc.h @@ -4,6 +4,7 @@ #ifndef SRC_GC_TRACE_GC_H_ #define SRC_GC_TRACE_GC_H_ +#include #ifdef __cplusplus extern "C" { #endif @@ -14,10 +15,13 @@ extern "C" { struct LEPUSRuntime; +#ifdef USE_PRIMJS_NAPI +#include "primjs_napi_defines.h" +#endif typedef struct napi_env__ *napi_env; typedef struct napi_value__ *napi_value; -class napi_handle_scope__; -typedef void napi_func(napi_env env, napi_handle_scope__ *scope); +class NAPIHandleScope; +typedef void napi_func(napi_env env, NAPIHandleScope *scope); enum HandleType { HANDLE_TYPE_UNDEFINED, @@ -62,6 +66,19 @@ class PtrHandles { void ResizeHandles(); }; +class CheckTools { + public: + CheckTools(); + ~CheckTools(); + bool PushTid(int tid); + bool IsValidTid(int tid); + + private: + int tid_idx; + int tid_size; + int *tids; +}; + class HandleScope { public: HandleScope(LEPUSRuntime *rt); @@ -80,22 +97,22 @@ class HandleScope { int handle_prev_idx; }; -class napi_handle_scope__ { +class NAPIHandleScope { public: - napi_handle_scope__(napi_env env, LEPUSContext *ctx, napi_func *func = nullptr); - explicit napi_handle_scope__(LEPUSContext *ctx) + NAPIHandleScope(napi_env env, LEPUSContext *ctx, napi_func *func = nullptr); + explicit NAPIHandleScope(LEPUSContext *ctx) : env_(nullptr), ctx_(ctx), handle_tail_(nullptr), reset_napi_env(nullptr) { is_gc = ctx_ == nullptr ? false : LEPUS_IsGCMode(ctx_); if (is_gc) { - prev_ = reinterpret_cast(GetNapiScope(ctx_)); + prev_ = reinterpret_cast(GetNapiScope(ctx_)); SetNapiScope(ctx_, this); } } - inline ~napi_handle_scope__() { + inline ~NAPIHandleScope() { Handle *curr = handle_tail_; while (curr) { Handle *temp = curr; @@ -112,8 +129,8 @@ class napi_handle_scope__ { } } - napi_handle_scope__(const napi_handle_scope__ &) = delete; - void operator=(const napi_handle_scope__ &) = delete; + NAPIHandleScope(const NAPIHandleScope &) = delete; + void operator=(const NAPIHandleScope &) = delete; napi_value Escape(napi_value v); @@ -123,15 +140,23 @@ class napi_handle_scope__ { Handle *prev; }; Handle *GetHandle() { return handle_tail_; } - napi_handle_scope__ *GetPrevScope() { return prev_; } + NAPIHandleScope *GetPrevScope() { return prev_; } napi_env env_; LEPUSContext *ctx_; bool is_gc; - napi_handle_scope__ *prev_; + NAPIHandleScope *prev_; Handle *handle_tail_; napi_func *reset_napi_env; }; +class GCObserver { + public: + virtual ~GCObserver() = default; + virtual void OnGC(std::string mem_info) = 0; +}; +#ifdef USE_PRIMJS_NAPI +#include "primjs_napi_undefs.h" +#endif #endif // SRC_GC_TRACE_GC_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/js_native_api_adapter.cc b/test-app/runtime/src/main/cpp/napi/primjs/js_native_api_adapter.cc new file mode 100644 index 00000000..750814b3 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/primjs/js_native_api_adapter.cc @@ -0,0 +1,707 @@ +/** + * Copyright (c) 2017 Node.js API collaborators. All Rights Reserved. + * + * Use of this source code is governed by a MIT license that can be + * found in the LICENSE file in the root of the source tree. + */ + +// Copyright 2025 The Lynx Authors. All rights reserved. +// Licensed under the Apache License Version 2.0 that can be found in the +// LICENSE file in the root directory of this source tree. + +// PrimJS Node-API adapter. +// +// The prebuilt primjs `libnapi.so` does not export the standard napi_* value +// operations; instead it installs them as function pointers on the napi_env +// vtable (struct napi_env__, defined in primjs_napi_vtable.h) via the exported +// napi_attach_quickjs(). This file provides the standard-named C entry points +// the binding layer calls (declared in common/js_native_api.h) as thin +// pass-throughs into that vtable. +// +// NativeScript-specific additions (host objects, ...) live in +// js_native_api_extensions.cc, not here. Besides the pass-throughs, this file +// also holds primjs_execute_pending_jobs -- the microtask pump that drives the +// engine's job queue for the runtime. + +#include "primjs_napi_vtable.h" // struct napi_env__ (+ standard napi types) +#include "quickjs.h" // LEPUS_* for primjs_execute_pending_jobs +#include "napi_env_quickjs.h" // napi_get_env_context_quickjs + +#include // std::fprintf (napi_fatal_error) +#include // std::abort (napi_fatal_error) + +EXTERN_C_START + +napi_status napi_get_version(napi_env env, uint32_t* result) { + return env->napi_get_version(env, result); +} + +napi_status napi_get_undefined(napi_env env, napi_value* result) { + return env->napi_get_undefined(env, result); +} + +napi_status napi_get_null(napi_env env, napi_value* result) { + return env->napi_get_null(env, result); +} + +napi_status napi_get_global(napi_env env, napi_value* result) { + return env->napi_get_global(env, result); +} + +napi_status napi_get_boolean(napi_env env, bool value, + napi_value* result) { + return env->napi_get_boolean(env, value, result); +} + +napi_status napi_create_object(napi_env env, napi_value* result) { + return env->napi_create_object(env, result); +} + +napi_status napi_create_array(napi_env env, napi_value* result) { + return env->napi_create_array(env, result); +} + +napi_status napi_create_array_with_length(napi_env env, size_t length, + napi_value* result) { + return env->napi_create_array_with_length(env, length, result); +} + +napi_status napi_create_double(napi_env env, double value, + napi_value* result) { + return env->napi_create_double(env, value, result); +} + +napi_status napi_create_int32(napi_env env, int32_t value, + napi_value* result) { + return env->napi_create_int32(env, value, result); +} + +napi_status napi_create_uint32(napi_env env, uint32_t value, + napi_value* result) { + return env->napi_create_uint32(env, value, result); +} + +napi_status napi_create_int64(napi_env env, int64_t value, + napi_value* result) { + return env->napi_create_int64(env, value, result); +} + +napi_status napi_create_string_latin1(napi_env env, const char* str, + size_t length, + napi_value* result) { + return env->napi_create_string_latin1(env, str, length, result); +} + +napi_status napi_create_string_utf8(napi_env env, const char* str, + size_t length, napi_value* result) { + return env->napi_create_string_utf8(env, str, length, result); +} + +napi_status napi_create_string_utf16(napi_env env, const char16_t* str, + size_t length, napi_value* result) { + return env->napi_create_string_utf16(env, str, length, result); +} + +napi_status napi_create_symbol(napi_env env, napi_value description, + napi_value* result) { + return env->napi_create_symbol(env, description, result); +} + +napi_status napi_create_function(napi_env env, const char* utf8name, + size_t length, napi_callback cb, + void* data, napi_value* result) { + return env->napi_create_function(env, utf8name, length, cb, data, result); +} + +napi_status napi_create_error(napi_env env, napi_value code, + napi_value msg, napi_value* result) { + return env->napi_create_error(env, code, msg, result); +} + +napi_status napi_create_type_error(napi_env env, napi_value code, + napi_value msg, napi_value* result) { + return env->napi_create_type_error(env, code, msg, result); +} + +napi_status napi_create_range_error(napi_env env, napi_value code, + napi_value msg, napi_value* result) { + return env->napi_create_range_error(env, code, msg, result); +} + +napi_status napi_typeof(napi_env env, napi_value value, + napi_valuetype* result) { + return env->napi_typeof(env, value, result); +} + +napi_status napi_get_value_double(napi_env env, napi_value value, + double* result) { + return env->napi_get_value_double(env, value, result); +} + +napi_status napi_get_value_int32(napi_env env, napi_value value, + int32_t* result) { + return env->napi_get_value_int32(env, value, result); +} + +napi_status napi_get_value_uint32(napi_env env, napi_value value, + uint32_t* result) { + return env->napi_get_value_uint32(env, value, result); +} + +napi_status napi_get_value_int64(napi_env env, napi_value value, + int64_t* result) { + return env->napi_get_value_int64(env, value, result); +} + +napi_status napi_get_value_bool(napi_env env, napi_value value, + bool* result) { + return env->napi_get_value_bool(env, value, result); +} + +napi_status napi_get_value_string_latin1(napi_env env, napi_value value, + char* buf, size_t bufsize, + size_t* result) { + return env->napi_get_value_string_latin1(env, value, buf, bufsize, result); +} + +napi_status napi_get_value_string_utf8(napi_env env, napi_value value, + char* buf, size_t bufsize, + size_t* result) { + return env->napi_get_value_string_utf8(env, value, buf, bufsize, result); +} + +napi_status napi_get_value_string_utf16(napi_env env, napi_value value, + char16_t* buf, size_t bufsize, + size_t* result) { + return env->napi_get_value_string_utf16(env, value, buf, bufsize, result); +} + +napi_status napi_coerce_to_bool(napi_env env, napi_value value, + napi_value* result) { + return env->napi_coerce_to_bool(env, value, result); +} + +napi_status napi_coerce_to_number(napi_env env, napi_value value, + napi_value* result) { + return env->napi_coerce_to_number(env, value, result); +} + +napi_status napi_coerce_to_object(napi_env env, napi_value value, + napi_value* result) { + return env->napi_coerce_to_object(env, value, result); +} + +napi_status napi_coerce_to_string(napi_env env, napi_value value, + napi_value* result) { + return env->napi_coerce_to_string(env, value, result); +} + +napi_status napi_get_prototype(napi_env env, napi_value object, + napi_value* result) { + return env->napi_get_prototype(env, object, result); +} + +napi_status napi_get_property_names(napi_env env, napi_value object, + napi_value* result) { + return env->napi_get_all_property_names( + env, object, napi_key_include_prototypes, + static_cast(napi_key_enumerable | napi_key_skip_symbols), + napi_key_numbers_to_strings, result); +} + +napi_status napi_set_property(napi_env env, napi_value object, + napi_value key, napi_value value) { + return env->napi_set_property(env, object, key, value); +} + +napi_status napi_has_property(napi_env env, napi_value object, + napi_value key, bool* result) { + return env->napi_has_property(env, object, key, result); +} + +napi_status napi_get_property(napi_env env, napi_value object, + napi_value key, napi_value* result) { + return env->napi_get_property(env, object, key, result); +} + +napi_status napi_delete_property(napi_env env, napi_value object, + napi_value key, bool* result) { + return env->napi_delete_property(env, object, key, result); +} + +napi_status napi_has_own_property(napi_env env, napi_value object, + napi_value key, bool* result) { + return env->napi_has_own_property(env, object, key, result); +} + +napi_status napi_set_named_property(napi_env env, napi_value object, + const char* utf8name, + napi_value value) { + return env->napi_set_named_property(env, object, utf8name, value); +} + +napi_status napi_has_named_property(napi_env env, napi_value object, + const char* utf8name, bool* result) { + return env->napi_has_named_property(env, object, utf8name, result); +} + +napi_status napi_get_named_property(napi_env env, napi_value object, + const char* utf8name, + napi_value* result) { + return env->napi_get_named_property(env, object, utf8name, result); +} + +napi_status napi_set_element(napi_env env, napi_value object, + uint32_t index, napi_value value) { + return env->napi_set_element(env, object, index, value); +} + +napi_status napi_has_element(napi_env env, napi_value object, + uint32_t index, bool* result) { + return env->napi_has_element(env, object, index, result); +} + +napi_status napi_get_element(napi_env env, napi_value object, + uint32_t index, napi_value* result) { + return env->napi_get_element(env, object, index, result); +} + +napi_status napi_delete_element(napi_env env, napi_value object, + uint32_t index, bool* result) { + return env->napi_delete_element(env, object, index, result); +} + +napi_status napi_define_properties( + napi_env env, napi_value object, size_t property_count, + const napi_property_descriptor* properties) { + if (property_count > 0) { + } + return env->napi_define_properties_spec_compliant(env, object, property_count, + properties); +} + +napi_status napi_is_array(napi_env env, napi_value value, bool* result) { + return env->napi_is_array(env, value, result); +} + +napi_status napi_get_array_length(napi_env env, napi_value value, + uint32_t* result) { + return env->napi_get_array_length(env, value, result); +} + +napi_status napi_strict_equals(napi_env env, napi_value lhs, + napi_value rhs, bool* result) { + return env->napi_strict_equals(env, lhs, rhs, result); +} + +napi_status napi_call_function(napi_env env, napi_value recv, + napi_value func, size_t argc, + const napi_value* argv, + napi_value* result) { + if (argc > 0) { + } + return env->napi_call_function_spec_compliant(env, recv, func, argc, argv, + result); +} + +napi_status napi_new_instance(napi_env env, napi_value constructor, + size_t argc, const napi_value* argv, + napi_value* result) { + return env->napi_new_instance(env, constructor, argc, argv, result); +} + +napi_status napi_instanceof(napi_env env, napi_value object, + napi_value constructor, bool* result) { + return env->napi_instanceof(env, object, constructor, result); +} + +napi_status napi_get_cb_info(napi_env env, napi_callback_info cbinfo, + size_t* argc, napi_value* argv, + napi_value* this_arg, void** data) { + return env->napi_get_cb_info(env, cbinfo, argc, argv, this_arg, data); +} + +napi_status napi_get_new_target(napi_env env, napi_callback_info cbinfo, + napi_value* result) { + return env->napi_get_new_target(env, cbinfo, result); +} + +napi_status napi_define_class(napi_env env, const char* utf8name, + size_t length, napi_callback constructor, + void* data, size_t property_count, + const napi_property_descriptor* properties, + napi_value* result) { + napi_class class_result = nullptr; + napi_status status = env->napi_define_class_spec_compliant( + env, utf8name, length, constructor, data, property_count, properties, + nullptr, &class_result); + if (!class_result) { + return status; + } + if (status != napi_ok) { + env->napi_release_class(env, class_result); + return status; + } + status = env->napi_class_get_function(env, class_result, result); + env->napi_release_class(env, class_result); + return status; +} + +napi_status napi_wrap(napi_env env, napi_value js_object, + void* native_object, napi_finalize finalize_cb, + void* finalize_hint, napi_ref* result) { + return env->napi_wrap_spec_compliant(env, js_object, native_object, + finalize_cb, finalize_hint, result); +} + +napi_status napi_unwrap(napi_env env, napi_value js_object, + void** result) { + return env->napi_unwrap_spec_compliant(env, js_object, result); +} + +napi_status napi_remove_wrap(napi_env env, napi_value js_object, + void** result) { + return env->napi_remove_wrap_spec_compliant(env, js_object, result); +} + +napi_status napi_create_external(napi_env env, void* data, + napi_finalize finalize_cb, + void* finalize_hint, + napi_value* result) { + return env->napi_create_external(env, data, finalize_cb, finalize_hint, + result); +} + +napi_status napi_get_value_external(napi_env env, napi_value value, + void** result) { + return env->napi_get_value_external(env, value, result); +} + +napi_status napi_create_reference(napi_env env, napi_value value, + uint32_t initial_refcount, + napi_ref* result) { + return env->napi_create_reference(env, value, initial_refcount, result); +} + +napi_status napi_delete_reference(napi_env env, napi_ref ref) { + return env->napi_delete_reference(env, ref); +} + +napi_status napi_reference_ref(napi_env env, napi_ref ref, + uint32_t* result) { + return env->napi_reference_ref(env, ref, result); +} + +napi_status napi_reference_unref(napi_env env, napi_ref ref, + uint32_t* result) { + return env->napi_reference_unref(env, ref, result); +} + +napi_status napi_get_reference_value(napi_env env, napi_ref ref, + napi_value* result) { + return env->napi_get_reference_value(env, ref, result); +} + +napi_status napi_open_handle_scope(napi_env env, + napi_handle_scope* result) { + return env->napi_open_handle_scope(env, result); +} + +napi_status napi_close_handle_scope(napi_env env, + napi_handle_scope scope) { + return env->napi_close_handle_scope(env, scope); +} + +napi_status napi_open_escapable_handle_scope( + napi_env env, napi_escapable_handle_scope* result) { + return env->napi_open_escapable_handle_scope(env, result); +} + +napi_status napi_close_escapable_handle_scope( + napi_env env, napi_escapable_handle_scope scope) { + return env->napi_close_escapable_handle_scope(env, scope); +} + +napi_status napi_escape_handle(napi_env env, + napi_escapable_handle_scope scope, + napi_value escapee, napi_value* result) { + return env->napi_escape_handle(env, scope, escapee, result); +} + +napi_status napi_throw(napi_env env, napi_value error) { + return env->napi_throw_(env, error); +} + +napi_status napi_throw_error(napi_env env, const char* code, + const char* msg) { + return env->napi_throw_error(env, code, msg); +} + +napi_status napi_throw_type_error(napi_env env, const char* code, + const char* msg) { + return env->napi_throw_type_error(env, code, msg); +} + +napi_status napi_throw_range_error(napi_env env, const char* code, + const char* msg) { + return env->napi_throw_range_error(env, code, msg); +} + +napi_status napi_is_error(napi_env env, napi_value value, bool* result) { + return env->napi_is_error(env, value, result); +} + +napi_status napi_is_exception_pending(napi_env env, bool* result) { + return env->napi_is_exception_pending(env, result); +} + +napi_status napi_get_and_clear_last_exception(napi_env env, + napi_value* result) { + return env->napi_get_and_clear_last_exception(env, result); +} + +napi_status napi_is_arraybuffer(napi_env env, napi_value value, + bool* result) { + return env->napi_is_arraybuffer(env, value, result); +} +napi_status napi_create_arraybuffer(napi_env env, size_t byte_length, + void** data, napi_value* result) { + return env->napi_create_arraybuffer(env, byte_length, data, result); +} +napi_status napi_create_external_arraybuffer( + napi_env env, void* external_data, size_t byte_length, + napi_finalize finalize_cb, void* finalize_hint, napi_value* result) { + return env->napi_create_external_arraybuffer( + env, external_data, byte_length, finalize_cb, finalize_hint, result); +} +napi_status napi_get_arraybuffer_info(napi_env env, + napi_value arraybuffer, + void** data, size_t* byte_length) { + return env->napi_get_arraybuffer_info(env, arraybuffer, data, byte_length); +} + +napi_status napi_is_typedarray(napi_env env, napi_value value, + bool* result) { + return env->napi_is_typedarray(env, value, result); +} + +napi_status napi_create_typedarray(napi_env env, + napi_typedarray_type type, + size_t length, napi_value arraybuffer, + size_t byte_offset, + napi_value* result) { + return env->napi_create_typedarray(env, type, length, arraybuffer, + byte_offset, result); +} + +napi_status napi_get_typedarray_info(napi_env env, napi_value typedarray, + napi_typedarray_type* type, + size_t* length, void** data, + napi_value* arraybuffer, + size_t* byte_offset) { + return env->napi_get_typedarray_info(env, typedarray, type, length, data, + arraybuffer, byte_offset); +} + +napi_status napi_create_dataview(napi_env env, size_t length, + napi_value arraybuffer, + size_t byte_offset, + napi_value* result) { + return env->napi_create_dataview(env, length, arraybuffer, byte_offset, + result); +} + +napi_status napi_is_dataview(napi_env env, napi_value value, + bool* result) { + return env->napi_is_dataview(env, value, result); +} + +napi_status napi_get_dataview_info(napi_env env, napi_value dataview, + size_t* bytelength, void** data, + napi_value* arraybuffer, + size_t* byte_offset) { + return env->napi_get_dataview_info(env, dataview, bytelength, data, + arraybuffer, byte_offset); +} + +napi_status napi_create_promise(napi_env env, napi_deferred* deferred, + napi_value* promise) { + return env->napi_create_promise(env, deferred, promise); +} + +napi_status napi_is_promise(napi_env env, napi_value value, + bool* is_promise) { + return env->napi_is_promise(env, value, is_promise); +} + +napi_status napi_resolve_deferred(napi_env env, napi_deferred deferred, + napi_value resolution) { + return env->napi_release_deferred(env, deferred, resolution, + napi_deferred_resolve); +} + +napi_status napi_reject_deferred(napi_env env, napi_deferred deferred, + napi_value rejection) { + return env->napi_release_deferred(env, deferred, rejection, + napi_deferred_reject); +} + +napi_status napi_run_script(napi_env env, const char* script, size_t length, + const char* filename, napi_value* result) { + return env->napi_run_script(env, script, length, filename, result); +} + +napi_status napi_adjust_external_memory(napi_env env, + int64_t change_in_bytes, + int64_t* adjusted_value) { + return env->napi_adjust_external_memory(env, change_in_bytes, adjusted_value); +} + +napi_status napi_add_finalizer(napi_env env, napi_value js_object, + void* native_object, + napi_finalize finalize_cb, + void* finalize_hint, napi_ref* result) { + return env->napi_add_finalizer(env, js_object, native_object, finalize_cb, + finalize_hint, result); +} + +static const uint64_t kNapiAdapterInstanceDataKey = + reinterpret_cast(&kNapiAdapterInstanceDataKey); +napi_status napi_set_instance_data(napi_env env, void* data, + napi_finalize finalize_cb, + void* finalize_hint) { + return env->napi_set_instance_data_spec_compliant( + env, kNapiAdapterInstanceDataKey, data, finalize_cb, finalize_hint); +} + +napi_status napi_get_instance_data(napi_env env, void** data) { + return env->napi_get_instance_data(env, kNapiAdapterInstanceDataKey, data); +} + +napi_status napi_get_last_error_info( + napi_env env, const napi_extended_error_info** result) { + return env->napi_get_last_error_info(env, result); +} + +napi_status napi_add_env_cleanup_hook(napi_env env, + void (*fun)(void* arg), + void* arg) { + return env->napi_add_env_cleanup_hook(env, fun, arg); +} + +napi_status napi_remove_env_cleanup_hook(napi_env env, + void (*fun)(void* arg), + void* arg) { + return env->napi_remove_env_cleanup_hook(env, fun, arg); +} + +napi_status napi_create_async_work(napi_env env, + napi_value async_resource, + napi_value async_resource_name, + napi_async_execute_callback execute, + napi_async_complete_callback complete, + void* data, napi_async_work* result) { + return env->napi_create_async_work(env, async_resource, async_resource_name, + execute, complete, data, result); +} + +napi_status napi_delete_async_work(napi_env env, napi_async_work work) { + return env->napi_delete_async_work(env, work); +} + +napi_status napi_queue_async_work(napi_env env, napi_async_work work) { + return env->napi_queue_async_work(env, work); +} + +napi_status napi_cancel_async_work(napi_env env, napi_async_work work) { + return env->napi_cancel_async_work(env, work); +} + +void napi_fatal_error(const char* location, size_t location_len, + const char* message, size_t message_len) { + if (location && location_len > 0) { + int print_len = + (location_len > INT_MAX) ? INT_MAX : static_cast(location_len); + std::fprintf(stderr, "Fatal error location: %.*s\n", print_len, location); + } + + if (message && message_len > 0) { + int message_print_len = + (message_len > INT_MAX) ? INT_MAX : static_cast(message_len); + std::fprintf(stderr, "Fatal error message: %.*s\n", message_print_len, + message); + } + + std::abort(); +} + +napi_status napi_create_date(napi_env env, double time, + napi_value* result) { + return env->napi_create_date(env, time, result); +} + +napi_status napi_is_date(napi_env env, napi_value value, bool* is_date) { + return env->napi_is_date(env, value, is_date); +} + +napi_status napi_get_date_value(napi_env env, napi_value value, + double* result) { + return env->napi_get_date_value(env, value, result); +} + +napi_status napi_get_all_property_names( + napi_env env, napi_value object, napi_key_collection_mode key_mode, + napi_key_filter key_filter, napi_key_conversion key_conversion, + napi_value* result) { + return env->napi_get_all_property_names(env, object, key_mode, key_filter, + key_conversion, result); +} + +napi_status napi_create_bigint_int64(napi_env env, int64_t value, + napi_value* result) { + return env->napi_create_bigint_int64(env, value, result); +} +napi_status napi_create_bigint_uint64(napi_env env, uint64_t value, + napi_value* result) { + return env->napi_create_bigint_uint64(env, value, result); +} + +napi_status napi_create_bigint_words(napi_env env, int sign_bit, + size_t word_count, + const uint64_t* words, + napi_value* result) { + return env->napi_create_bigint_words(env, sign_bit, word_count, words, + result); +} +napi_status napi_get_value_bigint_int64(napi_env env, napi_value value, + int64_t* result, + bool* lossless) { + return env->napi_get_value_bigint_int64(env, value, result, lossless); +} +napi_status napi_get_value_bigint_uint64(napi_env env, napi_value value, + uint64_t* result, + bool* lossless) { + return env->napi_get_value_bigint_uint64(env, value, result, lossless); +} +napi_status napi_get_value_bigint_words(napi_env env, napi_value value, + int* sign_bit, + size_t* word_count, + uint64_t* words) { + return env->napi_get_value_bigint_words(env, value, sign_bit, word_count, + words); +} + +napi_status primjs_execute_pending_jobs(napi_env env) { + int error; + do { + LEPUSContext *context; + error = LEPUS_ExecutePendingJob(LEPUS_GetRuntime(napi_get_env_context_quickjs(env)), &context); + if (error == -1) { + return napi_pending_exception; + } + } while (error != 0); + + return napi_ok; +} + +EXTERN_C_END diff --git a/test-app/runtime/src/main/cpp/napi/primjs/js_native_api_extensions.cc b/test-app/runtime/src/main/cpp/napi/primjs/js_native_api_extensions.cc new file mode 100644 index 00000000..1e1312bb --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/primjs/js_native_api_extensions.cc @@ -0,0 +1,296 @@ +// NativeScript-specific Node-API extensions for PrimJS. +// +// These are entry points NativeScript adds on top of what primjs' libnapi.so +// provides. They are ordinary exported C symbols (not vtable slots) and talk to +// the LEPUS engine directly. Keep engine extensions here so the adapter stays a +// pure pass-through to primjs' vtable. +// +// Currently: host objects (napi_create_host_object / napi_is_host_object / +// napi_get_host_object_data), guarded by USE_HOST_OBJECT.[ + +#include "primjs_napi_vtable.h" // struct napi_env__ (+ standard napi types) +#include "quickjs.h" +#include "napi_env_quickjs.h" + +#ifdef USE_HOST_OBJECT + +// --------------------------------------------------------------------------- +// PrimJS host-object implementation +// +// PrimJS is a QuickJS/LEPUS fork. We register a custom LEPUS class +// (NapiHostObject) with exotic property-trap callbacks that forward to the +// caller-supplied napi_host_object_methods. The three public NAPI functions +// live outside the vtable — they are called directly as normal C symbols by +// the binding layer. +// --------------------------------------------------------------------------- + +struct PrimJSHostObjectInfo { + napi_env env; + void *data; + napi_finalize finalize_cb; + napi_host_object_methods methods; +}; + +// Global class ID (process-lifetime; LEPUS_NewClassID is a monotonic counter). +static LEPUSClassID g_napiHostObjectClassId = 0; + +static void lepus_host_object_finalizer(LEPUSRuntime *rt, LEPUSValue val) { + PrimJSHostObjectInfo *info = static_cast( + LEPUS_GetOpaque(val, g_napiHostObjectClassId)); + if (!info) return; + if (info->finalize_cb) { + info->finalize_cb(info->env, info->data, nullptr); + } + delete info; +} + +static LEPUSValue lepus_host_object_get(LEPUSContext *ctx, + LEPUSValueConst obj, + JSAtom atom, + LEPUSValueConst /*receiver*/) { + PrimJSHostObjectInfo *info = static_cast( + LEPUS_GetOpaque(obj, g_napiHostObjectClassId)); + if (!info || !info->methods.get) return LEPUS_UNDEFINED; + napi_env env = info->env; + + napi_handle_scope scope; + env->napi_open_handle_scope(env, &scope); + + napi_value host = napi_quickjs_value_to_js_value(env, LEPUS_DupValue(ctx, obj)); + napi_value prop = napi_quickjs_value_to_js_value(env, LEPUS_AtomToValue(ctx, atom)); + napi_value cb_result = info->methods.get(env, host, prop, info->data); + + LEPUSValue ret = LEPUS_UNDEFINED; + if (cb_result != nullptr) { + ret = napi_js_value_to_quickjs_value(env, cb_result); + } + + env->napi_close_handle_scope(env, scope); + + bool exc = false; + env->napi_is_exception_pending(env, &exc); + if (exc) { + LEPUS_FreeValue(ctx, ret); + return LEPUS_EXCEPTION; + } + return ret; +} + +static int lepus_host_object_set(LEPUSContext *ctx, + LEPUSValueConst obj, + JSAtom atom, + LEPUSValueConst value, + LEPUSValueConst /*receiver*/, + int /*flags*/) { + PrimJSHostObjectInfo *info = static_cast( + LEPUS_GetOpaque(obj, g_napiHostObjectClassId)); + if (!info || !info->methods.set) return 1; // true = success + napi_env env = info->env; + + napi_handle_scope scope; + env->napi_open_handle_scope(env, &scope); + + napi_value host = napi_quickjs_value_to_js_value(env, LEPUS_DupValue(ctx, obj)); + napi_value prop = napi_quickjs_value_to_js_value(env, LEPUS_AtomToValue(ctx, atom)); + napi_value val = napi_quickjs_value_to_js_value(env, LEPUS_DupValue(ctx, value)); + info->methods.set(env, host, prop, val, info->data); + + env->napi_close_handle_scope(env, scope); + + bool exc = false; + env->napi_is_exception_pending(env, &exc); + if (exc) return -1; + return 1; +} + +static int lepus_host_object_has(LEPUSContext *ctx, + LEPUSValueConst obj, + JSAtom atom) { + PrimJSHostObjectInfo *info = static_cast( + LEPUS_GetOpaque(obj, g_napiHostObjectClassId)); + if (!info || !info->methods.has) return 0; + napi_env env = info->env; + + napi_handle_scope scope; + env->napi_open_handle_scope(env, &scope); + + napi_value host = napi_quickjs_value_to_js_value(env, LEPUS_DupValue(ctx, obj)); + napi_value prop = napi_quickjs_value_to_js_value(env, LEPUS_AtomToValue(ctx, atom)); + int present = info->methods.has(env, host, prop, info->data); + + env->napi_close_handle_scope(env, scope); + + bool exc = false; + env->napi_is_exception_pending(env, &exc); + if (exc) return -1; + return present; +} + +static int lepus_host_object_delete(LEPUSContext *ctx, + LEPUSValueConst obj, + JSAtom atom) { + PrimJSHostObjectInfo *info = static_cast( + LEPUS_GetOpaque(obj, g_napiHostObjectClassId)); + if (!info || !info->methods.delete_property) return 1; + napi_env env = info->env; + + napi_handle_scope scope; + env->napi_open_handle_scope(env, &scope); + + napi_value host = napi_quickjs_value_to_js_value(env, LEPUS_DupValue(ctx, obj)); + napi_value prop = napi_quickjs_value_to_js_value(env, LEPUS_AtomToValue(ctx, atom)); + int deleted = info->methods.delete_property(env, host, prop, info->data); + + env->napi_close_handle_scope(env, scope); + + bool exc = false; + env->napi_is_exception_pending(env, &exc); + if (exc) return -1; + return deleted; +} + +// Implements get_own_property_names so that Object.keys() / for..in enumerate +// the host object's properties via methods.own_keys. +static int lepus_host_object_own_property_names(LEPUSContext *ctx, + LEPUSPropertyEnum **ptab, + uint32_t *plen, + LEPUSValueConst obj) { + *plen = 0; + *ptab = nullptr; + + PrimJSHostObjectInfo *info = static_cast( + LEPUS_GetOpaque(obj, g_napiHostObjectClassId)); + if (!info || !info->methods.own_keys) return 0; + napi_env env = info->env; + + napi_handle_scope scope; + env->napi_open_handle_scope(env, &scope); + + napi_value host = napi_quickjs_value_to_js_value(env, LEPUS_DupValue(ctx, obj)); + napi_value keys_array = info->methods.own_keys(env, host, info->data); + + int ret = 0; + if (keys_array != nullptr) { + uint32_t count = 0; + env->napi_get_array_length(env, keys_array, &count); + if (count > 0) { + *ptab = static_cast( + lepus_malloc(ctx, sizeof(LEPUSPropertyEnum) * count, + ALLOC_TAG_LEPUSPropertyEnum)); + if (*ptab) { + uint32_t added = 0; + for (uint32_t i = 0; i < count; i++) { + napi_value elem = nullptr; + env->napi_get_element(env, keys_array, i, &elem); + if (!elem) continue; + LEPUSValue lv = napi_js_value_to_quickjs_value(env, elem); + JSAtom atom = LEPUS_ValueToAtom(ctx, lv); + LEPUS_FreeValue(ctx, lv); + if (atom == 0) continue; // 0 == invalid / JS_ATOM_NULL + (*ptab)[added].atom = atom; + (*ptab)[added].is_enumerable = 1; + added++; + } + *plen = added; + } + } + } + + env->napi_close_handle_scope(env, scope); + return ret; +} + +static LEPUSClassExoticMethods kNapiHostObjectExotic = { + /* get_own_property */ nullptr, + /* get_own_property_names */ lepus_host_object_own_property_names, + /* delete_property */ lepus_host_object_delete, + /* define_own_property */ nullptr, + /* has_property */ lepus_host_object_has, + /* get_property */ lepus_host_object_get, + /* set_property */ lepus_host_object_set, +}; + +static LEPUSClassDef kNapiHostObjectClassDef = { + /* class_name */ "NapiHostObject", + /* finalizer */ lepus_host_object_finalizer, + /* gc_mark */ nullptr, + /* call */ nullptr, + /* exotic */ &kNapiHostObjectExotic, +}; + +// Register the class on the given runtime if not already registered. +static void ensure_host_object_class(LEPUSContext *ctx) { + LEPUSRuntime *rt = LEPUS_GetRuntime(ctx); + if (g_napiHostObjectClassId == 0) { + LEPUS_NewClassID(&g_napiHostObjectClassId); + } + if (!LEPUS_IsRegisteredClass(rt, g_napiHostObjectClassId)) { + LEPUS_NewClass(rt, g_napiHostObjectClassId, &kNapiHostObjectClassDef); + } + LEPUS_SetClassProto(ctx, g_napiHostObjectClassId, LEPUS_NewObject(ctx)); +} + +napi_status napi_create_host_object(napi_env env, + napi_finalize finalize_cb, + void *data, + const napi_host_object_methods *methods, + napi_value *result) { + if (!env) return napi_invalid_arg; + if (!methods || !result) return napi_invalid_arg; + if (!methods->get || !methods->set) return napi_invalid_arg; + + LEPUSContext *ctx = napi_get_env_context_quickjs(env); + ensure_host_object_class(ctx); + + LEPUSValue obj = LEPUS_NewObjectClass(ctx, (int) g_napiHostObjectClassId); + if (LEPUS_IsException(obj)) { + return napi_pending_exception; + } + + PrimJSHostObjectInfo *info = new PrimJSHostObjectInfo(); + info->env = env; + info->data = data; + info->finalize_cb = finalize_cb; + info->methods = *methods; + LEPUS_SetOpaque(obj, info); + + // napi_quickjs_value_to_js_value takes ownership of obj and puts it in the + // current handle scope. + *result = napi_quickjs_value_to_js_value(env, obj); + return napi_ok; +} + +napi_status napi_get_host_object_data(napi_env env, + napi_value object, + void **data) { + if (!env) return napi_invalid_arg; + if (!object || !data) return napi_invalid_arg; + + // Direct cast: napi_value is LEPUSValue* in a handle scope. + LEPUSValue lv = *((LEPUSValue *) object); + if (!LEPUS_IsObject(lv)) return napi_object_expected; + + PrimJSHostObjectInfo *info = static_cast( + LEPUS_GetOpaque(lv, g_napiHostObjectClassId)); + if (!info) return napi_invalid_arg; + + *data = info->data; + return napi_ok; +} + +napi_status napi_is_host_object(napi_env env, + napi_value object, + bool *result) { + if (!env) return napi_invalid_arg; + if (!object || !result) return napi_invalid_arg; + + *result = false; + LEPUSValue lv = *((LEPUSValue *) object); + if (LEPUS_IsObject(lv)) { + void *opaque = LEPUS_GetOpaque(lv, g_napiHostObjectClassId); + *result = (opaque != nullptr); + } + return napi_ok; +} + +#endif // USE_HOST_OBJECT diff --git a/test-app/runtime/src/main/cpp/napi/primjs/jsr.cpp b/test-app/runtime/src/main/cpp/napi/primjs/jsr.cpp index 47a7cc10..caa2c7b2 100644 --- a/test-app/runtime/src/main/cpp/napi/primjs/jsr.cpp +++ b/test-app/runtime/src/main/cpp/napi/primjs/jsr.cpp @@ -1,16 +1,18 @@ #include "napi_env_quickjs.h" +#include "napi_env.h" #include "jsr.h" +#include JSR::JSR() = default; tns::SimpleMap JSR::env_to_jsr_cache; -struct napi_runtime__ { +struct jsr_ns_runtime__ { LEPUSRuntime* runtime; LEPUSContext* context; }; -napi_status js_create_runtime(napi_runtime *runtime) { - auto _runtime = new napi_runtime__(); +napi_status js_create_runtime(jsr_ns_runtime *runtime) { + auto _runtime = new jsr_ns_runtime__(); LEPUSRuntime* rt = LEPUS_NewRuntimeWithMode(0); LEPUS_SetRuntimeInfo(rt, "Lynx_LepusNG"); _runtime->context = LEPUS_NewContext(rt); @@ -23,7 +25,7 @@ napi_status js_create_runtime(napi_runtime *runtime) { return napi_ok; } -napi_status js_create_napi_env(napi_env *env, napi_runtime runtime) { +napi_status js_create_napi_env(napi_env *env, jsr_ns_runtime runtime) { *env = napi_new_env(); napi_attach_quickjs((*env), runtime->context); @@ -71,7 +73,7 @@ napi_status js_free_napi_env(napi_env env) { return napi_ok; } -napi_status js_free_runtime(napi_runtime runtime) { +napi_status js_free_runtime(jsr_ns_runtime runtime) { LEPUS_FreeContext(runtime->context); LEPUS_FreeRuntime(runtime->runtime); return napi_ok; @@ -81,8 +83,22 @@ napi_status js_execute_script(napi_env env, napi_value script, const char *file, napi_value *result) { - - return napi_run_script_source(env, script, file, result); + // PrimJS exposes napi_run_script as a raw (source, length, filename) entry + // point, which lets us pass the script source and its filename directly + // instead of round-tripping through napi_run_script_source. + size_t length = 0; + napi_status status = napi_get_value_string_utf8(env, script, nullptr, 0, &length); + if (status != napi_ok) { + return status; + } + + std::string source(length + 1, '\0'); + status = napi_get_value_string_utf8(env, script, &source[0], length + 1, &length); + if (status != napi_ok) { + return status; + } + + return napi_run_script(env, source.c_str(), length, file, result); } napi_status js_execute_pending_jobs(napi_env env) { diff --git a/test-app/runtime/src/main/cpp/napi/primjs/napi_env.cc b/test-app/runtime/src/main/cpp/napi/primjs/napi_env.cc deleted file mode 100644 index 287de1ed..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/napi_env.cc +++ /dev/null @@ -1,170 +0,0 @@ -/** - * Copyright (c) 2017 Node.js API collaborators. All Rights Reserved. - * - * Use of this source code is governed by a MIT license that can be - * found in the LICENSE file in the root of the source tree. - */ - -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -#include "napi_env.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "napi_env_quickjs.h" -#include "primjs-api.h" - -struct napi_env_data__ { - void AddCleanupHook(void (*fun)(void* arg), void* arg) { - cleanup_hooks.insert(CleanupHook{fun, arg, cleanup_hooks.size()}); - } - - void RemoveCleanupHook(void (*fun)(void* arg), void* arg) { - cleanup_hooks.erase(CleanupHook{fun, arg, 0}); - } - - ~napi_env_data__() { RunCleanup(); } - - struct CleanupHook { - void (*fun)(void*); - void* arg; - uint64_t insertion_order_counter; - - struct Equal { - bool operator()(const CleanupHook& lhs, const CleanupHook& rhs) const { - return lhs.fun == rhs.fun && lhs.arg == rhs.arg; - } - }; - - struct Hash { - std::size_t operator()(CleanupHook const& s) const { - std::size_t h1 = - std::hash{}(reinterpret_cast(s.fun)); - std::size_t h2 = - std::hash{}(reinterpret_cast(s.arg)); - return h1 ^ (h2 << 1); - } - }; - }; - - void RunCleanup() { - while (!cleanup_hooks.empty()) { - // Copy into a vector, since we can't sort an unordered_set in-place. - std::vector callbacks(cleanup_hooks.begin(), - cleanup_hooks.end()); - // We can't erase the copied elements from `cleanup_hooks_` yet, because - // we need to be able to check whether they were un-scheduled by another - // hook. - - std::sort(callbacks.begin(), callbacks.end(), - [](const CleanupHook& a, const CleanupHook& b) { - // Sort in descending order so that the most recently inserted - // callbacks are run first. - return a.insertion_order_counter > b.insertion_order_counter; - }); - - for (const auto& cb : callbacks) { - if (cleanup_hooks.count(cb) == 0) { - // This hook was removed from the `cleanup_hooks_` set during another - // hook that was run earlier. Nothing to do here. - continue; - } - - cb.fun(cb.arg); - cleanup_hooks.erase(cb); - } - } - } - - std::unordered_set - cleanup_hooks; -}; - -napi_status napi_get_version(napi_env env, uint32_t* version) { - *version = NAPI_VERSION_EXPERIMENTAL; - return napi_clear_last_error(env); -} - -napi_status napi_add_env_cleanup_hook(napi_env env, void (*fun)(void* arg), - void* arg) { - env->state.env_data->AddCleanupHook(fun, arg); - return napi_clear_last_error(env); -} - -napi_status napi_remove_env_cleanup_hook(napi_env env, void (*fun)(void* arg), - void* arg) { - env->state.env_data->RemoveCleanupHook(fun, arg); - return napi_clear_last_error(env); -} - -// Warning: Keep in-sync with napi_status enum -static const char* error_messages[] = { - nullptr, - "Invalid argument", - "An object was expected", - "A string was expected", - "A string or symbol was expected", - "A function was expected", - "A number was expected", - "A boolean was expected", - "An array was expected", - "Unknown failure", - "An exception is pending", - "The async work item was cancelled", - "napi_escape_handle already called on scope", - "Invalid handle scope usage", - "Invalid callback scope usage", - "Thread-safe function queue is full", - "Thread-safe function handle is closing", - "A bigint was expected", - "A date was expected", - "An arraybuffer was expected", - "A detachable arraybuffer was expected", - "Napi deadlock", - "napi_no_external_buffers_allowed", - "napi_cannot_run_js", - "napi_handle_scope_empty", - "napi_memory_error", - "napi_promise_exception"}; - -#define NAPI_ARRAYSIZE(array) (sizeof(array) / sizeof(array[0])) - -napi_status napi_get_last_error_info(napi_env env, - const napi_extended_error_info** result) { - // you must update this assert to reference the last message - // in the napi_status enum each time a new error message is added. - // We don't have a napi_status_last as this would result in an ABI - // change each time a message was added. - const int last_status = napi_promise_exception; - - static_assert(NAPI_ARRAYSIZE(error_messages) == last_status + 1, - "Count of error messages must match count of error values"); - assert(env->state.last_error.error_code <= last_status); - - // Wait until someone requests the last error information to fetch the error - // message string - env->state.last_error.error_message = - error_messages[env->state.last_error.error_code]; - - *result = &(env->state.last_error); - return napi_ok; -} - -napi_env napi_new_env() { - napi_env env = new napi_env__{}; - env->state.env_data = new napi_env_data__{}; - return env; -} - -void napi_free_env(napi_env env) { - delete env->state.env_data; - delete env; -} \ No newline at end of file diff --git a/test-app/runtime/src/main/cpp/napi/primjs/napi_env.h b/test-app/runtime/src/main/cpp/napi/primjs/napi_env.h index 9a123453..7d9ff135 100644 --- a/test-app/runtime/src/main/cpp/napi/primjs/napi_env.h +++ b/test-app/runtime/src/main/cpp/napi/primjs/napi_env.h @@ -12,19 +12,15 @@ #ifndef SRC_NAPI_ENV_NAPI_ENV_H_ #define SRC_NAPI_ENV_NAPI_ENV_H_ -//#include "js_native_api.h" -// -//EXTERN_C_START -// -//NAPI_EXTERN napi_env napi_new_env(); -// -//NAPI_EXTERN void napi_free_env(napi_env); -// -//NAPI_EXTERN void napi_setup_loader(napi_env env, const char* name); -// -//NAPI_EXTERN napi_status primjs_execute_pending_jobs(napi_env env); -// -//EXTERN_C_END +#include "js_native_api.h" +EXTERN_C_START +NAPI_EXTERN napi_env napi_new_env(); + +NAPI_EXTERN void napi_free_env(napi_env); + +NAPI_EXTERN void napi_setup_loader(napi_env env, const char* name); + +EXTERN_C_END #endif // SRC_NAPI_ENV_NAPI_ENV_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/napi_env_quickjs.h b/test-app/runtime/src/main/cpp/napi/primjs/napi_env_quickjs.h index 88c860b9..095605a4 100644 --- a/test-app/runtime/src/main/cpp/napi/primjs/napi_env_quickjs.h +++ b/test-app/runtime/src/main/cpp/napi/primjs/napi_env_quickjs.h @@ -10,24 +10,10 @@ #ifndef SRC_NAPI_QUICKJS_NAPI_ENV_QUICKJS_H_ #define SRC_NAPI_QUICKJS_NAPI_ENV_QUICKJS_H_ -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus -#include "quickjs/include/quickjs.h" -#ifdef __cplusplus -} -#endif // __cplusplus - #include "js_native_api.h" +#include "quickjs.h" EXTERN_C_START -NAPI_EXTERN napi_env napi_new_env(); - -NAPI_EXTERN void napi_free_env(napi_env); - -NAPI_EXTERN void napi_setup_loader(napi_env env, const char* name); - - NAPI_EXTERN void napi_attach_quickjs(napi_env env, LEPUSContext* ctx); NAPI_EXTERN void napi_detach_quickjs(napi_env env); diff --git a/test-app/runtime/src/main/cpp/napi/primjs/napi_state.h b/test-app/runtime/src/main/cpp/napi/primjs/napi_state.h deleted file mode 100644 index 20b82448..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/napi_state.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2017 Node.js API collaborators. All Rights Reserved. - * - * Use of this source code is governed by a MIT license that can be - * found in the LICENSE file in the root of the source tree. - */ - -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. - -#ifndef SRC_NAPI_COMMON_NAPI_STATE_H_ -#define SRC_NAPI_COMMON_NAPI_STATE_H_ - -//#include "primjs-api.h" - -//typedef struct napi_env_data__* napi_env_data; -// -//struct napi_state__ { -// napi_extended_error_info last_error; -// napi_env_data env_data; -//}; -// -//inline napi_status napi_clear_last_error(napi_env env) { -// env->state->last_error.error_code = napi_ok; -// -// env->state->last_error.engine_error_code = 0; -// return napi_ok; -//} -// -//inline napi_status napi_set_last_error(napi_env env, napi_status error_code) { -// env->state->last_error.error_code = error_code; -// return error_code; -//} - -#endif // SRC_NAPI_COMMON_NAPI_STATE_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/primjs-api.cc b/test-app/runtime/src/main/cpp/napi/primjs/primjs-api.cc deleted file mode 100644 index 9dc08f37..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/primjs-api.cc +++ /dev/null @@ -1,2881 +0,0 @@ -/** - * Copyright (c) 2017 Node.js API collaborators. All Rights Reserved. - * - * Use of this source code is governed by a MIT license that can be - * found in the LICENSE file in the root of the source tree. - */ - -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. -#include "primjs-api.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "basic/log/logging.h" -#include "napi_env_quickjs.h" -#include "quickjs/include/quickjs-inner.h" - - -std::unordered_map napi_context__::rt_to_env_cache; -struct napi_callback_info__ { - napi_value newTarget; - napi_value thisArg; - napi_value *argv; - void *data; - uint16_t argc; -}; - -static inline void js_enter(napi_env env) { - env->js_enter_state++; -} - -static inline void js_exit(napi_env env) { - if (--env->js_enter_state <= 0) { - primjs_execute_pending_jobs(env); - } -} - -namespace { - napi_status napi_set_exception(napi_env env, LEPUSValue exception) { - if (env->ctx->last_exception) { - JS_FreeValue_Comp(env->ctx->ctx, *env->ctx->last_exception); - } - env->ctx->last_exception.reset(new LEPUSValue(exception)); - - env->ctx->last_exception_pVal.Reset(nullptr, exception, nullptr, - env->ctx->ctx, true); - - return napi_set_last_error(env, napi_pending_exception); - } - - napi_status napi_set_error_msg_code(napi_env env, napi_value error, - napi_value code, napi_value msg, - const char *code_cstring) { - { - LEPUSValue msg_value = JS_DupValue_Comp(env->ctx->ctx, ToJSValue(msg)); - env->ctx->CreateHandle(msg_value, true); - - CHECK_QJS(env, LEPUS_SetProperty(env->ctx->ctx, ToJSValue(error), - env->ctx->PROP_MESSAGE, msg_value) != -1); - } - - if (code || code_cstring) { - LEPUSValue code_value; - if (code == nullptr) { - code_value = LEPUS_NewString(env->ctx->ctx, code_cstring); - env->ctx->CreateHandle(code_value, true); - } else { - code_value = ToJSValue(code); - RETURN_STATUS_IF_FALSE(env, - LEPUS_IsString(code_value) || LEPUS_IsUndefined(code_value), - napi_string_expected); - - code_value = JS_DupValue_Comp(env->ctx->ctx, code_value); - } - - if (!LEPUS_IsUndefined(code_value)) { - CHECK_QJS(env, LEPUS_SetProperty(env->ctx->ctx, ToJSValue(error), - env->ctx->PROP_CODE, code_value) != -1); - } - - } - - return napi_ok; - } - - template - class ArgsConverter { - public: - ArgsConverter(size_t argc, In *argv) { - Out *destination = inline_; - if (argc > kMaxStackArgs) { - outOfLine_ = std::make_unique(argc); - destination = outOfLine_.get(); - } - - for (size_t i = 0; i < argc; ++i) { - destination[i] = Convert(argv + i); - } - } - - operator Out *() { return outOfLine_ ? outOfLine_.get() : inline_; } - - private: - constexpr static unsigned kMaxStackArgs = 8; - Out inline_[kMaxStackArgs]; - std::unique_ptr outOfLine_; - }; -} // namespace - -namespace qjsimpl { - - enum NativeType { - External, Wrapper - }; - - class NativeInfo final { - public: - NativeInfo(napi_env env, NativeType type) - : _env(env), _type(type), _data(nullptr) {} - - std::list::const_iterator AddWeakRef(NAPIPersistent *ref) { - return _weakRefs.insert(_weakRefs.end(), ref); - } - - void RemoveWeakRef(std::list::const_iterator iter) { - _weakRefs.erase(iter); - } - - napi_env Env() const { return _env; } - - void Data(void *value) { _data = value; } - - void *Data() const { return _data; } - - NativeType Type() const { return _type; } - - static bool IsInstance(LEPUSClassID id) { return id == class_id; } - - static NativeInfo *Get(LEPUSValue val) { - return static_cast(LEPUS_GetOpaque(val, class_id)); - } - - static LEPUSClassID ClassId(napi_env env) { - static std::once_flag once_flag; - std::call_once(once_flag, [&] { LEPUS_NewClassID(&class_id); }); - auto rt = LEPUS_GetRuntime(env->ctx->ctx); - if (!LEPUS_IsRegisteredClass(rt, class_id)) { - static LEPUSClassDef def = {.class_name = "NAPIMagicNative", - .finalizer = NativeInfo::OnFinalize}; - if (LEPUS_NewClass(rt, class_id, &def) != 0) { - return 0; - } - } - - return class_id; - } - - private: - ~NativeInfo() { - // ref will remove itself when finalize, so copy is needed - for (NAPIPersistent *ref: std::vector( - std::begin(_weakRefs), std::end(_weakRefs))) { - NAPIPersistent::OnFinalize(ref); - } - } - - private: - const napi_env _env; - const NativeType _type; - - void *_data; - std::list _weakRefs; - - static LEPUSClassID class_id; - - static void OnFinalize(LEPUSRuntime *rt, LEPUSValue val) { - NativeInfo *info = static_cast(LEPUS_GetOpaque(val, class_id)); - LEPUS_SetOpaque(val, nullptr); - delete info; - } - }; - - LEPUSClassID NativeInfo::class_id = 0; - - class External { - public: - static LEPUSValue Create(napi_env env, NativeInfo **result) { - LEPUSClassID id = NativeInfo::ClassId(env); - if (!id) { - return LEPUS_ThrowInternalError(env->ctx->ctx, - "failed to create External Class"); - } - LEPUSValue object = LEPUS_NewObjectClass(env->ctx->ctx, id); - if (!LEPUS_IsException(object)) { - NativeInfo *info = new NativeInfo(env, NativeType::External); - LEPUS_SetOpaque(object, info); - *result = info; - } - return object; - } - }; - - class Wrapper { - public: - static LEPUSValue Create(napi_env env, LEPUSValue proto) { - LEPUSClassID id = NativeInfo::ClassId(env); - if (!id) { - return LEPUS_ThrowInternalError(env->ctx->ctx, - "failed to create Wrapper Class"); - } - LEPUSValue object = LEPUS_NewObjectProtoClass(env->ctx->ctx, proto, id); - if (!LEPUS_IsException(object)) { - LEPUS_SetOpaque(object, new NativeInfo(env, NativeType::Wrapper)); - } - return object; - } - }; - -// Wrapper around v8impl::Persistent that implements reference counting. - class RefBase : protected Finalizer, RefTracker { - protected: - RefBase(napi_env env, uint32_t initial_refcount, bool delete_self, - napi_finalize finalize_callback, void *finalize_data, - void *finalize_hint) - : Finalizer(env, finalize_callback, finalize_data, finalize_hint), - _refcount(initial_refcount), - _delete_self(delete_self), - _is_self_destroying(false) { - Link(finalize_callback == nullptr ? &env->ctx->reflist - : &env->ctx->finalizing_reflist); - } - - public: - static RefBase *New(napi_env env, uint32_t initial_refcount, bool delete_self, - napi_finalize finalize_callback, void *finalize_data, - void *finalize_hint) { - return new RefBase(env, initial_refcount, delete_self, finalize_callback, - finalize_data, finalize_hint); - } - - virtual ~RefBase() { Unlink(); } - - inline void *Data() { return _finalize_data; } - - // Delete is called in 2 ways. Either from the finalizer or - // from one of Unwrap or napi_delete_reference. - // - // When it is called from Unwrap or napi_delete_reference we only - // want to do the delete if the finalizer has already run or - // cannot have been queued to run (ie the reference count is > 0), - // otherwise we may crash when the finalizer does run. - // If the finalizer may have been queued and has not already run - // delay the delete until the finalizer runs by not doing the delete - // and setting _delete_self to true so that the finalizer will - // delete it when it runs. - // - // The second way this is called is from - // the finalizer and _delete_self is set. In this case we - // know we need to do the deletion so just do it. - static inline void Delete(RefBase *reference) { - if ((reference->RefCount() != 0) || (reference->_delete_self) || - (reference->_finalize_ran)) { - delete reference; - } else { - // defer until finalizer runs as - // it may alread be queued - reference->_delete_self = true; - } - } - - inline uint32_t Ref() { return ++_refcount; } - - inline uint32_t Unref() { - if (_refcount == 0) { - return 0; - } - return --_refcount; - } - - inline uint32_t RefCount() { return _refcount; } - - protected: - inline void Finalize(bool is_env_teardown = false) override { - if (is_env_teardown && RefCount() > 0) _refcount = 0; - - // There are cases where we want to avoid the reentrance of Finalize ( - // causing double-free): - // * When a wrapped object holds its own strong reference (either directly - // or indirectly) - // * (JSCore specific) when the destruction of a strong reference triggers - // garbage collection - // If we are sure this is getting deleted soon, there is no need for the - // finalizer to proceed. - if (_is_self_destroying && !is_env_teardown) { - return; - } - if (is_env_teardown) { - _is_self_destroying = true; - } - - if (_finalize_callback != nullptr) { - // This ensures that we never call the finalizer twice. - napi_finalize fini = _finalize_callback; - _finalize_callback = nullptr; - _env->ctx->CallFinalizer(fini, _finalize_data, _finalize_hint); - } - - // this is safe because if a request to delete the reference - // is made in the finalize_callback it will defer deletion - // to this block and set _delete_self to true - if (_delete_self || is_env_teardown) { - Delete(this); - } else { - _finalize_ran = true; - } - } - - private: - uint32_t _refcount; - bool _delete_self; - bool _is_self_destroying; - }; - - class Reference : public RefBase { - protected: - template - Reference(napi_env env, LEPUSValueConst value, NativeInfo *native_info, - Args &&... args) - : RefBase(env, std::forward(args)...), - _persistent(env, value, native_info, env->ctx->ctx) { - if (RefCount() == 0) { - _persistent.SetWeak(this, FinalizeCallback); - } - } - - public: - static inline Reference *New(napi_env env, LEPUSValueConst value, - NativeInfo *native_info, - uint32_t initial_refcount, bool delete_self, - napi_finalize finalize_callback = nullptr, - void *finalize_data = nullptr, - void *finalize_hint = nullptr) { - return new Reference(env, value, native_info, initial_refcount, delete_self, - finalize_callback, finalize_data, finalize_hint); - } - - void Finalize(bool is_env_teardown = false) override { - _persistent.Reset(true); - RefBase::Finalize(is_env_teardown); - } - - static inline void Delete(RefBase *reference) { - static_cast(reference)->_persistent.Reset(true); - RefBase::Delete(reference); - } - - inline uint32_t Ref() { - uint32_t refcount = RefBase::Ref(); - if (refcount == 1) { - _persistent.ClearWeak(); - } - return refcount; - } - - virtual ~Reference() { _persistent.Reset(true); } - - inline uint32_t Unref() { - uint32_t old_refcount = RefCount(); - uint32_t refcount = RefBase::Unref(); - if (old_refcount == 1 && refcount == 0) { - _persistent.SetWeak(this, FinalizeCallback); - } - return refcount; - } - - inline napi_value Get() { - return _persistent.IsEmpty() ? nullptr - : _env->ctx->CreateHandle(_persistent.Value()); - } - - private: - static void FinalizeCallback(void *data) { - Reference *r = static_cast(data); - r->_persistent.Reset(); - r->Finalize(); - } - - NAPIPersistent _persistent; - }; - - enum WrapType { - retrievable, anonymous - }; - - template - inline napi_status Wrap(napi_env env, napi_value js_object, void *native_object, - napi_finalize finalize_cb, void *finalize_hint, - napi_ref *result) { - LEPUSValueConst obj = ToJSValue(js_object); - - NativeInfo *info = NativeInfo::Get(obj); - - if (wrap_type == retrievable) { - RETURN_STATUS_IF_FALSE(env, - info != nullptr && - info->Type() == NativeType::Wrapper && - info->Data() == nullptr, - napi_invalid_arg); - } else { - // If no finalize callback is provided, we error out. - CHECK_ARG(env, finalize_cb); - } - - Reference *reference = nullptr; - if (result != nullptr) { - // The returned reference should be deleted via napi_delete_reference() - // ONLY in response to the finalize callback invocation. (If it is deleted - // before then, then the finalize callback will never be invoked.) - // Therefore a finalize callback is required when returning a reference. - CHECK_ARG(env, finalize_cb); - reference = Reference::New(env, obj, info, 0, false, finalize_cb, - native_object, finalize_hint); - *result = reinterpret_cast(reference); - } else { - // Create a self-deleting reference. - reference = - Reference::New(env, obj, info, 0, true, finalize_cb, native_object, - finalize_cb == nullptr ? nullptr : finalize_hint); - } - - if (wrap_type == retrievable) { - info->Data(reference); - } - - return napi_clear_last_error(env); - } - - enum UnwrapAction { - KeepWrap, RemoveWrap - }; - - inline static napi_status Unwrap(napi_env env, napi_value js_object, - void **result, UnwrapAction action) { - if (action == KeepWrap) { - CHECK_ARG(env, result); - } - - LEPUSValue obj = ToJSValue(js_object); - NativeInfo *info = NativeInfo::Get(obj); - - if (!info || info->Type() != qjsimpl::NativeType::Wrapper) { - if (result) { - *result = nullptr; - } - return napi_clear_last_error(env); - } - - Reference *reference = static_cast(info->Data()); - - if (result) { - *result = reference->Data(); - } - - if (action == RemoveWrap) { - info->Data(nullptr); - Reference::Delete(reference); - } - - return napi_clear_last_error(env); - } - - inline static Atom qjsAtomFromPropertyDescriptor( - napi_env env, const napi_property_descriptor &p) { - if (p.utf8name != nullptr) { - return Atom(env, env->ctx->ctx, p.utf8name); - } else { - return Atom(env, env->ctx->ctx, ToJSValue(p.name)); - } - } - - inline static uint8_t qjsFlagFromPropertyDescriptor( - napi_property_attributes attributes) { - uint8_t flags = 0; - if (attributes & napi_writable) { - flags |= LEPUS_PROP_WRITABLE; - } - if (attributes & napi_enumerable) { - flags |= LEPUS_PROP_ENUMERABLE; - } - if (attributes & napi_configurable) { - flags |= LEPUS_PROP_CONFIGURABLE; - } - return flags; - } - - inline NAPIPersistent::NAPIPersistent(napi_env env, LEPUSValueConst value, - NativeInfo *native_info, - LEPUSContext *ctx, bool is_weak) - : PersistentBase( - PersistentBase::New(LEPUS_GetRuntime(ctx), value, is_weak)), - _env(env), - _empty(false), - _value(JS_DupValue_Comp(env->ctx->ctx, value)), - _native_info(native_info), - _ctx(ctx) {} - - inline NAPIPersistent::NAPIPersistent(napi_env env, JSAtom atom, - NativeInfo *native_info, - LEPUSContext *ctx, bool is_weak) - : PersistentBase(PersistentBase::New(LEPUS_GetRuntime(ctx), - LEPUS_MKVAL(LEPUS_TAG_Atom, (int) atom), - is_weak)), - _env(env), - _empty(false), - _value(LEPUS_MKVAL(LEPUS_TAG_Atom, (int) atom)), - _native_info(native_info), - _ctx(ctx) {} - - void NAPIPersistent::Reset(bool for_gc) { - if (_empty) { - return; - } - if (_ctx != nullptr && LEPUS_IsGCMode(_ctx)) { - PersistentBase::Reset(_ctx); - _env = nullptr; - _empty = true; - _native_info = nullptr; - } else if (!for_gc) { - if (_weak_info) { - ResetWeakInfo(); - } else { - JS_FreeValue_Comp(_env->ctx->ctx, _value); - } - _env = nullptr; - _empty = true; - _native_info = nullptr; - } - } - - void NAPIPersistent::Reset(napi_env env, LEPUSValueConst value, - NativeInfo *native_info, LEPUSContext *ctx, - bool for_gc) { - _ctx = ctx; - if (_ctx != nullptr && LEPUS_IsGCMode(_ctx)) { // gc - PersistentBase::Reset(_ctx, value, false); - _empty = false; - _env = env; - _value = value; - _native_info = native_info; - } else if (!for_gc) { - Reset(); - _empty = false; - _env = env; - _value = JS_DupValue_Comp(env->ctx->ctx, value); - _native_info = native_info; - } - } - - void NAPIPersistent::Reset(napi_env env, LEPUSContext *ctx, JSAtom atom) { - _env = env; - _ctx = ctx; - if (_ctx != nullptr && LEPUS_IsGCMode(_ctx)) { - PersistentBase::Reset(_ctx, LEPUS_MKVAL(LEPUS_TAG_Atom, (int) atom), false); - _empty = false; - } - } - - void NAPIPersistent::SetWeak(void *data, void (*cb)(void *)) { - if (_ctx != nullptr && LEPUS_IsGCMode(_ctx)) { - SetGlobalWeak(LEPUS_GetRuntime(_ctx), this->val_, data, cb); - } else { - assert(!_empty); - if (_weak_info) { - _weak_info->cb_arg = data; - _weak_info->cb = cb; - } else { - _weak_info.reset( - new WeakInfo{_get_native_info()->AddWeakRef(this), cb, data}); - JS_FreeValue_Comp(_env->ctx->ctx, _value); - } - } - } - - void NAPIPersistent::ClearWeak() { - if (_ctx != nullptr && LEPUS_IsGCMode(_ctx)) { - ClearGlobalWeak(LEPUS_GetRuntime(_ctx), this->val_); - } else { - JS_DupValue_Comp(_env->ctx->ctx, _value); - ResetWeakInfo(); - } - } - - LEPUSValue NAPIPersistent::Value() const { - if (_ctx != nullptr && LEPUS_IsGCMode(_ctx)) { - return Get(); - } else { - return JS_DupValue_Comp(_env->ctx->ctx, _value); - } - } - - void NAPIPersistent::OnFinalize(NAPIPersistent *ref) { - auto cb = ref->_weak_info->cb; - auto cb_arg = ref->_weak_info->cb_arg; - ref->Reset(); - cb(cb_arg); - } - - void NAPIPersistent::ResetWeakInfo() { - assert(!_empty); - _get_native_info()->RemoveWeakRef(_weak_info->weak_iter); - _weak_info.reset(); - } - - NativeInfo *NAPIPersistent::_get_native_info() { - assert(!_empty); - if (!_native_info) { - LEPUSValue finalizer = - LEPUS_GetProperty(_env->ctx->ctx, _value, _env->ctx->PROP_FINALIZER); - assert(!LEPUS_IsException(finalizer)); - if (LEPUS_IsUndefined(finalizer)) { - NativeInfo *info; - finalizer = External::Create(_env, &info); - assert(!LEPUS_IsException(finalizer)); - int ret = LEPUS_DefinePropertyValue( - _env->ctx->ctx, _value, _env->ctx->PROP_FINALIZER, finalizer, 0); - (void) ret; - assert(ret != -1); - _native_info = info; - } else { - _native_info = qjsimpl::NativeInfo::Get(finalizer); - JS_FreeValue_Comp(_env->ctx->ctx, finalizer); - } - } - return _native_info; - } - -} // namespace qjsimpl - -namespace { - static inline LEPUSValue CallJSFunctionWithNAPI(napi_env env, napi_callback cb, - napi_callback_info cbinfo) { - napi_value result; - std::unique_ptr exception; - env->ctx->CallIntoModule([&](napi_env env) { result = cb(env, cbinfo); }, - [&](napi_env env, LEPUSValue exc) { - exception.reset(new LEPUSValue(exc)); - }); - - if (exception) { - env->ctx->CreateHandle(*exception, true); - return LEPUS_Throw(env->ctx->ctx, *exception); - } - - return result ? JS_DupValue_Comp(env->ctx->ctx, ToJSValue(result)) - : LEPUS_UNDEFINED; - } -} // namespace - -namespace qjsimpl { - typedef struct FunctionDataWrapper { - void *data; - } FunctionDataWrapper; -} - -napi_status napi_create_function(napi_env env, const char *utf8name, - size_t length, napi_callback cb, - void *callback_data, napi_value *result) { - LEPUSContext *ctx = env->ctx->ctx; - - auto dataWrapper = new qjsimpl::FunctionDataWrapper(); - dataWrapper->data = callback_data; - - LEPUSValue data[] = { - LEPUS_MKPTR(LEPUS_TAG_LEPUS_CPOINTER, env), - LEPUS_MKPTR(LEPUS_TAG_LEPUS_CPOINTER, reinterpret_cast(cb)), - LEPUS_MKPTR(LEPUS_TAG_LEPUS_CPOINTER, dataWrapper)}; - LEPUSValue fun = LEPUS_NewCFunctionData( - ctx, - [](LEPUSContext *ctx, LEPUSValueConst this_val, int argc, - LEPUSValueConst *argv, int magic, - LEPUSValue *func_data) -> LEPUSValue { - napi_env env = - reinterpret_cast(LEPUS_VALUE_GET_CPOINTER(func_data[0])); - napi_callback cb = reinterpret_cast( - LEPUS_VALUE_GET_CPOINTER(func_data[1])); - auto dataWrapper = reinterpret_cast LEPUS_VALUE_GET_CPOINTER( - func_data[2]); - - napi_clear_last_error(env); - - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - - ArgsConverter args(argc, argv); - - napi_callback_info__ cbinfo{}; - cbinfo.thisArg = ToNapi(&this_val); - cbinfo.newTarget = nullptr; - cbinfo.argc = argc; - cbinfo.argv = args; - cbinfo.data = dataWrapper->data; - - return CallJSFunctionWithNAPI(env, cb, &cbinfo); - }, - 0, 0, 3, data); - - napi_value external; - napi_create_external(env, dataWrapper, [](napi_env, void *data, void *hint) { - if (data) { - auto dataWrapper = reinterpret_cast(data); - delete dataWrapper; - } - }, dataWrapper, &external); - napi_set_named_property(env, ToNapi(&fun), "__qjs::finalizer__", external); - - CHECK_QJS(env, !LEPUS_IsException(fun)); - - *result = env->ctx->CreateHandle(fun); - - if (utf8name) { - // ignore error - LEPUSValue str = LEPUS_NewString(ctx, utf8name); - env->ctx->CreateHandle(str, true); - LEPUS_DefinePropertyValue(ctx, fun, env->ctx->PROP_NAME, str, - LEPUS_PROP_CONFIGURABLE); - } - - return napi_clear_last_error(env); -} - -static __attribute__((unused)) std::string GetExceptionMessage( - LEPUSContext *ctx, LEPUSValueConst exception_val) { - LEPUSValue val; - const char *stack; - const char *message = LEPUS_ToCString(ctx, exception_val); - std::string ret = "quickjs: "; - if (message) { - ret += message; - ret += "\n"; - JS_FreeCString_Comp(ctx, message); - } - - bool is_error = LEPUS_IsError(ctx, exception_val); - if (is_error) { - val = LEPUS_GetPropertyStr(ctx, exception_val, "stack"); - if (!LEPUS_IsUndefined(val)) { - stack = LEPUS_ToCString(ctx, val); - ret += stack; - JS_FreeCString_Comp(ctx, stack); - } - JS_FreeValue_Comp(ctx, val); - } - return ret; -} - -napi_status napi_define_class(napi_env env, const char *utf8name, size_t length, - napi_callback cb, void *data, - size_t property_count, - const napi_property_descriptor *properties, napi_value *result) { - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - - LEPUSContext *ctx = env->ctx->ctx; - - qjsimpl::Value proto(ctx, LEPUS_NewObject(ctx)); - - CHECK_QJS(env, !LEPUS_IsException(proto)); - - struct ClassData { - napi_callback cb; - void *data; - LEPUSValue proto; - qjsimpl::NAPIPersistent p_proto; - - ~ClassData() { p_proto.Reset(true); } - }; - - qjsimpl::NativeInfo *ctor_info; - qjsimpl::Value ctor_magic(ctx, qjsimpl::External::Create(env, &ctor_info)); - CHECK_QJS(env, !LEPUS_IsException(ctor_magic)); - - ClassData *ctor_magic_data = - new ClassData{.cb = cb, .data = data, .proto = proto.dup()}; - if (LEPUS_IsGCMode(env->ctx->ctx)) { - ctor_magic_data->p_proto.Reset(env, ctor_magic_data->proto, nullptr, - env->ctx->ctx, true); - } - ctor_info->Data(ctor_magic_data); - qjsimpl::Reference::New( - env, ctor_magic, ctor_info, 0, true, - [](napi_env env, void *data, void *hint) { - ClassData *ctor_magic_data = static_cast(data); - JS_FreeValue_Comp(env->ctx->ctx, ctor_magic_data->proto); - delete ctor_magic_data; - static_cast(hint)->Data(nullptr); - }, - ctor_magic_data, ctor_info); - LEPUSValue cfunction = LEPUS_NewCFunctionMagic( - ctx, - [](LEPUSContext *ctx, LEPUSValueConst new_target, int argc, - LEPUSValueConst *argv, int magic) -> LEPUSValue { - JSAtom prop_ctor_magic = LEPUS_NewAtom(ctx, "@#ctor@#"); - LEPUSValue ctor_magic = - LEPUS_GetProperty(ctx, new_target, prop_ctor_magic); - JS_FreeAtom_Comp(ctx, prop_ctor_magic); - if (LEPUS_IsException(ctor_magic) || LEPUS_IsUndefined(ctor_magic)) { - if (LEPUS_IsObject(new_target)) { - LOGI("new_target is an object"); - } - LOGI("new_target ptr is " - << LEPUS_VALUE_GET_PTR(new_target) << ", prop_ctor_magic is " - << prop_ctor_magic << ", function magic is " << magic - << ", exception message: " - << GetExceptionMessage(ctx, ctor_magic)); - return ctor_magic; - } - qjsimpl::NativeInfo *info = qjsimpl::NativeInfo::Get(ctor_magic); - JS_FreeValue_Comp(ctx, ctor_magic); - if (!(info != nullptr && - info->Type() == qjsimpl::NativeType::External && info->Data())) { - LOGI("ctor_magic native_info error return undefined, info is " - << info); - return LEPUS_UNDEFINED; - } - napi_env env = info->Env(); - ClassData *class_data = static_cast(info->Data()); - LEPUSValue this_val = qjsimpl::Wrapper::Create(env, class_data->proto); - - if (LEPUS_IsException(this_val)) { - LOGI("create Wrapper return exception"); - return this_val; - } - napi_clear_last_error(env); - - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - - ArgsConverter args(argc, argv); - - napi_callback_info__ cbinfo{}; - cbinfo.thisArg = env->ctx->CreateHandle(this_val); - cbinfo.newTarget = ToNapi(&new_target); - cbinfo.argc = argc; - cbinfo.argv = args; - cbinfo.data = class_data->data; - - auto result = CallJSFunctionWithNAPI(env, class_data->cb, &cbinfo); - if (LEPUS_IsUndefined(result)) { - LOGI("napi callback return undefined"); - } - return result; - }, - utf8name, 0, LEPUS_CFUNC_constructor_magic, env->ctx->PROP_CTOR_MAGIC); - - qjsimpl::Value constructor(ctx, cfunction); - - auto ctor_handle = env->ctx->CreateHandle(cfunction, true); - - if (LEPUS_IsException(constructor)) { - napi_status status = - napi_set_exception(env, LEPUS_GetException(env->ctx->ctx)); - LOGI(GetExceptionMessage(env->ctx->ctx, *env->ctx->last_exception)); - return status; - } - - if (LEPUS_DefinePropertyValue(ctx, constructor, env->ctx->PROP_CTOR_MAGIC, - ctor_magic.move(), 0) == -1) { - napi_status status = - napi_set_exception(env, LEPUS_GetException(env->ctx->ctx)); - LOGI(GetExceptionMessage(env->ctx->ctx, *env->ctx->last_exception)); - return status; - } - - - CHECK_QJS( - env, LEPUS_DefinePropertyValue(ctx, constructor, env->ctx->PROP_PROTOTYPE, - proto.dup(), 0) != -1); - CHECK_QJS(env, LEPUS_DefinePropertyValue( - ctx, proto, env->ctx->PROP_CONSTRUCTOR, constructor.dup(), - LEPUS_PROP_WRITABLE | LEPUS_PROP_CONFIGURABLE) != -1); - - int instancePropertyCount{0}; - int staticPropertyCount{0}; - for (size_t i = 0; i < property_count; i++) { - if ((properties[i].attributes & napi_static) != 0) { - staticPropertyCount++; - } else { - instancePropertyCount++; - } - } - - std::vector staticDescriptors{}; - std::vector instanceDescriptors{}; - staticDescriptors.reserve(staticPropertyCount); - instanceDescriptors.reserve(instancePropertyCount); - - for (size_t i = 0; i < property_count; i++) { - if ((properties[i].attributes & napi_static) != 0) { - staticDescriptors.push_back(properties[i]); - } else { - instanceDescriptors.push_back(properties[i]); - } - } - - if (staticPropertyCount > 0) { - LEPUSValue ctor_val = constructor; - - CHECK_NAPI(napi_define_properties(env, ToNapi(&ctor_val), - staticDescriptors.size(), - staticDescriptors.data())); - } - - if (instancePropertyCount > 0) { - LEPUSValue proto_val = proto; - - CHECK_NAPI(napi_define_properties(env, ToNapi(&proto_val), - instanceDescriptors.size(), - instanceDescriptors.data())); - } - - - *result = scope.Escape(ctor_handle); - - return napi_clear_last_error(env); -} - -napi_status napi_get_property_names_gc(napi_env env, napi_value object, - napi_value *result) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSPropertyEnum *props = nullptr; - HandleScope func_scope(ctx, &props, HANDLE_TYPE_HEAP_OBJ); - uint32_t props_length; - CHECK_QJS(env, LEPUS_GetOwnPropertyNames( - ctx, &props, &props_length, ToJSValue(object), - LEPUS_GPN_STRING_MASK | LEPUS_GPN_SYMBOL_MASK | - LEPUS_GPN_ENUM_ONLY | LEPUS_PROP_THROW) != -1); - - std::vector values; - values.reserve(props_length); - for (uint32_t i = 0; i < props_length; i++) { - values.emplace_back(LEPUS_AtomToValue(ctx, props[i].atom)); - func_scope.PushHandle(&values[i], HANDLE_TYPE_LEPUS_VALUE); - } - LEPUSValue arr = LEPUS_NewArrayWithValue(ctx, props_length, values.data()); - - CHECK_QJS(env, !LEPUS_IsException(arr)); - *result = env->ctx->CreateHandle(arr); - return napi_clear_last_error(env); -} - -napi_status napi_get_property_names(napi_env env, - napi_value object, - napi_value *result) { - LEPUSContext *ctx = env->ctx->ctx; - if (LEPUS_IsGCMode(ctx)) { - return napi_get_property_names_gc(env, object, result); - } - LEPUSPropertyEnum *props = nullptr; - uint32_t props_length; - CHECK_QJS(env, LEPUS_GetOwnPropertyNames( - ctx, &props, &props_length, ToJSValue(object), - LEPUS_GPN_STRING_MASK | LEPUS_GPN_SYMBOL_MASK | - LEPUS_GPN_ENUM_ONLY | LEPUS_PROP_THROW) != -1); - - std::vector values; - values.reserve(props_length); - for (uint32_t i = 0; i < props_length; i++) { - values.emplace_back(LEPUS_AtomToValue(ctx, props[i].atom)); - JS_FreeAtom_Comp(ctx, props[i].atom); - } - js_free_comp(ctx, props); - LEPUSValue arr = LEPUS_NewArrayWithValue(ctx, props_length, values.data()); - for (LEPUSValue v: values) { - JS_FreeValue_Comp(ctx, v); - } - - CHECK_QJS(env, !LEPUS_IsException(arr)); - *result = env->ctx->CreateHandle(arr); - return napi_clear_last_error(env); -} - -napi_status napi_get_all_property_names(napi_env env, - napi_value object, - napi_key_collection_mode key_mode, - napi_key_filter key_filter, - napi_key_conversion key_conversion, - napi_value *result) { - LEPUSContext *ctx = env->ctx->ctx; - if (LEPUS_IsGCMode(ctx)) { - return napi_get_property_names_gc(env, object, result); - } - LEPUSPropertyEnum *props = nullptr; - uint32_t props_length; - CHECK_QJS(env, LEPUS_GetOwnPropertyNames( - ctx, &props, &props_length, ToJSValue(object), - LEPUS_GPN_STRING_MASK | LEPUS_GPN_SYMBOL_MASK | - LEPUS_GPN_ENUM_ONLY | LEPUS_PROP_THROW) != -1); - - std::vector values; - values.reserve(props_length); - for (uint32_t i = 0; i < props_length; i++) { - values.emplace_back(LEPUS_AtomToValue(ctx, props[i].atom)); - JS_FreeAtom_Comp(ctx, props[i].atom); - } - js_free_comp(ctx, props); - LEPUSValue arr = LEPUS_NewArrayWithValue(ctx, props_length, values.data()); - for (LEPUSValue v: values) { - JS_FreeValue_Comp(ctx, v); - } - - CHECK_QJS(env, !LEPUS_IsException(arr)); - *result = env->ctx->CreateHandle(arr); - return napi_clear_last_error(env); -} - -napi_status napi_set_property(napi_env env, napi_value object, napi_value key, - napi_value value) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue obj = ToJSValue(object); - qjsimpl::Atom prop_atom(env, ctx, ToJSValue(key)); - CHECK_QJS(env, prop_atom.IsValid()); - int result = LEPUS_SetProperty(ctx, obj, prop_atom, - JS_DupValue_Comp(ctx, ToJSValue(value))); - CHECK_QJS(env, result != -1); - return napi_clear_last_error(env); -} - -napi_status napi_has_property(napi_env env, napi_value object, napi_value key, - bool *result) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue obj = ToJSValue(object); - qjsimpl::Atom prop_atom(env, ctx, ToJSValue(key)); - CHECK_QJS(env, prop_atom.IsValid()); - int result_has = LEPUS_HasProperty(ctx, obj, prop_atom); - CHECK_QJS(env, result_has != -1); - *result = result_has; - return napi_clear_last_error(env); -} - -napi_status napi_get_property(napi_env env, napi_value object, napi_value key, - napi_value *result) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue obj = ToJSValue(object); - qjsimpl::Atom prop_atom(env, ctx, ToJSValue(key)); - CHECK_QJS(env, prop_atom.IsValid()); - LEPUSValue val = LEPUS_GetProperty(ctx, obj, prop_atom); - CHECK_QJS(env, !LEPUS_IsException(val)); - *result = env->ctx->CreateHandle(val); - return napi_clear_last_error(env); -} - -napi_status napi_delete_property(napi_env env, napi_value object, - napi_value key, bool *result) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue obj = ToJSValue(object); - qjsimpl::Atom prop_atom(env, ctx, ToJSValue(key)); - CHECK_QJS(env, prop_atom.IsValid()); - int result_delete = - LEPUS_DeleteProperty(ctx, obj, prop_atom, LEPUS_PROP_THROW); - CHECK_QJS(env, result_delete != -1); - if (result) { - *result = result_delete; - } - return napi_clear_last_error(env); -} - -napi_status napi_has_own_property(napi_env env, napi_value object, - napi_value key, bool *result) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue obj = ToJSValue(object); - qjsimpl::Atom prop_atom(env, ctx, ToJSValue(key)); - CHECK_QJS(env, prop_atom.IsValid()); - int result_has = LEPUS_GetOwnProperty(ctx, nullptr, obj, prop_atom); - CHECK_QJS(env, result_has != -1); - *result = result_has; - return napi_clear_last_error(env); -} - -napi_status napi_set_named_property(napi_env env, napi_value object, - const char *utf8name, napi_value value) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue obj = ToJSValue(object); - qjsimpl::Atom prop_atom(env, ctx, LEPUS_NewAtom(ctx, utf8name)); - CHECK_QJS(env, prop_atom.IsValid()); - int result = LEPUS_SetProperty(ctx, obj, prop_atom, - JS_DupValue_Comp(ctx, ToJSValue(value))); - CHECK_QJS(env, result != -1); - return napi_clear_last_error(env); -} - -napi_status napi_has_named_property(napi_env env, napi_value object, - const char *utf8name, bool *result) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue obj = ToJSValue(object); - qjsimpl::Atom prop_atom(env, ctx, utf8name); - CHECK_QJS(env, prop_atom.IsValid()); - int result_has = LEPUS_HasProperty(ctx, obj, prop_atom); - CHECK_QJS(env, result_has != -1); - *result = result_has; - return napi_clear_last_error(env); -} - -napi_status napi_get_named_property(napi_env env, napi_value object, - const char *utf8name, napi_value *result) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue obj = ToJSValue(object); - qjsimpl::Atom prop_atom(env, ctx, utf8name); - CHECK_QJS(env, prop_atom.IsValid()); - LEPUSValue val = LEPUS_GetProperty(ctx, obj, prop_atom); - CHECK_QJS(env, !LEPUS_IsException(val)); - *result = env->ctx->CreateHandle(val); - return napi_clear_last_error(env); -} - -napi_status napi_set_element(napi_env env, napi_value object, uint32_t index, - napi_value value) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue obj = ToJSValue(object); - int result = LEPUS_SetPropertyUint32(ctx, obj, index, - JS_DupValue_Comp(ctx, ToJSValue(value))); - CHECK_QJS(env, result != -1); - return napi_clear_last_error(env); -} - -napi_status napi_has_element(napi_env env, napi_value object, uint32_t index, - bool *result) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue obj = ToJSValue(object); - LEPUSValue val = LEPUS_GetPropertyUint32(ctx, obj, index); - CHECK_QJS(env, !LEPUS_IsException(val)); - *result = !LEPUS_IsUndefined(val); - JS_FreeValue_Comp(ctx, val); - return napi_clear_last_error(env); -} - -napi_status napi_get_element(napi_env env, napi_value object, uint32_t index, - napi_value *result) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue obj = ToJSValue(object); - LEPUSValue val = LEPUS_GetPropertyUint32(ctx, obj, index); - - CHECK_QJS(env, !LEPUS_IsException(val)); - *result = env->ctx->CreateHandle(val); - return napi_clear_last_error(env); -} - -napi_status napi_delete_element(napi_env env, napi_value object, uint32_t index, - bool *result) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue obj = ToJSValue(object); - qjsimpl::Atom prop_atom(env, ctx, LEPUS_NewAtomUInt32(ctx, index)); - CHECK_QJS(env, prop_atom.IsValid()); - int result_delete = - LEPUS_DeleteProperty(ctx, obj, prop_atom, LEPUS_PROP_THROW); - CHECK_QJS(env, result_delete != -1); - *result = result_delete; - return napi_clear_last_error(env); -} - -napi_status napi_define_properties(napi_env env, napi_value object, - size_t property_count, - const napi_property_descriptor *properties) { - if (property_count > 0) { - CHECK_ARG(env, properties); - } - - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue obj = ToJSValue(object); - - for (size_t i = 0; i < property_count; i++) { - const napi_property_descriptor &p = properties[i]; - qjsimpl::Atom prop_atom = qjsimpl::qjsAtomFromPropertyDescriptor(env, p); - CHECK_QJS(env, prop_atom.IsValid()); - uint8_t flags = qjsimpl::qjsFlagFromPropertyDescriptor(p.attributes); - if (p.getter != nullptr || p.setter != nullptr) { - LEPUSValue getter = LEPUS_UNDEFINED; - char name_buf[128]; - memset(name_buf, 0, sizeof(name_buf)); - if (p.getter) { - napi_value napi_getter; - if (p.utf8name) { - snprintf(name_buf, sizeof(name_buf), "get %s", p.utf8name); - } - CHECK_NAPI(napi_create_function(env, name_buf, NAPI_AUTO_LENGTH, - p.getter, p.data, &napi_getter)); - getter = JS_DupValue_Comp(ctx, ToJSValue(napi_getter)); - } - LEPUSValue setter = LEPUS_UNDEFINED; - if (p.setter) { - napi_value napi_setter; - if (p.utf8name) { - snprintf(name_buf, sizeof(name_buf), "set %s", p.utf8name); - } - CHECK_NAPI(napi_create_function(env, name_buf, NAPI_AUTO_LENGTH, - p.setter, p.data, &napi_setter)); - setter = JS_DupValue_Comp(ctx, ToJSValue(napi_setter)); - } - CHECK_QJS(env, LEPUS_DefinePropertyGetSet(ctx, obj, prop_atom, getter, - setter, flags) != -1); - } else if (p.method != nullptr) { - napi_value method; - CHECK_NAPI(napi_create_function(env, p.utf8name, NAPI_AUTO_LENGTH, - p.method, p.data, &method)); - CHECK_QJS(env, - LEPUS_DefinePropertyValue( - ctx, obj, prop_atom, - JS_DupValue_Comp(ctx, ToJSValue(method)), flags) != -1); - } else { - LEPUSValue value = JS_DupValue_Comp(ctx, ToJSValue(p.value)); - CHECK_QJS(env, LEPUS_DefinePropertyValue(ctx, obj, prop_atom, value, - flags) != -1); - } - } - - return napi_clear_last_error(env); -} - -napi_status napi_is_array(napi_env env, napi_value value, bool *result) { - int result_is = LEPUS_IsArray(env->ctx->ctx, ToJSValue(value)); - CHECK_QJS(env, result_is != -1); - *result = result_is; - return napi_clear_last_error(env); -} - -napi_status napi_get_array_length(napi_env env, napi_value value, - uint32_t *result) { - LEPUSContext *ctx = env->ctx->ctx; - LEPUSValue v = - LEPUS_GetProperty(ctx, ToJSValue(value), env->ctx->PROP_LENGTH); - CHECK_QJS(env, !LEPUS_IsException(v)); - int result_toint = LEPUS_ToUint32(ctx, result, v); - JS_FreeValue_Comp(ctx, v); - CHECK_QJS(env, result_toint != -1); - return napi_clear_last_error(env); -} - -napi_status napi_equals(napi_env env, napi_value lhs, napi_value rhs, - bool *result) { - LEPUSValue a = ToJSValue(lhs); - LEPUSValue b = ToJSValue(rhs); - LEPUSContext *ctx = env->ctx->ctx; - *result = LEPUS_SameValue(ctx, a, b); - - return napi_clear_last_error(env); -} - -napi_status napi_strict_equals(napi_env env, napi_value lhs, napi_value rhs, - bool *result) { - LEPUSValue a = ToJSValue(lhs); - LEPUSValue b = ToJSValue(rhs); - LEPUSContext *ctx = env->ctx->ctx; - *result = - LEPUS_StrictEq(ctx, JS_DupValue_Comp(ctx, a), JS_DupValue_Comp(ctx, b)); - return napi_clear_last_error(env); -} - -napi_status napi_get_prototype(napi_env env, napi_value object, - napi_value *result) { - LEPUSValueConst prototype = - LEPUS_GetPrototype(env->ctx->ctx, ToJSValue(object)); - CHECK_QJS(env, !LEPUS_IsException(prototype)); - *result = env->ctx->CreateHandle(JS_DupValue_Comp(env->ctx->ctx, prototype)); - return napi_clear_last_error(env); -} - -napi_status napi_create_object(napi_env env, napi_value *result) { - LEPUSValue object = LEPUS_NewObject(env->ctx->ctx); - CHECK_QJS(env, !LEPUS_IsException(object)); - *result = env->ctx->CreateHandle(object); - return napi_clear_last_error(env); -} - -napi_status napi_create_array(napi_env env, napi_value *result) { - LEPUSValue array = LEPUS_NewArray(env->ctx->ctx); - CHECK_QJS(env, !LEPUS_IsException(array)); - *result = env->ctx->CreateHandle(array); - return napi_clear_last_error(env); -} - -napi_status napi_create_array_with_length(napi_env env, size_t length, - napi_value *result) { - LEPUSValue array = LEPUS_NewArray(env->ctx->ctx); - CHECK_QJS(env, !LEPUS_IsException(array)); - - *result = env->ctx->CreateHandle(array); - CHECK_QJS(env, - LEPUS_SetProperty(env->ctx->ctx, array, env->ctx->PROP_LENGTH, - LEPUS_NewInt64(env->ctx->ctx, length)) != -1); - - return napi_clear_last_error(env); -} - -napi_status napi_create_string_latin1(napi_env env, const char *str, - size_t length, napi_value *result) { - *result = env->ctx->CreateHandle( - length == NAPI_AUTO_LENGTH - ? LEPUS_NewString(env->ctx->ctx, str) - : LEPUS_NewStringLen(env->ctx->ctx, str, length)); - return napi_clear_last_error(env); -} - -napi_status napi_create_string_utf8(napi_env env, const char *str, - size_t length, napi_value *result) { - *result = env->ctx->CreateHandle( - length == NAPI_AUTO_LENGTH - ? LEPUS_NewString(env->ctx->ctx, str) - : LEPUS_NewStringLen(env->ctx->ctx, str, length)); - return napi_clear_last_error(env); -} - -napi_status napi_create_string_utf16(napi_env env, const char16_t *str, - size_t length, napi_value *result) { - *result = env->ctx->CreateHandle(LEPUS_NewWString( - env->ctx->ctx, reinterpret_cast(str), - length == NAPI_AUTO_LENGTH ? std::char_traits::length(str) - : length)); - return napi_clear_last_error(env); -} - -napi_status napi_create_double(napi_env env, double value, napi_value *result) { - *result = env->ctx->CreateHandle(LEPUS_NewFloat64(env->ctx->ctx, value)); - return napi_clear_last_error(env); -} - -napi_status napi_create_int32(napi_env env, int32_t value, napi_value *result) { - *result = env->ctx->CreateHandle(LEPUS_NewInt32(env->ctx->ctx, value)); - return napi_clear_last_error(env); -} - -napi_status napi_create_uint32(napi_env env, uint32_t value, - napi_value *result) { - *result = env->ctx->CreateHandle(LEPUS_NewInt64(env->ctx->ctx, value)); - return napi_clear_last_error(env); -} - -napi_status napi_create_int64(napi_env env, int64_t value, napi_value *result) { - *result = env->ctx->CreateHandle(LEPUS_NewInt64(env->ctx->ctx, value)); - return napi_clear_last_error(env); -} - -napi_status napi_get_boolean(napi_env env, bool value, napi_value *result) { - *result = env->ctx->CreateHandle(LEPUS_NewBool(env->ctx->ctx, value)); - return napi_clear_last_error(env); -} - -napi_status napi_create_symbol(napi_env env, napi_value description, - napi_value *result) { - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - napi_value global{}, symbol_func{}, symbol_value{}; - CHECK_NAPI(napi_get_global(env, &global)); - CHECK_NAPI(napi_get_named_property(env, global, "Symbol", &symbol_func)); - CHECK_NAPI(napi_call_function(env, global, symbol_func, 1, &description, - &symbol_value)); - *result = scope.Escape(symbol_value); - return napi_clear_last_error(env); -} - -napi_status napi_create_error(napi_env env, napi_value code, napi_value msg, - napi_value *result) { - LEPUSValue error = LEPUS_NewError(env->ctx->ctx); - *result = env->ctx->CreateHandle(error); - - CHECK_NAPI(napi_set_error_msg_code(env, ToNapi(&error), code, msg, nullptr)); - - return napi_clear_last_error(env); -} - -napi_status napi_create_type_error(napi_env env, napi_value code, - napi_value msg, napi_value *result) { - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - - napi_value global{}, error_ctor{}, error{}; - CHECK_NAPI(napi_get_global(env, &global)); - CHECK_NAPI(napi_get_named_property(env, global, "TypeError", &error_ctor)); - CHECK_NAPI(napi_new_instance(env, error_ctor, 1, &msg, &error)); - CHECK_NAPI(napi_set_error_msg_code(env, error, code, msg, nullptr)); - - *result = scope.Escape(error); - return napi_clear_last_error(env); -} - -napi_status napi_create_range_error(napi_env env, napi_value code, - napi_value msg, napi_value *result) { - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - - napi_value global{}, error_ctor{}, error{}; - CHECK_NAPI(napi_get_global(env, &global)); - CHECK_NAPI(napi_get_named_property(env, global, "RangeError", &error_ctor)); - CHECK_NAPI(napi_new_instance(env, error_ctor, 1, &msg, &error)); - CHECK_NAPI(napi_set_error_msg_code(env, error, code, msg, nullptr)); - - *result = scope.Escape(error); - return napi_clear_last_error(env); -} - -napi_status napi_typeof(napi_env env, napi_value value, - napi_valuetype *result) { - LEPUSValue v = ToJSValue(value); - int64_t tag = LEPUS_VALUE_GET_NORM_TAG(v); - - switch (tag) { - case LEPUS_TAG_INT: - case LEPUS_TAG_FLOAT64: - *result = napi_number; - break; - case LEPUS_TAG_BIG_INT: - *result = napi_bigint; - break; - case LEPUS_TAG_STRING: - *result = napi_string; - break; - case LEPUS_TAG_SEPARABLE_STRING: - *result = napi_string; - break; - case LEPUS_TAG_SYMBOL: - *result = napi_symbol; - break; - case LEPUS_TAG_NULL: - *result = napi_null; - break; - case LEPUS_TAG_UNDEFINED: - *result = napi_undefined; - break; - case LEPUS_TAG_BOOL: - *result = napi_boolean; - break; - case LEPUS_TAG_OBJECT: - if (LEPUS_IsFunction(env->ctx->ctx, v)) { - *result = napi_function; - } else { - qjsimpl::NativeInfo *info = qjsimpl::NativeInfo::Get(v); - if (info && info->Type() == qjsimpl::NativeType::External) { - *result = napi_external; - } else { - *result = napi_object; - } - } - break; - default: - // Should not get here unless QuickJS has added some new kind of value. - return napi_set_last_error(env, napi_invalid_arg); - } - - return napi_clear_last_error(env); -} - -napi_status napi_get_undefined(napi_env env, napi_value *result) { - *result = ToNapi(&(env->ctx->V_UNDEFINED)); - return napi_clear_last_error(env); -} - -napi_status napi_get_null(napi_env env, napi_value *result) { - *result = ToNapi(&(env->ctx->V_NULL)); - return napi_clear_last_error(env); -} - -napi_status napi_get_cb_info( - napi_env env, // [in] NAPI environment handle - napi_callback_info cbinfo, // [in] Opaque callback-info handle - size_t *argc, // [in-out] Specifies the size of the provided argv array - // and receives the actual count of args. - napi_value *argv, // [out] Array of values - napi_value *this_arg, // [out] Receives the JS 'this' arg for the call - void **data) { // [out] Receives the data pointer for the callback. - if (argv != nullptr) { - CHECK_ARG(env, argc); - - size_t i{0}; - size_t min{std::min(*argc, static_cast(cbinfo->argc))}; - - for (; i < min; i++) { - argv[i] = cbinfo->argv[i]; - } - - if (i < *argc) { - for (; i < *argc; i++) { - argv[i] = ToNapi(&(env->ctx->V_UNDEFINED)); - } - } - } - - if (argc != nullptr) { - *argc = cbinfo->argc; - } - - if (this_arg != nullptr) { - *this_arg = cbinfo->thisArg; - } - - if (data != nullptr) { - *data = cbinfo->data; - } - - return napi_clear_last_error(env); -} - -napi_status napi_get_new_target(napi_env env, napi_callback_info cbinfo, - napi_value *result) { - *result = cbinfo->newTarget; - return napi_clear_last_error(env); -} - -namespace { - inline LEPUSValueConst ToJSValue(napi_value *v) { return ToJSValue(*v); } -} // namespace - -napi_status napi_call_function(napi_env env, napi_value recv, napi_value func, - size_t argc, const napi_value *argv, - napi_value *result) { - if (argc > 0) { - CHECK_ARG(env, argv); - } - - LEPUSContext *ctx = env->ctx->ctx; - - js_enter(env); - - ArgsConverter args( - argc, const_cast(argv)); - - LEPUSValue call_result = - LEPUS_Call(ctx, ToJSValue(func), recv ? ToJSValue(recv) : LEPUS_UNDEFINED, - argc, args); - - - CHECK_QJS(env, !LEPUS_IsException(call_result)); - - if (result) { - *result = env->ctx->CreateHandle(call_result); - } else { - if (!LEPUS_IsGCMode(ctx)) { - LEPUS_FreeValue(ctx, call_result); - } - } - - js_exit(env); - auto rt = LEPUS_GetRuntime(ctx); - if (rt && !rt->current_stack_frame) { - LEPUSContext *pctx = NULL; - int result = 0; - while ((result = LEPUS_ExecutePendingJob(rt, &pctx))) { - if (result < 0) { - return napi_set_exception(env, LEPUS_GetException(pctx)); - } - } - } - - return napi_clear_last_error(env); -} - -napi_status napi_get_global(napi_env env, napi_value *result) { - *result = env->ctx->CreateHandle(LEPUS_GetGlobalObject(env->ctx->ctx)); - return napi_clear_last_error(env); -} - -napi_status napi_throw(napi_env env, napi_value error) { - if (env->ctx->last_exception) { - JS_FreeValue_Comp(env->ctx->ctx, *env->ctx->last_exception); - } - env->ctx->last_exception.reset( - new LEPUSValue(JS_DupValue_Comp(env->ctx->ctx, ToJSValue(error)))); - env->ctx->last_exception_pVal.Reset(nullptr, *env->ctx->last_exception, - nullptr, env->ctx->ctx, true); - return napi_clear_last_error(env); -} - -napi_status napi_throw_error(napi_env env, const char *code, const char *msg) { - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - - LEPUSValue code_val = LEPUS_UNDEFINED; - if (code != NULL) { - LEPUS_NewString(env->ctx->ctx, code); - env->ctx->CreateHandle(code_val, true); - } - - LEPUSValue msg_val = LEPUS_NewString(env->ctx->ctx, msg); - env->ctx->CreateHandle(msg_val, true); - - napi_value error{}; - napi_status ret = - napi_create_error(env, ToNapi(&code_val), ToNapi(&msg_val), &error); - JS_FreeValue_Comp(env->ctx->ctx, code_val); - JS_FreeValue_Comp(env->ctx->ctx, msg_val); - - CHECK_NAPI(ret); - - return napi_throw(env, error); -} - -napi_status napi_throw_type_error(napi_env env, const char *code, - const char *msg) { - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - - LEPUSValue code_val = LEPUS_UNDEFINED; - if (code != NULL) { - LEPUS_NewString(env->ctx->ctx, code); - env->ctx->CreateHandle(code_val, true); - } - - LEPUSValue msg_val = LEPUS_NewString(env->ctx->ctx, msg); - env->ctx->CreateHandle(msg_val, true); - - napi_value error{}; - napi_status ret = - napi_create_type_error(env, ToNapi(&code_val), ToNapi(&msg_val), &error); - JS_FreeValue_Comp(env->ctx->ctx, code_val); - JS_FreeValue_Comp(env->ctx->ctx, msg_val); - - CHECK_NAPI(ret); - - return napi_throw(env, error); -} - -napi_status napi_throw_range_error(napi_env env, const char *code, - const char *msg) { - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - LEPUSValue code_val = LEPUS_UNDEFINED; - if (code != NULL) { - LEPUS_NewString(env->ctx->ctx, code); - env->ctx->CreateHandle(code_val, true); - } - LEPUSValue msg_val = LEPUS_NewString(env->ctx->ctx, msg); - env->ctx->CreateHandle(msg_val, true); - - napi_value error{}; - napi_status ret = - napi_create_range_error(env, ToNapi(&code_val), ToNapi(&msg_val), &error); - - JS_FreeValue_Comp(env->ctx->ctx, code_val); - - JS_FreeValue_Comp(env->ctx->ctx, msg_val); - - CHECK_NAPI(ret); - - return napi_throw(env, error); -} - -napi_status napi_is_error(napi_env env, napi_value value, bool *result) { - *result = LEPUS_IsError(env->ctx->ctx, ToJSValue(value)); - - return napi_clear_last_error(env); -} - -napi_status napi_get_value_double(napi_env env, napi_value value, - double *result) { - int ret = LEPUS_ToFloat64(env->ctx->ctx, result, ToJSValue(value)); - - CHECK_QJS(env, ret != -1); - - return napi_clear_last_error(env); -} - -napi_status napi_get_value_int32(napi_env env, napi_value value, - int32_t *result) { - int ret = LEPUS_ToInt32(env->ctx->ctx, result, ToJSValue(value)); - - CHECK_QJS(env, ret != -1); - - return napi_clear_last_error(env); -} - -napi_status napi_get_value_uint32(napi_env env, napi_value value, - uint32_t *result) { - int ret = LEPUS_ToUint32(env->ctx->ctx, result, ToJSValue(value)); - - CHECK_QJS(env, ret != -1); - - return napi_clear_last_error(env); -} - -napi_status napi_get_value_int64(napi_env env, napi_value value, - int64_t *result) { - int ret = LEPUS_ToInt64(env->ctx->ctx, result, ToJSValue(value)); - - CHECK_QJS(env, ret != -1); - - return napi_clear_last_error(env); -} - -napi_status napi_get_value_bool(napi_env env, napi_value value, bool *result) { - *result = LEPUS_ToBool(env->ctx->ctx, ToJSValue(value)); - - return napi_clear_last_error(env); -} - -// Copies a JavaScript string into a LATIN-1 string buffer. The result is the -// number of bytes (excluding the null terminator) copied into buf. -// A sufficient buffer size should be greater than the length of string, -// reserving space for null terminator. -// If bufsize is insufficient, the string will be truncated and null terminated. -// If buf is NULL, this method returns the length of the string (in bytes) -// via the result parameter. -// The result argument is optional unless buf is NULL. -napi_status napi_get_value_string_latin1(napi_env env, napi_value value, - char *buf, size_t bufsize, - size_t *result) { - LEPUSValue wstring = LEPUS_ToWString(env->ctx->ctx, ToJSValue(value)); - env->ctx->CreateHandle(wstring, true); - - CHECK_QJS(env, !LEPUS_IsException(wstring)); - - size_t length = LEPUS_GetStringLength(env->ctx->ctx, wstring); - - if (buf == nullptr) { - *result = length; - } else { - const char16_t *chars = reinterpret_cast( - LEPUS_GetStringChars(env->ctx->ctx, wstring)); - size_t size{std::min(length, bufsize - 1)}; - for (size_t i = 0; i < size; ++i) { - const char16_t ch{chars[i]}; - buf[i] = (ch < 256) ? ch : '?'; - } - buf[size] = '\0'; - if (result != nullptr) { - *result = size; - } - } - - JS_FreeValue_Comp(env->ctx->ctx, wstring); - - return napi_clear_last_error(env); -} - -// Copies a JavaScript string into a UTF-8 string buffer. The result is the -// number of bytes (excluding the null terminator) copied into buf. -// A sufficient buffer size should be greater than the length of string, -// reserving space for null terminator. -// If bufsize is insufficient, the string will be truncated and null terminated. -// If buf is NULL, this method returns the length of the string (in bytes) -// via the result parameter. -// The result argument is optional unless buf is NULL. -napi_status napi_get_value_string_utf8(napi_env env, napi_value value, - char *buf, size_t bufsize, - size_t *result) { - size_t length; - const char *str = - LEPUS_ToCStringLen(env->ctx->ctx, &length, ToJSValue(value)); - - CHECK_QJS(env, str); - - if (buf == nullptr) { - *result = length; - } else { - size_t size{std::min(length, bufsize - 1)}; - std::copy(str, str + size, buf); - buf[size] = '\0'; - if (result != nullptr) { - *result = size; - } - } - - JS_FreeCString_Comp(env->ctx->ctx, str); - - return napi_clear_last_error(env); -} - -// Copies a JavaScript string into a UTF-16 string buffer. The result is the -// number of 2-byte code units (excluding the null terminator) copied into buf. -// A sufficient buffer size should be greater than the length of string, -// reserving space for null terminator. -// If bufsize is insufficient, the string will be truncated and null terminated. -// If buf is NULL, this method returns the length of the string (in 2-byte -// code units) via the result parameter. -// The result argument is optional unless buf is NULL. -napi_status napi_get_value_string_utf16(napi_env env, napi_value value, - char16_t *buf, size_t bufsize, - size_t *result) { - LEPUSValue wstring = LEPUS_ToWString(env->ctx->ctx, ToJSValue(value)); - env->ctx->CreateHandle(wstring, true); - - CHECK_QJS(env, !LEPUS_IsException(wstring)); - - size_t length = LEPUS_GetStringLength(env->ctx->ctx, wstring); - - if (buf == nullptr) { - *result = length; - } else { - const char16_t *chars = reinterpret_cast( - LEPUS_GetStringChars(env->ctx->ctx, wstring)); - size_t size{std::min(length, bufsize - 1)}; - std::copy(chars, chars + size, buf); - buf[size] = '\0'; - if (result != nullptr) { - *result = size; - } - } - - JS_FreeValue_Comp(env->ctx->ctx, wstring); - - return napi_clear_last_error(env); -} - -napi_status napi_coerce_to_bool(napi_env env, napi_value value, - napi_value *result) { - *result = env->ctx->CreateHandle(LEPUS_NewBool( - env->ctx->ctx, LEPUS_ToBool(env->ctx->ctx, ToJSValue(value)))); - return napi_clear_last_error(env); -} - -napi_status napi_coerce_to_number(napi_env env, napi_value value, - napi_value *result) { - double number; - int ret = LEPUS_ToFloat64(env->ctx->ctx, &number, ToJSValue(value)); - - CHECK_QJS(env, ret != -1); - - *result = env->ctx->CreateHandle(LEPUS_NewFloat64(env->ctx->ctx, number)); - return napi_clear_last_error(env); -} - -napi_status napi_coerce_to_object(napi_env env, napi_value value, - napi_value *result) { - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - napi_value global{}, object_func{}, object_value{}; - CHECK_NAPI(napi_get_global(env, &global)); - CHECK_NAPI(napi_get_named_property(env, global, "Object", &object_func)); - CHECK_NAPI( - napi_call_function(env, global, object_func, 1, &value, &object_value)); - *result = scope.Escape(object_value); - - return napi_clear_last_error(env); -} - -napi_status napi_coerce_to_string(napi_env env, napi_value value, - napi_value *result) { - LEPUSValue str = LEPUS_ToString(env->ctx->ctx, ToJSValue(value)); - CHECK_QJS(env, !LEPUS_IsException(str)); - *result = env->ctx->CreateHandle(str); - return napi_clear_last_error(env); -} - -napi_status napi_wrap(napi_env env, napi_value js_object, void *native_object, - napi_finalize finalize_cb, void *finalize_hint, - napi_ref *result) { - return qjsimpl::Wrap( - env, js_object, native_object, finalize_cb, finalize_hint, result); -} - -napi_status napi_unwrap(napi_env env, napi_value obj, void **result) { - return qjsimpl::Unwrap(env, obj, result, qjsimpl::KeepWrap); -} - -napi_status napi_remove_wrap(napi_env env, napi_value obj, void **result) { - return qjsimpl::Unwrap(env, obj, result, qjsimpl::RemoveWrap); -} - -napi_status napi_create_external(napi_env env, void *data, - napi_finalize finalize_cb, void *finalize_hint, - napi_value *result) { - qjsimpl::NativeInfo *info; - LEPUSValue value = qjsimpl::External::Create(env, &info); - - CHECK_QJS(env, !LEPUS_IsException(value)); - - info->Data(data); - - qjsimpl::Reference::New(env, value, info, 0, true, finalize_cb, data, - finalize_hint); - - *result = env->ctx->CreateHandle(value); - - return napi_clear_last_error(env); -} - -napi_status napi_get_value_external(napi_env env, napi_value value, - void **result) { - qjsimpl::NativeInfo *info = qjsimpl::NativeInfo::Get(ToJSValue(value)); - *result = info != nullptr && info->Type() == qjsimpl::NativeType::External - ? info->Data() - : nullptr; - return napi_clear_last_error(env); -} - -// Set initial_refcount to 0 for a weak reference, >0 for a strong reference. -napi_status napi_create_reference(napi_env env, napi_value value, - uint32_t initial_refcount, napi_ref *result) { - LEPUSValueConst val = ToJSValue(value); - - if (LEPUS_VALUE_GET_NORM_TAG(val) != LEPUS_TAG_OBJECT) { - return napi_set_last_error(env, napi_object_expected); - } - - qjsimpl::Reference *reference = qjsimpl::Reference::New( - env, val, qjsimpl::NativeInfo::Get(val), initial_refcount, false); - - *result = reinterpret_cast(reference); - - return napi_clear_last_error(env); -} - -// Deletes a reference. The referenced value is released, and may be GC'd -// unless there are other references to it. -napi_status napi_delete_reference(napi_env env, napi_ref ref) { - qjsimpl::Reference::Delete(reinterpret_cast(ref)); - - return napi_clear_last_error(env); -} - -// Increments the reference count, optionally returning the resulting count. -// After this call the reference will be a strong reference because its refcount -// is >0, and the referenced object is effectively "pinned". Calling this when -// the refcount is 0 and the target is unavailable results in an error. -napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t *result) { - qjsimpl::Reference *reference = reinterpret_cast(ref); - uint32_t count = reference->Ref(); - - if (result != nullptr) { - *result = count; - } - - return napi_clear_last_error(env); -} - -// Decrements the reference count, optionally returning the resulting count. -// If the result is 0 the reference is now weak and the object may be GC'd at -// any time if there are no other references. Calling this when the refcount -// is already 0 results in an error. -napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t *result) { - qjsimpl::Reference *reference = reinterpret_cast(ref); - - if (reference->RefCount() == 0) { - return napi_set_last_error(env, napi_generic_failure); - } - - uint32_t count = reference->Unref(); - - if (result != nullptr) { - *result = count; - } - - return napi_clear_last_error(env); -} - -// Attempts to get a referenced value. If the reference is weak, the value -// might no longer be available, in that case the call is still successful but -// the result is NULL. -napi_status napi_get_reference_value(napi_env env, napi_ref ref, - napi_value *result) { - qjsimpl::Reference *reference = reinterpret_cast(ref); - - *result = reference->Get(); - return napi_clear_last_error(env); -} - -//// Stub implementation of handle scope apis for QuickLEPUS. -//napi_status napi_open_context_scope(napi_env env, napi_context_scope* result) { -// *result = reinterpret_cast(1); -// return napi_clear_last_error(env); -//} -// -//// Stub implementation of handle scope apis for QuickJS. -//napi_status napi_close_context_scope(napi_env env, napi_context_scope scope) { -// return napi_clear_last_error(env); -//} - -napi_status napi_open_handle_scope(napi_env env, napi_handle_scope *result) { - *result = reinterpret_cast( - new napi_handle_scope__(env, env->ctx->ctx, reset_napi_env)); - env->ctx->open_handle_scopes++; - return napi_clear_last_error(env); -} - -napi_status napi_close_handle_scope(napi_env env, napi_handle_scope scope) { - if (env->ctx->open_handle_scopes == 0) { - return napi_handle_scope_mismatch; - } - env->ctx->open_handle_scopes--; - - delete reinterpret_cast(scope); - return napi_clear_last_error(env); -} - -napi_status napi_open_escapable_handle_scope( - napi_env env, napi_escapable_handle_scope *result) { - *result = reinterpret_cast( - new napi_handle_scope__(env, env->ctx->ctx, reset_napi_env)); - env->ctx->open_handle_scopes++; - return napi_clear_last_error(env); -} - -napi_status napi_close_escapable_handle_scope( - napi_env env, napi_escapable_handle_scope scope) { - if (env->ctx->open_handle_scopes == 0) { - return napi_handle_scope_mismatch; - } - env->ctx->open_handle_scopes--; - - delete reinterpret_cast(scope); - return napi_clear_last_error(env); -} - -napi_status napi_escape_handle(napi_env env, napi_escapable_handle_scope scope, - napi_value escapee, napi_value *result) { - *result = reinterpret_cast(scope)->Escape(escapee); - return napi_clear_last_error(env); -} - -napi_status napi_new_instance(napi_env env, napi_value constructor, size_t argc, - const napi_value *argv, napi_value *result) { - if (argc > 0) { - CHECK_ARG(env, argv); - } - - ArgsConverter args( - argc, const_cast(argv)); - - js_enter(env); - - LEPUSValue instance = - LEPUS_CallConstructor(env->ctx->ctx, ToJSValue(constructor), argc, args); - - js_exit(env); - - CHECK_QJS(env, !LEPUS_IsException(instance)); - - *result = env->ctx->CreateHandle(instance); - - return napi_clear_last_error(env); -} - -napi_status napi_instanceof(napi_env env, napi_value object, - napi_value constructor, bool *result) { - int ret = LEPUS_IsInstanceOf(env->ctx->ctx, ToJSValue(object), - ToJSValue(constructor)); - - CHECK_QJS(env, ret != -1); - - *result = ret; - - return napi_clear_last_error(env); -} - -napi_status napi_is_exception_pending(napi_env env, bool *result) { - *result = static_cast(env->ctx->last_exception); - return napi_clear_last_error(env); -} - -napi_status napi_get_and_clear_last_exception(napi_env env, - napi_value *result) { - if (!env->ctx->last_exception) { - return napi_get_undefined(env, result); - } else { - *result = env->ctx->CreateHandle(*env->ctx->last_exception); - env->ctx->last_exception.reset(); - env->ctx->last_exception_pVal.Reset(true); - } - - return napi_clear_last_error(env); -} - -std::string get_lepus_error_stack(LEPUSContext *ctx, LEPUSValue &value) { - std::string err; - if (LEPUS_IsError(ctx, value) || LEPUS_IsException(value)) { - LEPUSValue val = LEPUS_GetPropertyStr(ctx, value, "stack"); - if (!LEPUS_IsUndefined(val)) { - const char *stack = LEPUS_ToCString(ctx, val); - if (stack) { - err.append(stack); - } - JS_FreeCString_Comp(ctx, stack); - } - JS_FreeValue_Comp(ctx, val); - } - return err; -} - -napi_status napi_get_unhandled_rejection_exception(napi_env env, - napi_value *result) { - LEPUSContext *ctx = env->ctx->ctx; - std::string error_result; - while (LEPUS_MoveUnhandledRejectionToException(ctx)) { - LEPUSValue exception = LEPUS_GetException(ctx); - env->ctx->CreateHandle(exception, true); - const char *error_message = LEPUS_ToCString(ctx, exception); - if (error_message) { - error_result.append("message: "); - error_result.append(error_message); - } - JS_FreeCString_Comp(ctx, error_message); - - std::string error_stack = get_lepus_error_stack(ctx, exception); - error_result.append("\nstack: "); - error_result.append(error_stack); - error_result.append("\n"); - } - LEPUSValue result_lepus = LEPUS_NewString(ctx, error_result.c_str()); - *result = env->ctx->CreateHandle(result_lepus); - return napi_clear_last_error(env); -} - -napi_status napi_get_own_property_descriptor(napi_env env, napi_value obj, - napi_value prop, - napi_value *result) { - LEPUSValueConst args[2]; - args[0] = ToJSValue(obj); - args[1] = ToJSValue(prop); - LEPUSValue descriptor = lepus_object_getOwnPropertyDescriptor( - env->ctx->ctx, LEPUS_UNDEFINED, 2, args, 0); - CHECK_QJS(env, !LEPUS_IsException(descriptor)); - *result = env->ctx->CreateHandle(descriptor); - return napi_clear_last_error(env); -} - -napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool *result) { - LEPUSClassID id = LEPUS_GetClassID(env->ctx->ctx, ToJSValue(value)); - *result = id == JS_CLASS_ARRAY_BUFFER || id == JS_CLASS_SHARED_ARRAY_BUFFER; - return napi_clear_last_error(env); -} - -napi_status napi_create_arraybuffer(napi_env env, size_t byte_length, - void **data, napi_value *result) { - void *bytes = std::malloc(byte_length); - // v8 use zero initialized - std::memset(bytes, 0, byte_length); - LEPUSValue buffer = LEPUS_NewArrayBuffer( - env->ctx->ctx, static_cast(bytes), byte_length, - [](LEPUSRuntime *rt, void *opaque, void *ptr) { std::free(ptr); }, - nullptr, false); - - if (LEPUS_IsException(buffer)) { - std::free(bytes); - CHECK_QJS(env, false); - } - - *data = bytes; - *result = env->ctx->CreateHandle(buffer); - - return napi_clear_last_error(env); -} - -napi_status napi_create_external_arraybuffer(napi_env env, void *external_data, - size_t byte_length, - napi_finalize finalize_cb, - void *finalize_hint, - napi_value *result) { - LEPUSValue buffer = LEPUS_NewArrayBuffer( - env->ctx->ctx, static_cast(external_data), byte_length, - [](LEPUSRuntime *rt, void *opaque, void *ptr) {}, nullptr, false); - - CHECK_QJS(env, !LEPUS_IsException(buffer)); - - if (finalize_cb != nullptr) { - qjsimpl::Reference::New(env, buffer, nullptr, 0, true, finalize_cb, - external_data, finalize_hint); - } - - *result = env->ctx->CreateHandle(buffer); - - return napi_clear_last_error(env); -} - -napi_status napi_get_arraybuffer_info(napi_env env, napi_value arraybuffer, - void **data, size_t *byte_length) { - size_t size; - uint8_t *bytes = - LEPUS_GetArrayBuffer(env->ctx->ctx, &size, ToJSValue(arraybuffer)); - - CHECK_QJS(env, bytes); - - if (data) { - *data = static_cast(bytes); - } - if (byte_length) { - *byte_length = size; - } - return napi_clear_last_error(env); -} - -napi_status napi_is_typedarray(napi_env env, napi_value value, bool *result) { - LEPUSClassID class_id = LEPUS_GetClassID(env->ctx->ctx, ToJSValue(value)); - *result = - class_id >= JS_CLASS_UINT8C_ARRAY && class_id <= JS_CLASS_FLOAT64_ARRAY; - return napi_clear_last_error(env); -} - -#define FOR_EACH_TYPEDARRAY(V) \ - V(napi_uint8_clamped_array, JS_CLASS_UINT8C_ARRAY) \ - V(napi_uint8_array, JS_CLASS_UINT8_ARRAY) \ - V(napi_int8_array, JS_CLASS_INT8_ARRAY) \ - V(napi_int16_array, JS_CLASS_INT16_ARRAY) \ - V(napi_uint16_array, JS_CLASS_UINT16_ARRAY) \ - V(napi_int32_array, JS_CLASS_INT32_ARRAY) \ - V(napi_uint32_array, JS_CLASS_UINT32_ARRAY) \ - V(napi_float32_array, JS_CLASS_FLOAT32_ARRAY) \ - V(napi_float64_array, JS_CLASS_FLOAT64_ARRAY) - -napi_status napi_create_typedarray(napi_env env, napi_typedarray_type type, - size_t length, napi_value arraybuffer, - size_t byte_offset, napi_value *result) { - LEPUSClassID class_id; - - switch (type) { -#define CASE_TYPE(TYPE, CLASS_ID) \ - case TYPE: \ - class_id = CLASS_ID; \ - break; - - FOR_EACH_TYPEDARRAY(CASE_TYPE) - -#undef CASE_TYPE - case napi_bigint64_array: - case napi_biguint64_array: - return napi_set_last_error(env, napi_invalid_arg); - } - - LEPUSValue array = LEPUS_NewTypedArrayWithBuffer( - env->ctx->ctx, ToJSValue(arraybuffer), byte_offset, length, class_id); - - CHECK_QJS(env, !LEPUS_IsException(array)); - - *result = env->ctx->CreateHandle(array); - - return napi_clear_last_error(env); -} - -napi_status napi_is_typedarray_of(napi_env env, napi_value typedarray, - napi_typedarray_type type, bool *result) { - LEPUSClassID class_id = - LEPUS_GetClassID(env->ctx->ctx, ToJSValue(typedarray)); - - switch (type) { -#define CASE_TYPE(TYPE, CLASS_ID) \ - case TYPE: \ - *result = class_id == CLASS_ID; \ - break; - - FOR_EACH_TYPEDARRAY(CASE_TYPE) - -#undef CASE_TYPE - case napi_bigint64_array: - case napi_biguint64_array: - return napi_set_last_error(env, napi_invalid_arg); - } - - return napi_clear_last_error(env); -} - -napi_status napi_get_typedarray_info(napi_env env, napi_value typedarray, - napi_typedarray_type *type, size_t *length, - void **data, napi_value *arraybuffer, - size_t *byte_offset) { - LEPUSValueConst typedarray_val = ToJSValue(typedarray); - LEPUSClassID class_id = LEPUS_GetClassID(env->ctx->ctx, typedarray_val); - - switch (class_id) { -#define CASE_TYPE(TYPE, CLASS_ID) \ - case CLASS_ID: \ - if (type) *type = TYPE; \ - break; - - FOR_EACH_TYPEDARRAY(CASE_TYPE) - -#undef CASE_TYPE - case napi_bigint64_array: - case napi_biguint64_array: - return napi_set_last_error(env, napi_invalid_arg); - } - - uint32_t byte_offset_num; - - { - LEPUSValue val = LEPUS_GetProperty(env->ctx->ctx, typedarray_val, - env->ctx->PROP_BYTEOFFSET); - CHECK_QJS(env, !LEPUS_IsException(val)); - CHECK_QJS(env, LEPUS_ToUint32(env->ctx->ctx, &byte_offset_num, val) != -1); - if (byte_offset) { - *byte_offset = byte_offset_num; - } - } - - if (length) { - LEPUSValue val = - LEPUS_GetProperty(env->ctx->ctx, typedarray_val, env->ctx->PROP_LENGTH); - CHECK_QJS(env, !LEPUS_IsException(val)); - uint32_t length_num; - CHECK_QJS(env, LEPUS_ToUint32(env->ctx->ctx, &length_num, val) != -1); - *length = length_num; - } - - if (data || arraybuffer) { - LEPUSValue val = - LEPUS_GetProperty(env->ctx->ctx, typedarray_val, env->ctx->PROP_BUFFER); - CHECK_QJS(env, !LEPUS_IsException(val)); - if (arraybuffer) { - *arraybuffer = env->ctx->CreateHandle(val); - } - if (data) { - size_t unused; - uint8_t *buffer_start = LEPUS_GetArrayBuffer(env->ctx->ctx, &unused, val); - CHECK_QJS(env, buffer_start); - *data = buffer_start + byte_offset_num; - } - } - - return napi_clear_last_error(env); -} - -napi_status napi_create_dataview(napi_env env, size_t byte_length, - napi_value arraybuffer, size_t byte_offset, - napi_value *result) { - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - napi_value global{}, dataview_ctor{}, data_view{}; - CHECK_NAPI(napi_get_global(env, &global)); - CHECK_NAPI(napi_get_named_property(env, global, "DataView", &dataview_ctor)); - - napi_value byte_offset_value{}, byte_length_value{}; - napi_create_double(env, static_cast(byte_offset), &byte_offset_value); - napi_create_double(env, static_cast(byte_length), &byte_length_value); - napi_value args[] = {arraybuffer, byte_offset_value, byte_length_value}; - CHECK_NAPI(napi_new_instance(env, dataview_ctor, 3, args, &data_view)); - - *result = scope.Escape(data_view); - - return napi_clear_last_error(env); -} - -napi_status napi_is_dataview(napi_env env, napi_value value, bool *result) { - LEPUSClassID class_id = LEPUS_GetClassID(env->ctx->ctx, ToJSValue(value)); - *result = class_id == JS_CLASS_DATAVIEW; - return napi_clear_last_error(env); -} - -napi_status napi_is_date(napi_env env, napi_value value, bool *result) { - LEPUSClassID class_id = LEPUS_GetClassID(env->ctx->ctx, ToJSValue(value)); - *result = class_id == JS_CLASS_DATE; - return napi_clear_last_error(env); -} - -napi_status napi_get_dataview_info(napi_env env, napi_value dataview, - size_t *byte_length, void **data, - napi_value *arraybuffer, - size_t *byte_offset) { - LEPUSValueConst dataview_val = ToJSValue(dataview); - LEPUSClassID class_id = LEPUS_GetClassID(env->ctx->ctx, dataview_val); - - if (class_id != JS_CLASS_DATAVIEW) { - return napi_set_last_error(env, napi_invalid_arg); - } - - uint32_t byte_offset_num; - - { - LEPUSValue val = LEPUS_GetProperty(env->ctx->ctx, dataview_val, - env->ctx->PROP_BYTEOFFSET); - CHECK_QJS(env, !LEPUS_IsException(val)); - CHECK_QJS(env, LEPUS_ToUint32(env->ctx->ctx, &byte_offset_num, val) != -1); - if (byte_offset) { - *byte_offset = byte_offset_num; - } - } - - if (byte_length) { - LEPUSValue val = LEPUS_GetProperty(env->ctx->ctx, dataview_val, - env->ctx->PROP_BYTELENGTH); - CHECK_QJS(env, !LEPUS_IsException(val)); - uint32_t byte_length_num; - CHECK_QJS(env, LEPUS_ToUint32(env->ctx->ctx, &byte_length_num, val) != -1); - *byte_length = byte_length_num; - } - - if (data || arraybuffer) { - LEPUSValue val = - LEPUS_GetProperty(env->ctx->ctx, dataview_val, env->ctx->PROP_BUFFER); - CHECK_QJS(env, !LEPUS_IsException(val)); - if (arraybuffer) { - *arraybuffer = env->ctx->CreateHandle(val); - } - if (data) { - size_t unused; - uint8_t *buffer_start = LEPUS_GetArrayBuffer(env->ctx->ctx, &unused, val); - CHECK_QJS(env, buffer_start); - *data = buffer_start + byte_offset_num; - } - } - - return napi_clear_last_error(env); -} - -struct napi_deferred__ { - qjsimpl::NAPIPersistent resolve; - qjsimpl::NAPIPersistent reject; - - bool has_init = false; - - static napi_value Callback(napi_env env, napi_callback_info cbinfo) { - napi_deferred__ *deferred = - static_cast(cbinfo->data); - deferred->has_init = true; - deferred->resolve.Reset(env, ToJSValue(cbinfo->argv[0]), nullptr, - env->ctx->ctx, false); - deferred->reject.Reset(env, ToJSValue(cbinfo->argv[1]), nullptr, - env->ctx->ctx, false); - return nullptr; - } - - ~napi_deferred__() { - resolve.Reset(true); - reject.Reset(true); - } -}; - -napi_status napi_create_promise(napi_env env, napi_deferred *deferred, - napi_value *promise) { - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - napi_value global{}, promise_ctor{}; - CHECK_NAPI(napi_get_global(env, &global)); - CHECK_NAPI(napi_get_named_property(env, global, "Promise", &promise_ctor)); - - std::unique_ptr deferred_val = - std::make_unique(); - napi_value executor{}, promise_val{}; - CHECK_NAPI(napi_create_function(env, "executor", NAPI_AUTO_LENGTH, - napi_deferred__::Callback, - deferred_val.get(), &executor)); - CHECK_NAPI(napi_new_instance(env, promise_ctor, 1, &executor, &promise_val)); - - if (!deferred_val->has_init) { - return napi_set_last_error(env, napi_generic_failure); - } - - *promise = scope.Escape(promise_val); - *deferred = deferred_val.release(); - - return napi_clear_last_error(env); -} - -napi_status napi_is_promise(napi_env env, napi_value promise, - bool *is_promise) { - napi_handle_scope__ scope(env, env->ctx->ctx, reset_napi_env); - - napi_value global{}, promise_ctor{}; - CHECK_NAPI(napi_get_global(env, &global)); - CHECK_NAPI(napi_get_named_property(env, global, "Promise", &promise_ctor)); - CHECK_NAPI(napi_instanceof(env, promise, promise_ctor, is_promise)); - - return napi_clear_last_error(env); -} - -napi_status napi_run_script(napi_env env, napi_value script, - napi_value *result) { - return napi_run_script_source(env, script, "ctx->ctx, &size, ToJSValue(script)); - js_enter(env); - result_val = LEPUS_Eval(env->ctx->ctx, src, size, - source_url, LEPUS_EVAL_TYPE_GLOBAL); - JS_FreeCString_Comp(env->ctx->ctx, src); - js_exit(env); - - CHECK_QJS(env, !LEPUS_IsException(result_val)); - - *result = env->ctx->CreateHandle(result_val); - return napi_clear_last_error(env); -} - -#ifdef ENABLE_CODECACHE - -napi_status napi_run_code_cache(napi_env env, const uint8_t* data, int length, - napi_value* result) { - LEPUSValue result_val = LEPUS_UNDEFINED; - LEPUSValue top_func = - LEPUS_EvalBinary(env->ctx->ctx, data, static_cast(length), - LEPUS_EVAL_BINARY_LOAD_ONLY); - if (!LEPUS_IsException(top_func) && !LEPUS_IsUndefined(top_func)) { - LEPUSValue global = LEPUS_GetGlobalObject(env->ctx->ctx); - env->ctx->CreateHandle(top_func, true); - result_val = LEPUS_EvalFunction(env->ctx->ctx, top_func, global); - } - CHECK_QJS(env, !LEPUS_IsException(result_val)); - - *result = env->ctx->CreateHandle(result_val); - return napi_clear_last_error(env); -} - -napi_status napi_run_script_cache(napi_env env, const char* script, - size_t length, const char* filename, - napi_value* result) { - if (length == NAPI_AUTO_LENGTH) { - length = std::strlen(script); - } - - LEPUSValue result_val = LEPUS_UNINITIALIZED; - { - int len = -1; - const uint8_t* data = nullptr; - env->napi_get_code_cache(env, filename, &data, &len); - if (data) { - // TODO(yang): check whether the script is obsolate - LOG_TIME_START(); - LEPUSValue top_func = - LEPUS_EvalBinary(env->ctx->ctx, data, static_cast(len), - LEPUS_EVAL_BINARY_LOAD_ONLY); - if (!LEPUS_IsException(top_func) && !LEPUS_IsUndefined(top_func)) { - LEPUSValue global = LEPUS_GetGlobalObject(env->ctx->ctx); - env->ctx->CreateHandle(top_func, true); - result_val = LEPUS_EvalFunction(env->ctx->ctx, top_func, global); - } - LOG_TIME_END("----- script eval with cache -----"); - } else if (len == 0) { - // if len is 0, we need to make cache. - // if len is -1, someone is modifying the cache, we do not make cache. - LOG_TIME_START(); - LEPUSValue top_func = - LEPUS_Eval(env->ctx->ctx, script, length, filename, - LEPUS_EVAL_FLAG_COMPILE_ONLY | LEPUS_EVAL_TYPE_GLOBAL); - CHECK_QJS(env, - !LEPUS_IsException(top_func) && !LEPUS_IsUndefined(top_func)); - LEPUSValue global = LEPUS_GetGlobalObject(env->ctx->ctx); - env->ctx->CreateHandle(top_func, true); - - size_t obj_len; - data = LEPUS_WriteObject(env->ctx->ctx, &obj_len, top_func, - LEPUS_WRITE_OBJ_BYTECODE); - env->napi_store_code_cache(env, filename, data, - static_cast(obj_len)); - js_free_comp(env->ctx->ctx, - reinterpret_cast(const_cast(data))); - result_val = LEPUS_EvalFunction(env->ctx->ctx, top_func, global); - LOG_TIME_END( - "---- evaluating %s and making code cache for it lengthed %d -----", - filename, (int)obj_len); - } - } - if (LEPUS_IsUninitialized(result_val)) { - LOG_TIME_START(); - result_val = LEPUS_Eval(env->ctx->ctx, script, length, - filename ? filename : "", LEPUS_EVAL_TYPE_GLOBAL); - LOG_TIME_END("----- script eval without cache -----"); - } - CHECK_QJS(env, !LEPUS_IsException(result_val)); - - *result = env->ctx->CreateHandle(result_val); - return napi_clear_last_error(env); -} - -// `data` memory need to be freed from outside -napi_status napi_gen_code_cache(napi_env env, const char* script, - size_t script_len, const uint8_t** data, - int* length) { - if (script_len == NAPI_AUTO_LENGTH) { - script_len = std::strlen(script); - } - LEPUSValue top_func = - LEPUS_Eval(env->ctx->ctx, script, script_len, "", - LEPUS_EVAL_FLAG_COMPILE_ONLY | LEPUS_EVAL_TYPE_GLOBAL); - CHECK_QJS(env, !LEPUS_IsException(top_func) && !LEPUS_IsUndefined(top_func)); - env->ctx->CreateHandle(top_func, true); - - size_t obj_len; - uint8_t* cache = LEPUS_WriteObject(env->ctx->ctx, &obj_len, top_func, - LEPUS_WRITE_OBJ_BYTECODE); - *data = static_cast(std::malloc(obj_len)); - *length = static_cast(obj_len); - memcpy(static_cast(const_cast(*data)), - static_cast(cache), obj_len); - js_free_comp(env->ctx->ctx, reinterpret_cast(cache)); - - return napi_clear_last_error(env); -} - -#endif // ENABLE_CODECACHE - -napi_status napi_add_finalizer(napi_env env, napi_value js_object, - void *native_object, napi_finalize finalize_cb, - void *finalize_hint, napi_ref *result) { - return qjsimpl::Wrap(env, js_object, native_object, - finalize_cb, finalize_hint, result); -} - -napi_status napi_adjust_external_memory(napi_env env, int64_t change_in_bytes, - int64_t *adjusted_value) { - // TODO: Determine if QJS needs or is able to do anything here - // For now, we can lie and say that we always adjusted more memory - *adjusted_value = change_in_bytes; - - return napi_clear_last_error(env); -} - -napi_status napi_set_instance_data(napi_env env, uint64_t key, void *data, - napi_finalize finalize_cb, - void *finalize_hint) { - auto it = env->ctx->instance_data_registry.find(key); - if (it != env->ctx->instance_data_registry.end()) { - return napi_invalid_arg; - } - - env->ctx->instance_data_registry[key] = - qjsimpl::RefBase::New(env, 0, true, finalize_cb, data, finalize_hint); - - return napi_clear_last_error(env); -} - -napi_status napi_get_instance_data(napi_env env, uint64_t key, void **data) { - auto it = env->ctx->instance_data_registry.find(key); - if (it == env->ctx->instance_data_registry.end()) { - *data = nullptr; - } else { - qjsimpl::RefBase *idata = static_cast(it->second); - - *data = idata->Data(); - } - - return napi_clear_last_error(env); -} - -void napi_attach_quickjs(napi_env env, LEPUSContext *context) { - env->ctx = new napi_context__(env, context); - - InitNapiScope(context); -} - -void napi_detach_quickjs(napi_env env) { - LEPUSContext *ctx = env->ctx->ctx; - delete env->ctx; - env->ctx = nullptr; - FreeNapiScope(ctx); -} - -LEPUSContext *napi_get_env_context_quickjs(napi_env env) { - return env->ctx->ctx; -} - -LEPUSValue napi_js_value_to_quickjs_value(napi_env env, napi_value value) { - return JS_DupValue_Comp(env->ctx->ctx, ToJSValue(value)); -} - -napi_value napi_quickjs_value_to_js_value(napi_env env, LEPUSValue value) { - return env->ctx->CreateHandle(value); -} - -inline napi_handle_scope__::napi_handle_scope__(napi_env env, LEPUSContext *ctx, - napi_func *func) - : env_(env), ctx_(ctx), handle_tail_(nullptr), reset_napi_env(func) { - is_gc = env_->ctx->gc_enable; - if (is_gc) { - prev_ = reinterpret_cast(GetNapiScope(ctx_)); - SetNapiScope(ctx_, this); - } else { - prev_ = env_->ctx->handle_scope; - env_->ctx->handle_scope = this; - } -} - -inline napi_value napi_handle_scope__::CreateHandle(LEPUSValue v) { - Handle *h = new Handle{.value = v, .prev = handle_tail_}; - handle_tail_ = h; - return ToNapi(&(h->value)); -} - -inline napi_value napi_handle_scope__::Escape(napi_value v) { - return prev_->CreateHandle(JS_DupValue_Comp(env_->ctx->ctx, ToJSValue(v))); -} - -napi_status primjs_execute_pending_jobs(napi_env env) { - int error; - do { - LEPUSContext *context; - error = LEPUS_ExecutePendingJob(LEPUS_GetRuntime(env->ctx->ctx), &context); - if (error == -1) { - return napi_set_last_error(env, napi_pending_exception); - } - } while (error != 0); - - return napi_clear_last_error(env); -} - - -typedef struct NapiHostObjectInfo { - void *data; - napi_ref ref; - napi_finalize finalize_cb; - bool is_array; - napi_ref getter; - napi_ref setter; -} NapiHostObjectInfo; - -void host_object_finalizer(LEPUSRuntime *rt, LEPUSValue value) { - napi_env env = (napi_env) napi_context__::GetEnv(rt); - NapiHostObjectInfo *info = (NapiHostObjectInfo *) LEPUS_GetOpaque(value, - env->ctx->napiHostObjectClassId); - if (info->finalize_cb) { - info->finalize_cb(env, info->data, NULL); - } - if (info->is_array) { - napi_delete_reference(env, info->getter); - napi_delete_reference(env, info->setter); - } - - napi_delete_reference(env, info->ref); - delete info; -} - -int host_object_set(LEPUSContext *ctx, LEPUSValue obj, JSAtom atom, - LEPUSValue value, LEPUSValue receiver, int flags) { - napi_env env = (napi_env) napi_context__::GetEnv(LEPUS_GetRuntime(ctx)); - NapiHostObjectInfo *info = (NapiHostObjectInfo *) LEPUS_GetOpaque(obj, - env->ctx->napiHostObjectClassId); - if (info != NULL) { - auto *target = reinterpret_cast(info->ref); - if (info->is_array) { - LEPUSValue atom_val = LEPUS_AtomToValue(ctx, atom); - - auto *setter = reinterpret_cast(info->setter); - - LEPUSValue argv[4] = { - ToJSValue(target->Get()), - atom_val, - value, - obj - }; - - LEPUSValue result = LEPUS_Call(ctx, ToJSValue(setter->Get()), LEPUS_UNDEFINED, 4, argv); - - JS_FreeValue_Comp(ctx, atom_val); - - if (LEPUS_IsException(result)) return -1; - - return true; - } - return LEPUS_SetProperty(ctx, ToJSValue(target->Get()), atom, JS_DupValue_Comp(ctx, value)); - } - return true; -} - -LEPUSValue host_object_get(LEPUSContext *ctx, LEPUSValue obj, JSAtom atom, LEPUSValue receiver) { - napi_env env = (napi_env) napi_context__::GetEnv(LEPUS_GetRuntime(ctx)); - NapiHostObjectInfo *info = (NapiHostObjectInfo *) LEPUS_GetOpaque(obj, - env->ctx->napiHostObjectClassId); - if (info != NULL) { - auto *target = reinterpret_cast(info->ref); - if (info->is_array) { - LEPUSValue atom_val = LEPUS_AtomToValue(ctx, atom); - auto *getter = reinterpret_cast(info->getter); - LEPUSValue argv[3] = { - ToJSValue(target->Get()), - atom_val, - obj - }; - LEPUSValue value = LEPUS_Call(ctx, ToJSValue(getter->Get()), LEPUS_UNDEFINED, 3, argv); - JS_FreeValue_Comp(ctx, atom_val); - return value; - } - return LEPUS_GetProperty(ctx, ToJSValue(target->Get()), atom); - } - return LEPUS_UNDEFINED; -} - -int host_object_has(LEPUSContext *ctx, LEPUSValue obj, JSAtom atom) { - napi_env env = (napi_env) napi_context__::GetEnv(LEPUS_GetRuntime(ctx)); - NapiHostObjectInfo *info = (NapiHostObjectInfo *) LEPUS_GetOpaque(obj, - env->ctx->napiHostObjectClassId); - if (info != NULL) { - auto *target = reinterpret_cast(info->ref); - return LEPUS_HasProperty(ctx, ToJSValue(target->Get()), atom); - } - return false; -} - -static int host_object_delete(LEPUSContext *ctx, LEPUSValue obj, JSAtom atom) { - napi_env env = (napi_env) napi_context__::GetEnv(LEPUS_GetRuntime(ctx)); - NapiHostObjectInfo *info = (NapiHostObjectInfo *) LEPUS_GetOpaque(obj, - env->ctx->napiHostObjectClassId); - if (info != NULL) { - auto *target = reinterpret_cast(info->ref); - return LEPUS_DeleteProperty(ctx, ToJSValue(target->Get()), atom, 0); - } - return true; -} - -LEPUSClassExoticMethods NapiHostObjectExoticMethods = { - .get_own_property = nullptr, - .get_own_property_names = nullptr, - .delete_property = host_object_delete, - .define_own_property = nullptr, - .has_property = host_object_has, - .get_property = host_object_get, - .set_property = host_object_set, -}; - -napi_status -napi_create_host_object(napi_env env, napi_value value, napi_finalize finalize, void *data, - bool is_array, napi_value getter, napi_value setter, napi_value *result) { - CHECK_ARG(env, result); - - if (env->ctx->napi_host_object_class_init == 0) { - LEPUSClassDef NapiHostObjectClassDef = {"NapiHostObject", host_object_finalizer, NULL, NULL, - &NapiHostObjectExoticMethods}; - LEPUS_NewClass(env->ctx->rt, env->ctx->napiHostObjectClassId, &NapiHostObjectClassDef); - env->ctx->napi_host_object_class_init = 1; - } - - napi_value constructor; - napi_get_named_property(env, value, "constructor", &constructor); - - napi_value prototype; - napi_get_named_property(env, constructor, "prototype", &prototype); - - LEPUSValue jsValue = LEPUS_NewObjectClass(env->ctx->ctx, env->ctx->napiHostObjectClassId); - LEPUS_SetPrototype(env->ctx->ctx, jsValue, ToJSValue(prototype)); - - NapiHostObjectInfo *info = new NapiHostObjectInfo; - info->data = data; - if (finalize) { - info->finalize_cb = finalize; - } else { - info->finalize_cb = NULL; - } - info->is_array = is_array; - - if (is_array) { - if (getter) napi_create_reference(env, getter, 1, &info->getter); - if (setter) napi_create_reference(env, setter, 1, &info->setter); - } - - napi_create_reference(env, value, 1, &info->ref); - - LEPUS_SetOpaque(jsValue, info); - - *result = env->ctx->CreateHandle(jsValue); - return napi_ok; -} - -napi_status napi_get_host_object_data(napi_env env, napi_value object, void **data) { - CHECK_ARG(env, object); - CHECK_ARG(env, data); - - LEPUSValue jsValue = ToJSValue(object); - - - if (!LEPUS_IsObject(jsValue)) { - return napi_set_last_error(env, napi_object_expected); - } - - NapiHostObjectInfo *info = (NapiHostObjectInfo *) LEPUS_GetOpaque(jsValue, - env->ctx->napiHostObjectClassId); - if (info) { - *data = info->data; - } else { - *data = NULL; - } - - return napi_clear_last_error(env); -} - -napi_status napi_is_host_object(napi_env env, napi_value object, bool *result) { - CHECK_ARG(env, object); - - LEPUSValue jsValue = ToJSValue(object); - - if (!LEPUS_IsObject(jsValue)) { - return napi_set_last_error(env, napi_object_expected); - } - - void *data = LEPUS_GetOpaque(jsValue, - env->ctx->napiHostObjectClassId); - if (data != NULL) { - *result = true; - } else { - *result = false; - } - - return napi_clear_last_error(env); -} \ No newline at end of file diff --git a/test-app/runtime/src/main/cpp/napi/primjs/primjs-api.h b/test-app/runtime/src/main/cpp/napi/primjs/primjs-api.h deleted file mode 100644 index c7953eef..00000000 --- a/test-app/runtime/src/main/cpp/napi/primjs/primjs-api.h +++ /dev/null @@ -1,572 +0,0 @@ -/** - * Copyright (c) 2017 Node.js API collaborators. All Rights Reserved. - * - * Use of this source code is governed by a MIT license that can be - * found in the LICENSE file in the root of the source tree. - */ -// Copyright 2024 The Lynx Authors. All rights reserved. -// Licensed under the Apache License Version 2.0 that can be found in the -// LICENSE file in the root directory of this source tree. -#ifndef SRC_NAPI_QUICKJS_JS_NATIVE_API_QUICKJS_H_ -#define SRC_NAPI_QUICKJS_JS_NATIVE_API_QUICKJS_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus -#include "quickjs/include/quickjs.h" -#ifdef __cplusplus -} -#endif // __cplusplus - -#include "gc/persistent-handle.h" -#include "gc/trace-gc.h" -#include "js_native_api.h" -#include "js_native_api_types.h" -#include "napi_env_quickjs.h" - - -typedef struct napi_env_data__ *napi_env_data; -typedef struct napi_state__ { - napi_extended_error_info last_error; - napi_env_data env_data; -} napi_state; - -typedef struct napi_context__ *napi_context; - -struct napi_env__ { - napi_state state; - napi_runtime rt; - napi_context ctx; - int js_enter_state; -}; - -inline napi_status napi_clear_last_error(napi_env env) { - env->state.last_error.error_code = napi_ok; - env->state.last_error.engine_error_code = 0; - return napi_ok; -} - -inline napi_status napi_set_last_error(napi_env env, napi_status error_code) { - env->state.last_error.error_code = error_code; - return error_code; -} - -inline napi_value ToNapi(LEPUSValueConst *v) { - return reinterpret_cast(v); -} - -inline LEPUSValueConst ToJSValue(napi_value v) { - return *reinterpret_cast(v); -} - -inline LEPUSValue JS_DupValue_Comp(LEPUSContext *ctx, LEPUSValueConst v) { - if (!LEPUS_IsGCMode(ctx)) { - return LEPUS_DupValue(ctx, v); - } - return v; -} - -inline void JS_FreeValue_Comp(LEPUSContext *ctx, LEPUSValue v) { - if (!LEPUS_IsGCMode(ctx)) { - LEPUS_FreeValue(ctx, v); - } -} - -inline void JS_FreeAtom_Comp(LEPUSContext *ctx, JSAtom v) { - if (!LEPUS_IsGCMode(ctx)) { - LEPUS_FreeAtom(ctx, v); - } -} - -inline void JS_FreeCString_Comp(LEPUSContext *ctx, const char *ptr) { - if (!LEPUS_IsGCMode(ctx)) { - LEPUS_FreeCString(ctx, ptr); - } -} - -inline void js_free_comp(LEPUSContext *ctx, void *ptr) { - if (!LEPUS_IsGCMode(ctx)) { - lepus_free(ctx, ptr); - } -} - -namespace qjsimpl { - - class NAPIPersistent; - - class NativeInfo; - - struct WeakInfo { - std::list::const_iterator weak_iter; - std::function cb; - void *cb_arg; - }; - - class NAPIPersistent : public PersistentBase { - public: - /** - * A Persistent with no storage cell. - */ - inline NAPIPersistent() - : PersistentBase(nullptr), - _env(nullptr), - _empty(true), - _native_info(nullptr), - _ctx(nullptr) {} - - /** - * Construct a NAPIPersistent from a Local. - * When the Local is non-empty, a new storage cell is created - * pointing to the same object, and no flags are set. - */ - inline NAPIPersistent(napi_env env, LEPUSValueConst value, - NativeInfo *native_info, LEPUSContext *ctx, - bool is_weak = false); - - inline NAPIPersistent(napi_env env, JSAtom atom, NativeInfo *native_info, - LEPUSContext *ctx, bool is_weak = false); - - NAPIPersistent(const NAPIPersistent &that) = delete; - - NAPIPersistent &operator=(const NAPIPersistent &that) = delete; - - void Reset(bool for_gc = false); - - void Reset(napi_env env, LEPUSValueConst value, NativeInfo *native_info, - LEPUSContext *ctx, bool for_gc = false); - - void Reset(napi_env env, LEPUSContext *ctx, JSAtom atom); - - void SetWeak(void *data, void (*cb)(void *)); - - void ClearWeak(); - - inline ~NAPIPersistent() { Reset(); } - - LEPUSValue Value() const; - - bool IsEmpty() { - if (_ctx != nullptr && LEPUS_IsGCMode(_ctx)) { - return val_ == nullptr; - } else { - return _empty; - } - } - - static void OnFinalize(NAPIPersistent *ref); - - private: - inline LEPUSValue *operator*() const { return this->val_; } - - void ResetWeakInfo(); - - NativeInfo *_get_native_info(); - - napi_env _env; - bool _empty; - LEPUSValue _value; - NativeInfo *_native_info; - std::unique_ptr _weak_info; - LEPUSContext *_ctx; - }; - - class Atom { - public: - Atom() : _env(nullptr), _ctx(nullptr), _atom(0) {} - - Atom(napi_env env, LEPUSContext *ctx, LEPUSValueConst value) - : _env(env), _ctx(ctx), _atom(LEPUS_ValueToAtom(ctx, value)) { - _atom_persist.Reset(_env, _ctx, _atom); - } - - Atom(napi_env env, LEPUSContext *ctx, JSAtom atom) - : _env(env), _ctx(ctx), _atom(atom) { - _atom_persist.Reset(_env, _ctx, _atom); - } - - Atom(napi_env env, LEPUSContext *ctx, const char *str, - size_t length = NAPI_AUTO_LENGTH) - : _env(env), - _ctx(ctx), - _atom(length == NAPI_AUTO_LENGTH ? LEPUS_NewAtom(ctx, str) - : LEPUS_NewAtomLen(ctx, str, length)) { - _atom_persist.Reset(_env, _ctx, _atom); - } - - Atom(Atom &other) - : _env(other._env), - _ctx(other._ctx), - _atom(LEPUS_DupAtom(_ctx, other._atom)) { - _atom_persist.Reset(_env, _ctx, _atom); - } - - Atom(Atom &&other) : _env(other._env), _ctx(other._ctx), _atom(other._atom) { - other._env = nullptr; - other._ctx = nullptr; - other._atom = 0; - other._atom_persist.Reset(true); - _atom_persist.Reset(_env, _ctx, _atom); - } - - ~Atom() { - if (_atom) { - JS_FreeAtom_Comp(_ctx, _atom); - } - _atom_persist.Reset(true); - } - - bool IsValid() { return _atom > 0; } - - operator JSAtom() const { return _atom; } - - private: - napi_env _env; - LEPUSContext *_ctx; - JSAtom _atom; - NAPIPersistent _atom_persist; - }; - - class Value { - public: - Value() : _ctx(nullptr), _val(), pVal(), is_gc(false) {} - - Value(LEPUSContext *ctx, LEPUSValue val) : _ctx(ctx), _val(val), pVal() { - if (ctx) { - is_gc = LEPUS_IsGCMode(ctx); - } - if (is_gc) { - pVal.Reset(nullptr, val, nullptr, ctx, true); - } - } - - ~Value() { - if (is_gc) { - pVal.Reset(true); - } else if (_ctx) { - JS_FreeValue_Comp(_ctx, _val); - } - } - - operator LEPUSValueConst() { - if (is_gc) { - return pVal.Value(); - } else { - return _val; - } - } - - LEPUSValue dup() { - if (is_gc) { - return pVal.Value(); - } else { - return JS_DupValue_Comp(_ctx, _val); - } - } - - LEPUSValue move() { - if (!is_gc) { - _ctx = nullptr; - return _val; - } else { - return pVal.Value(); - } - } - - private: - LEPUSContext *_ctx; - LEPUSValue _val; - NAPIPersistent pVal; - bool is_gc; - }; - - class RefTracker { - public: - RefTracker() {} - - virtual ~RefTracker() {} - - virtual void Finalize(bool isEnvTeardown) {} - - typedef RefTracker RefList; - - inline void Link(RefList *list) { - prev_ = list; - next_ = list->next_; - if (next_ != nullptr) { - next_->prev_ = this; - } - list->next_ = this; - } - - inline void Unlink() { - if (prev_ != nullptr) { - prev_->next_ = next_; - } - if (next_ != nullptr) { - next_->prev_ = prev_; - } - prev_ = nullptr; - next_ = nullptr; - } - - static void FinalizeAll(RefList *list) { - while (list->next_ != nullptr) { - list->next_->Finalize(true); - } - } - - private: - RefList *next_ = nullptr; - RefList *prev_ = nullptr; - }; - - class Reference; - -} // namespace qjsimpl - -inline void reset_napi_env(napi_env env, napi_handle_scope__ *scope); - - - -struct napi_context__ { - napi_env env; - LEPUSRuntime *rt{}; - LEPUSContext *ctx{}; - - LEPUSValue V_NULL{LEPUS_NULL}; - LEPUSValue V_UNDEFINED{LEPUS_UNDEFINED}; - - napi_context__(napi_env env, LEPUSContext *ctx) - : env(env), - rt{LEPUS_GetRuntime(ctx)}, - ctx{ctx}, - PROP_NAME(env, ctx, "name"), - PROP_LENGTH(env, ctx, "length"), - PROP_PROTOTYPE(env, ctx, "prototype"), - PROP_CONSTRUCTOR(env, ctx, "constructor"), - PROP_FINALIZER(env, ctx, "@#fin@#"), - PROP_MESSAGE(env, ctx, "message"), - PROP_CODE(env, ctx, "code"), - PROP_BUFFER(env, ctx, "buffer"), - PROP_BYTELENGTH(env, ctx, "byteLength"), - PROP_BYTEOFFSET(env, ctx, "byteOffset"), - PROP_CTOR_MAGIC(env, ctx, "@#ctor@#"), - gc_enable(LEPUS_IsGCModeRT(rt)) { - env->ctx = this; - napi_context__::rt_to_env_cache.emplace(rt, env); - handle_scope = new napi_handle_scope__(env, ctx, reset_napi_env); - - LEPUSValue gc = LEPUS_NewCFunction(ctx, [](LEPUSContext *ctx, LEPUSValueConst this_val, - int argc, LEPUSValueConst *argv) -> LEPUSValue { - LEPUS_RunGC(LEPUS_GetRuntime(ctx)); - return LEPUS_UNDEFINED; - }, "gc", 0); - auto globalValue = LEPUS_GetGlobalObject(ctx); - LEPUS_SetPropertyStr(ctx, globalValue, "gc", gc); - JS_FreeValue_Comp(ctx, globalValue); - LEPUS_NewClassID(&napiHostObjectClassId); - - // TODO primjs doesn't expose DupContext - } - - ~napi_context__() { - qjsimpl::RefTracker::FinalizeAll(&finalizing_reflist); - qjsimpl::RefTracker::FinalizeAll(&reflist); - - // root handle scope may be used during FinalizeAll - // must delete at last - delete handle_scope; - rt_to_env_cache.erase(rt); - } - - inline void Ref() { refs++; } - - inline void Unref() { - if (--refs == 0) delete this; - } - - template> - inline void CallIntoModule(T &&call, U &&handle_exception) { - int open_handle_scopes_before = open_handle_scopes; - (void) open_handle_scopes_before; - napi_clear_last_error(this->env); - call(this->env); - assert(open_handle_scopes == open_handle_scopes_before); - if (last_exception) { - handle_exception(this->env, *last_exception); - last_exception.reset(); - last_exception_pVal.Reset(true); - } - } - - void CallFinalizer(napi_finalize cb, void *data, void *hint) { - cb(this->env, data, hint); - } - - qjsimpl::RefTracker::RefList reflist; - qjsimpl::RefTracker::RefList finalizing_reflist; - - std::unique_ptr last_exception; - qjsimpl::NAPIPersistent last_exception_pVal; - - std::unordered_map instance_data_registry; - - int napi_host_object_class_init = 0; - LEPUSClassID napiHostObjectClassId = 0; - static std::unordered_map rt_to_env_cache; - - static napi_env GetEnv(LEPUSRuntime* rt) { - auto it = rt_to_env_cache.find(rt); - if (it == rt_to_env_cache.end()) return nullptr; - return it->second; - } - - int open_handle_scopes = 0; - - const qjsimpl::Atom PROP_NAME; - const qjsimpl::Atom PROP_LENGTH; - const qjsimpl::Atom PROP_PROTOTYPE; - const qjsimpl::Atom PROP_CONSTRUCTOR; - const qjsimpl::Atom PROP_FINALIZER; - const qjsimpl::Atom PROP_MESSAGE; - const qjsimpl::Atom PROP_CODE; - const qjsimpl::Atom PROP_BUFFER; - const qjsimpl::Atom PROP_BYTELENGTH; - const qjsimpl::Atom PROP_BYTEOFFSET; - const qjsimpl::Atom PROP_CTOR_MAGIC; - - napi_value CreateHandle(LEPUSValue v, bool only_gc = false) { - if (LEPUS_IsGCMode(ctx)) { - return static_cast(GetNapiScope(ctx))->CreateHandle(v); - } else if (!only_gc) { - return handle_scope->CreateHandle(v); - } - return {}; - } - - void set_handle_scope(napi_handle_scope__ *scope) { handle_scope = scope; } - -private: - int refs = 1; - napi_handle_scope__ *handle_scope{}; - bool gc_enable; - - friend class napi_handle_scope__; -}; - -inline void reset_napi_env(napi_env env, napi_handle_scope__ *scope) { - env->ctx->set_handle_scope(scope); -} - -struct napi_class__qjs { - napi_class__qjs(LEPUSContext *ctx, LEPUSValue proto, LEPUSValue constructor) - : ctx(ctx), proto(proto), constructor(constructor) { - if (LEPUS_IsGCMode(ctx)) { - proto_persist.Reset(nullptr, proto, nullptr, ctx, true); - constructor_persist.Reset(nullptr, constructor, nullptr, ctx, true); - } - } - - ~napi_class__qjs() { - if (LEPUS_IsGCMode(ctx)) { - proto_persist.Reset(true); - constructor_persist.Reset(true); - } else { - LEPUS_FreeValue(ctx, proto); - LEPUS_FreeValue(ctx, constructor); - } - } - - LEPUSValue GetFunction() { return JS_DupValue_Comp(ctx, constructor); } - - LEPUSContext *ctx; - - LEPUSValue proto; - qjsimpl::NAPIPersistent proto_persist; - LEPUSValue constructor; - qjsimpl::NAPIPersistent constructor_persist; -}; - -#define RETURN_STATUS_IF_FALSE(env, condition, status) \ - do { \ - if (!(condition)) { \ - return napi_set_last_error((env), (status)); \ - } \ - } while (0) - -#define CHECK_ARG(env, arg) \ - RETURN_STATUS_IF_FALSE((env), ((arg) != nullptr), napi_invalid_arg) - -#define CHECK_QJS(env, condition) \ - do { \ - if (!(condition)) { \ - return napi_set_exception(env, LEPUS_GetException(env->ctx->ctx)); \ - } \ - } while (0) - -// This does not call napi_set_last_error because the expression -// is assumed to be a NAPI function call that already did. -#define CHECK_NAPI(expr) \ - do { \ - napi_status status = (expr); \ - if (status != napi_ok) return status; \ - } while (0) - -namespace qjsimpl { -// Adapter for napi_finalize callbacks. - class Finalizer { - public: - // Some Finalizers are run during shutdown when the napi_env is destroyed, - // and some need to keep an explicit reference to the napi_env because they - // are run independently. - enum EnvReferenceMode { - kNoEnvReference, kKeepEnvReference - }; - - protected: - Finalizer(napi_env env, napi_finalize finalize_callback, void *finalize_data, - void *finalize_hint, EnvReferenceMode refmode = kNoEnvReference) - : _env(env), - _finalize_callback(finalize_callback), - _finalize_data(finalize_data), - _finalize_hint(finalize_hint), - _has_env_reference(refmode == kKeepEnvReference) { - if (_has_env_reference) _env->ctx->Ref(); - } - - ~Finalizer() { - if (_has_env_reference) _env->ctx->Unref(); - } - - public: - static Finalizer *New(napi_env env, napi_finalize finalize_callback = nullptr, - void *finalize_data = nullptr, - void *finalize_hint = nullptr, - EnvReferenceMode refmode = kNoEnvReference) { - return new Finalizer(env, finalize_callback, finalize_data, finalize_hint, - refmode); - } - - static void Delete(Finalizer *finalizer) { delete finalizer; } - - protected: - napi_env _env; - napi_finalize _finalize_callback; - void *_finalize_data; - void *_finalize_hint; - bool _finalize_ran = false; - bool _has_env_reference = false; - }; - -} // namespace qjsimpl - -#endif // SRC_NAPI_QUICKJS_JS_NATIVE_API_QUICKJS_H_ diff --git a/test-app/runtime/src/main/cpp/napi/primjs/primjs_napi_vtable.h b/test-app/runtime/src/main/cpp/napi/primjs/primjs_napi_vtable.h new file mode 100644 index 00000000..f032b224 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/primjs/primjs_napi_vtable.h @@ -0,0 +1,520 @@ +// PrimJS Node-API vtable. +// +// `struct napi_env__` below is the function-pointer table that the prebuilt +// primjs `libnapi.so` installs on every napi_env via the exported +// napi_attach_quickjs(). The adapter (js_native_api_adapter.cc) forwards the +// standard-named napi_* C entry points into these slots. +// +// This is a verbatim mirror of `struct napi_env__` in primjs' +// src/napi/js_native_api.h, built with ENABLE_CODECACHE=ON. KEEP IT IN SYNC: +// append new members at the END only -- never reorder or remove -- to preserve +// the ABI the shipped libnapi.so expects. + +#ifndef TEST_APP_PRIMJS_NAPI_VTABLE_H +#define TEST_APP_PRIMJS_NAPI_VTABLE_H + +#include "js_native_api.h" // standard napi types (napi_env, napi_value, ...) + +#include +#include +#include +#include + +// --- primjs-internal handle/callback types. Only their pointer/enum size is +// --- relevant here: every use below is a vtable *slot* (function pointer) or a +// --- leading env pointer, so opaque placeholders keep the layout ABI-exact. +typedef void* napi_state; +typedef void* napi_runtime; +typedef void* napi_context; +typedef void* napi_context_scope; +typedef void* napi_error_scope; +typedef void* napi_class; +typedef void* napi_async_work; +typedef void* napi_threadsafe_function; +typedef void (*napi_async_execute_callback)(napi_env env, void* data); +typedef void (*napi_async_complete_callback)(napi_env env, napi_status status, + void* data); +typedef void (*napi_threadsafe_function_call_js)(napi_env env, napi_value cb, + void* ctx, void* data); +typedef int napi_threadsafe_function_call_mode; +typedef int napi_status_legacy; + +typedef enum { + napi_deferred_resolve, + napi_deferred_reject, + napi_deferred_delete +} napi_deferred_release_mode; + +struct napi_env__ { + napi_state state; + napi_runtime rt; + napi_context ctx; + + // Warning: Keep in-sync with macros in napi_macro.h! + // Always append function at the end to keep ABI compatible! + + napi_status (*napi_get_version)(napi_env env, uint32_t* result); + + // ENGINE CALL + // Getters for defined singletons + napi_status (*napi_get_undefined)(napi_env env, napi_value* result); + napi_status (*napi_get_null)(napi_env env, napi_value* result); + napi_status (*napi_get_global)(napi_env env, napi_value* result); + napi_status (*napi_get_boolean)(napi_env env, bool value, napi_value* result); + + // Methods to create Primitive types/Objects + napi_status (*napi_create_object)(napi_env env, napi_value* result); + napi_status (*napi_create_array)(napi_env env, napi_value* result); + napi_status (*napi_create_array_with_length)(napi_env env, size_t length, + napi_value* result); + napi_status (*napi_create_double)(napi_env env, double value, + napi_value* result); + napi_status (*napi_create_int32)(napi_env env, int32_t value, + napi_value* result); + napi_status (*napi_create_uint32)(napi_env env, uint32_t value, + napi_value* result); + napi_status (*napi_create_int64)(napi_env env, int64_t value, + napi_value* result); + napi_status (*napi_create_string_latin1)(napi_env env, const char* str, + size_t length, napi_value* result); + napi_status (*napi_create_string_utf8)(napi_env env, const char* str, + size_t length, napi_value* result); + napi_status (*napi_create_string_utf16)(napi_env env, const char16_t* str, + size_t length, napi_value* result); + napi_status (*napi_create_symbol)(napi_env env, napi_value description, + napi_value* result); + napi_status (*napi_create_function)(napi_env env, const char* utf8name, + size_t length, napi_callback cb, + void* data, napi_value* result); + napi_status (*napi_create_error)(napi_env env, napi_value code, + napi_value msg, napi_value* result); + napi_status (*napi_create_type_error)(napi_env env, napi_value code, + napi_value msg, napi_value* result); + napi_status (*napi_create_range_error)(napi_env env, napi_value code, + napi_value msg, napi_value* result); + + // Methods to get the native napi_value from Primitive type + napi_status (*napi_typeof)(napi_env env, napi_value value, + napi_valuetype* result); + napi_status (*napi_get_value_double)(napi_env env, napi_value value, + double* result); + napi_status (*napi_get_value_int32)(napi_env env, napi_value value, + int32_t* result); + napi_status (*napi_get_value_uint32)(napi_env env, napi_value value, + uint32_t* result); + napi_status (*napi_get_value_int64)(napi_env env, napi_value value, + int64_t* result); + napi_status (*napi_get_value_bool)(napi_env env, napi_value value, + bool* result); + + // Copies LATIN-1 encoded bytes from a string into a buffer. + napi_status (*napi_get_value_string_latin1)(napi_env env, napi_value value, + char* buf, size_t bufsize, + size_t* result); + + // Copies UTF-8 encoded bytes from a string into a buffer. + napi_status (*napi_get_value_string_utf8)(napi_env env, napi_value value, + char* buf, size_t bufsize, + size_t* result); + + // Copies UTF-16 encoded bytes from a string into a buffer. + napi_status (*napi_get_value_string_utf16)(napi_env env, napi_value value, + char16_t* buf, size_t bufsize, + size_t* result); + + // Methods to coerce values + // These APIs may execute user scripts + napi_status (*napi_coerce_to_bool)(napi_env env, napi_value value, + napi_value* result); + napi_status (*napi_coerce_to_number)(napi_env env, napi_value value, + napi_value* result); + napi_status (*napi_coerce_to_object)(napi_env env, napi_value value, + napi_value* result); + napi_status (*napi_coerce_to_string)(napi_env env, napi_value value, + napi_value* result); + + // Methods to work with Objects + napi_status (*napi_get_prototype)(napi_env env, napi_value object, + napi_value* result); + napi_status (*napi_get_property_names)(napi_env env, napi_value object, + napi_value* result); + napi_status (*napi_set_property)(napi_env env, napi_value object, + napi_value key, napi_value value); + napi_status (*napi_has_property)(napi_env env, napi_value object, + napi_value key, bool* result); + napi_status (*napi_get_property)(napi_env env, napi_value object, + napi_value key, napi_value* result); + napi_status (*napi_delete_property)(napi_env env, napi_value object, + napi_value key, bool* result); + napi_status (*napi_has_own_property)(napi_env env, napi_value object, + napi_value key, bool* result); + napi_status (*napi_set_named_property)(napi_env env, napi_value object, + const char* utf8name, + napi_value value); + napi_status (*napi_has_named_property)(napi_env env, napi_value object, + const char* utf8name, bool* result); + napi_status (*napi_get_named_property)(napi_env env, napi_value object, + const char* utf8name, + napi_value* result); + napi_status (*napi_set_element)(napi_env env, napi_value object, + uint32_t index, napi_value value); + napi_status (*napi_has_element)(napi_env env, napi_value object, + uint32_t index, bool* result); + napi_status (*napi_get_element)(napi_env env, napi_value object, + uint32_t index, napi_value* result); + napi_status (*napi_delete_element)(napi_env env, napi_value object, + uint32_t index, bool* result); + + napi_status (*napi_define_properties)( + napi_env env, napi_value object, size_t property_count, + const napi_property_descriptor* properties); + + // Methods to work with Arrays + napi_status (*napi_is_array)(napi_env env, napi_value value, bool* result); + napi_status (*napi_get_array_length)(napi_env env, napi_value value, + uint32_t* result); + + // Methods to compare values + napi_status (*napi_strict_equals)(napi_env env, napi_value lhs, + napi_value rhs, bool* result); + + // Methods to work with Functions + napi_status (*napi_call_function)(napi_env env, napi_value recv, + napi_value func, size_t argc, + const napi_value* argv, napi_value* result); + napi_status (*napi_new_instance)(napi_env env, napi_value constructor, + size_t argc, const napi_value* argv, + napi_value* result); + napi_status (*napi_instanceof)(napi_env env, napi_value object, + napi_value constructor, bool* result); + + // Methods to work with napi_callbacks + + // Gets all callback info in a single call. (Ugly, but faster.) + napi_status (*napi_get_cb_info)( + napi_env env, // [in] NAPI environment handle + napi_callback_info cbinfo, // [in] Opaque callback-info handle + size_t* argc, // [in-out] Specifies the size of the provided argv array + // and receives the actual count of args. + napi_value* argv, // [out] Array of values + napi_value* this_arg, // [out] Receives the JS 'this' arg for the call + void** data); // [out] Receives the data pointer for the callback. + + napi_status (*napi_get_new_target)(napi_env env, napi_callback_info cbinfo, + napi_value* result); + + napi_status (*napi_define_class)(napi_env env, const char* utf8name, + size_t length, napi_callback constructor, + void* data, size_t property_count, + const napi_property_descriptor* properties, + napi_class super_class, napi_class* result); + + napi_status (*napi_release_class)(napi_env env, napi_class clazz); + + napi_status (*napi_class_get_function)(napi_env env, napi_class clazz, + napi_value* result); + + // Methods to work with external data objects + napi_status (*napi_wrap)(napi_env env, napi_value js_object, + void* native_object, napi_finalize finalize_cb, + void* finalize_hint, napi_ref* result); + napi_status (*napi_unwrap)(napi_env env, napi_value js_object, void** result); + napi_status (*napi_remove_wrap)(napi_env env, napi_value js_object, + void** result); + napi_status (*napi_create_external)(napi_env env, void* data, + napi_finalize finalize_cb, + void* finalize_hint, napi_value* result); + napi_status (*napi_get_value_external)(napi_env env, napi_value value, + void** result); + + // Methods to control object lifespan + + // Set initial_refcount to 0 for a weak reference, >0 for a strong reference. + napi_status (*napi_create_reference)(napi_env env, napi_value value, + uint32_t initial_refcount, + napi_ref* result); + + // Deletes a reference. The referenced value is released, and may + // be GC'd unless there are other references to it. + napi_status (*napi_delete_reference)(napi_env env, napi_ref ref); + + // Increments the reference count, optionally returning the resulting count. + // After this call the reference will be a strong reference because its + // refcount is >0, and the referenced object is effectively "pinned". + // Calling this when the refcount is 0 and the object is unavailable + // results in an error. + napi_status (*napi_reference_ref)(napi_env env, napi_ref ref, + uint32_t* result); + + // Decrements the reference count, optionally returning the resulting count. + // If the result is 0 the reference is now weak and the object may be GC'd + // at any time if there are no other references. Calling this when the + // refcount is already 0 results in an error. + napi_status (*napi_reference_unref)(napi_env env, napi_ref ref, + uint32_t* result); + + // Attempts to get a referenced value. If the reference is weak, + // the value might no longer be available, in that case the call + // is still successful but the result is NULL. + napi_status (*napi_get_reference_value)(napi_env env, napi_ref ref, + napi_value* result); + + napi_status (*napi_open_handle_scope)(napi_env env, + napi_handle_scope* result); + napi_status (*napi_close_handle_scope)(napi_env env, napi_handle_scope scope); + napi_status (*napi_open_escapable_handle_scope)( + napi_env env, napi_escapable_handle_scope* result); + napi_status (*napi_close_escapable_handle_scope)( + napi_env env, napi_escapable_handle_scope scope); + + napi_status (*napi_escape_handle)(napi_env env, + napi_escapable_handle_scope scope, + napi_value escapee, napi_value* result); + + // Methods to support error handling + napi_status (*napi_throw_)(napi_env env, napi_value error); + napi_status (*napi_throw_error)(napi_env env, const char* code, + const char* msg); + napi_status (*napi_throw_type_error)(napi_env env, const char* code, + const char* msg); + napi_status (*napi_throw_range_error)(napi_env env, const char* code, + const char* msg); + napi_status (*napi_is_error)(napi_env env, napi_value value, bool* result); + + // Methods to support catching exceptions + napi_status (*napi_is_exception_pending)(napi_env env, bool* result); + napi_status (*napi_get_and_clear_last_exception)(napi_env env, + napi_value* result); + + // Methods to work with array buffers and typed arrays + napi_status (*napi_is_arraybuffer)(napi_env env, napi_value value, + bool* result); + napi_status (*napi_create_arraybuffer)(napi_env env, size_t byte_length, + void** data, napi_value* result); + napi_status (*napi_create_external_arraybuffer)( + napi_env env, void* external_data, size_t byte_length, + napi_finalize finalize_cb, void* finalize_hint, napi_value* result); + napi_status (*napi_get_arraybuffer_info)(napi_env env, napi_value arraybuffer, + void** data, size_t* byte_length); + napi_status (*napi_is_typedarray)(napi_env env, napi_value value, + bool* result); + napi_status (*napi_create_typedarray)(napi_env env, napi_typedarray_type type, + size_t length, napi_value arraybuffer, + size_t byte_offset, napi_value* result); + + napi_status (*napi_is_typedarray_of)(napi_env env, napi_value typedarray, + napi_typedarray_type type, bool* result); + + napi_status (*napi_get_typedarray_info)(napi_env env, napi_value typedarray, + napi_typedarray_type* type, + size_t* length, void** data, + napi_value* arraybuffer, + size_t* byte_offset); + + napi_status (*napi_create_dataview)(napi_env env, size_t length, + napi_value arraybuffer, + size_t byte_offset, napi_value* result); + napi_status (*napi_is_dataview)(napi_env env, napi_value value, bool* result); + napi_status (*napi_get_dataview_info)(napi_env env, napi_value dataview, + size_t* bytelength, void** data, + napi_value* arraybuffer, + size_t* byte_offset); + + // Promises + napi_status (*napi_create_promise)(napi_env env, napi_deferred* deferred, + napi_value* promise); + napi_status (*napi_release_deferred)(napi_env env, napi_deferred deferred, + napi_value resolution, + napi_deferred_release_mode mode); + napi_status (*napi_is_promise)(napi_env env, napi_value value, + bool* is_promise); + + // Running a script + napi_status (*napi_run_script)(napi_env env, const char* script, + size_t length, const char* filename, + napi_value* result); + + // Memory management + napi_status (*napi_adjust_external_memory)(napi_env env, + int64_t change_in_bytes, + int64_t* adjusted_value); + + // Add finalizer for pointer + napi_status (*napi_add_finalizer)(napi_env env, napi_value js_object, + void* native_object, + napi_finalize finalize_cb, + void* finalize_hint, napi_ref* result); + + // Instance data + napi_status_legacy (*napi_set_instance_data)(napi_env env, uint64_t key, + void* data, + napi_finalize finalize_cb, + void* finalize_hint); + + napi_status (*napi_get_instance_data)(napi_env env, uint64_t key, + void** data); + + // ENGINE CALL END + + // Universal CALL + napi_status (*napi_get_last_error_info)( + napi_env env, const napi_extended_error_info** result); + + napi_status (*napi_add_env_cleanup_hook)(napi_env env, void (*fun)(void* arg), + void* arg); + napi_status (*napi_remove_env_cleanup_hook)(napi_env env, + void (*fun)(void* arg), + void* arg); + + napi_status (*napi_create_async_work)(napi_env env, napi_value async_resource, + napi_value async_resource_name, + napi_async_execute_callback execute, + napi_async_complete_callback complete, + void* data, napi_async_work* result); + + napi_status (*napi_delete_async_work)(napi_env env, napi_async_work work); + napi_status (*napi_queue_async_work)(napi_env env, napi_async_work work); + napi_status (*napi_cancel_async_work)(napi_env env, napi_async_work work); + + // Calling into JS from other threads + napi_status (*napi_create_threadsafe_function)( + napi_env env, void* thread_finalize_data, + napi_finalize thread_finalize_cb, void* context, + napi_threadsafe_function_call_js call_js_cb, + napi_threadsafe_function* result); + + napi_status (*napi_get_threadsafe_function_context)( + napi_threadsafe_function func, void** result); + + napi_status (*napi_call_threadsafe_function)( + napi_threadsafe_function func, void* data, + napi_threadsafe_function_call_mode is_blocking); + + // no need to acquire tsfn, just hold the pointer and release in any thread + napi_status (*napi_acquire_threadsafe_function)( + napi_threadsafe_function func); + + napi_status (*napi_delete_threadsafe_function)(napi_threadsafe_function func); + + // no need to ref thread + napi_status (*napi_unref_threadsafe_function)( + napi_env env, napi_threadsafe_function func); + + // no need to ref thread + napi_status (*napi_ref_threadsafe_function)( + napi_env env, napi_threadsafe_function func); + + napi_status (*napi_get_loader)(napi_env env, napi_value* result); + + // UNIVERSAL CALL END + + napi_status (*napi_open_context_scope)(napi_env env, + napi_context_scope* result); + napi_status_legacy (*napi_close_context_scope)(napi_env env, + napi_context_scope scope); + + napi_status (*napi_open_error_scope)(napi_env env, napi_error_scope* result); + napi_status (*napi_close_error_scope)(napi_env env, napi_error_scope scope); + + // loose equals + napi_status (*napi_equals)(napi_env env, napi_value lhs, napi_value rhs, + bool* result); + + napi_status (*napi_get_unhandled_rejection_exception)(napi_env env, + napi_value* result); + napi_status (*napi_get_own_property_descriptor)(napi_env env, napi_value obj, + napi_value prop, + napi_value* result); + napi_status (*napi_post_worker_task)(napi_env env, + std::function task); + napi_status (*napi_store_code_cache)(napi_env env, + const std::string& filename, + const uint8_t* data, int length); + napi_status (*napi_get_code_cache)(napi_env env, const std::string& filename, + const uint8_t** data, int* length); + napi_status (*napi_output_code_cache)(napi_env env, + unsigned int place_holder); + // this interface may be optimized by + // discarding the parameter of std::function type + napi_status (*napi_init_code_cache)(napi_env env, int capacity, + const std::string& cache_file, + std::function callback); + napi_status (*napi_dump_code_cache_status)(napi_env env, void* dump_vec); + napi_status (*napi_run_script_cache)(napi_env env, const char* script, + size_t length, const char* filename, + napi_value* result); + napi_status (*napi_run_code_cache)(napi_env env, const uint8_t* data, + int length, napi_value* result); + napi_status (*napi_gen_code_cache)(napi_env env, const char* script, + size_t script_len, const uint8_t** data, + int* length); + + napi_status (*napi_set_instance_data_spec_compliant)( + napi_env env, uint64_t key, void* data, napi_finalize finalize_cb, + void* finalize_hint); + + napi_status (*napi_define_properties_spec_compliant)( + napi_env env, napi_value object, size_t property_count, + const napi_property_descriptor* properties); + + napi_status (*napi_define_class_spec_compliant)( + napi_env env, const char* utf8name, size_t length, + napi_callback constructor, void* data, size_t property_count, + const napi_property_descriptor* properties, napi_class super_class, + napi_class* result); + + napi_status (*napi_call_function_spec_compliant)(napi_env env, + napi_value recv, + napi_value func, size_t argc, + const napi_value* argv, + napi_value* result); + + napi_status (*napi_wrap_spec_compliant)(napi_env env, napi_value js_object, + void* native_object, + napi_finalize finalize_cb, + void* finalize_hint, + napi_ref* result); + napi_status (*napi_unwrap_spec_compliant)(napi_env env, napi_value js_object, + void** result); + napi_status (*napi_remove_wrap_spec_compliant)(napi_env env, + napi_value js_object, + void** result); + + napi_status (*napi_create_date)(napi_env env, double time, + napi_value* result); + + napi_status (*napi_is_date)(napi_env env, napi_value value, bool* is_date); + + napi_status (*napi_get_date_value)(napi_env env, napi_value value, + double* result); + + napi_status (*napi_get_all_property_names)(napi_env env, napi_value object, + napi_key_collection_mode key_mode, + napi_key_filter key_filter, + napi_key_conversion key_conversion, + napi_value* result); + + napi_status (*napi_create_threadsafe_function_spec_compliant)( + napi_env env, void* thread_finalize_data, + napi_finalize thread_finalize_cb, void* context, + napi_threadsafe_function_call_js call_js_cb, size_t max_queue_size, + size_t thread_count, napi_threadsafe_function* result); + + napi_status (*napi_create_bigint_int64)(napi_env env, int64_t value, + napi_value* result); + napi_status (*napi_create_bigint_uint64)(napi_env env, uint64_t value, + napi_value* result); + napi_status (*napi_get_value_bigint_int64)(napi_env env, napi_value value, + int64_t* result, bool* lossless); + napi_status (*napi_get_value_bigint_uint64)(napi_env env, napi_value value, + uint64_t* result, bool* lossless); + napi_status (*napi_create_bigint_words)(napi_env env, int sign_bit, + size_t word_count, + const uint64_t* words, + napi_value* result); + napi_status (*napi_get_value_bigint_words)(napi_env env, napi_value value, + int* sign_bit, size_t* word_count, + uint64_t* words); +}; + +#endif // TEST_APP_PRIMJS_NAPI_VTABLE_H diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/jsr.cpp b/test-app/runtime/src/main/cpp/napi/quickjs/jsr.cpp index b9ec43e7..e6b91b19 100644 --- a/test-app/runtime/src/main/cpp/napi/quickjs/jsr.cpp +++ b/test-app/runtime/src/main/cpp/napi/quickjs/jsr.cpp @@ -4,11 +4,27 @@ JSR::JSR() = default; tns::SimpleMap JSR::env_to_jsr_cache; -napi_status js_create_runtime(napi_runtime *runtime) { - return qjs_create_runtime(runtime); +// Engine-agnostic runtime handle for the jsr layer. QuickJS keeps its own +// napi_runtime (the real engine runtime defined in quickjs-api.c); this wrapper +// just points at it so the jsr API can speak jsr_ns_runtime while +// quickjs-api.c / quicks-runtime.h stay unchanged. +struct jsr_ns_runtime__ { + napi_runtime rt; +}; + +napi_status js_create_runtime(jsr_ns_runtime *runtime) { + if (!runtime) return napi_invalid_arg; + auto *wrapper = new jsr_ns_runtime__(); + napi_status status = qjs_create_runtime(&wrapper->rt); + if (status != napi_ok) { + delete wrapper; + return status; + } + *runtime = wrapper; + return napi_ok; } -napi_status js_create_napi_env(napi_env *env, napi_runtime runtime) { - napi_status status = qjs_create_napi_env(env, runtime); +napi_status js_create_napi_env(napi_env *env, jsr_ns_runtime runtime) { + napi_status status = qjs_create_napi_env(env, runtime->rt); JSR::env_to_jsr_cache.Insert((*env), new JSR()); return status; } @@ -37,8 +53,10 @@ napi_status js_free_napi_env(napi_env env) { return qjs_free_napi_env(env); } -napi_status js_free_runtime(napi_runtime runtime) { - return qjs_free_runtime(runtime); +napi_status js_free_runtime(jsr_ns_runtime runtime) { + napi_status status = qjs_free_runtime(runtime->rt); + delete runtime; + return status; } napi_status js_execute_script(napi_env env, diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/quickjs-api.c b/test-app/runtime/src/main/cpp/napi/quickjs/quickjs-api.c index 627c3731..81297859 100644 --- a/test-app/runtime/src/main/cpp/napi/quickjs/quickjs-api.c +++ b/test-app/runtime/src/main/cpp/napi/quickjs/quickjs-api.c @@ -220,14 +220,13 @@ typedef struct ExternalInfo { napi_finalize finalizeCallback; // size_t } ExternalInfo; +#ifdef USE_HOST_OBJECT typedef struct NapiHostObjectInfo { void *data; - napi_ref ref; napi_finalize finalize_cb; - bool is_array; - napi_ref getter; - napi_ref setter; + napi_host_object_methods methods; } NapiHostObjectInfo; +#endif typedef struct JsAtoms { @@ -428,7 +427,7 @@ static inline napi_status CreateJSValueHandle(napi_env env, JSValue value, struc CHECK_ARG(env) CHECK_ARG(result) - RETURN_STATUS_IF_FALSE(!LIST_EMPTY(&env->handleScopeList), napi_handle_scope_empty) + RETURN_STATUS_IF_FALSE(!LIST_EMPTY(&env->handleScopeList), napi_handle_scope_mismatch) napi_handle_scope handleScope = LIST_FIRST(&env->handleScopeList); @@ -484,7 +483,7 @@ napi_status napi_open_handle_scope(napi_env env, napi_handle_scope *result) { napi_handle_scope__ *handleScope = (napi_handle_scope__ *) mi_malloc( sizeof(napi_handle_scope__)); - RETURN_STATUS_IF_FALSE(handleScope, napi_memory_error) + RETURN_STATUS_IF_FALSE(handleScope, napi_handle_scope_mismatch) handleScope->type = HANDLE_HEAP_ALLOCATED; handleScope->handleCount = 0; handleScope->escapeCalled = false; @@ -530,12 +529,12 @@ napi_status napi_open_escapable_handle_scope(napi_env env, napi_escapable_handle sizeof(napi_handle_scope__)); handleScope->type = HANDLE_HEAP_ALLOCATED; handleScope->handleCount = 0; - RETURN_STATUS_IF_FALSE(handleScope, napi_memory_error) + RETURN_STATUS_IF_FALSE(handleScope, napi_handle_scope_mismatch) SLIST_INIT(&handleScope->handleList); handleScope->escapeCalled = false; LIST_INSERT_HEAD(&env->handleScopeList, handleScope, node); - *result = handleScope; + *result = (napi_escapable_handle_scope) handleScope; return napi_clear_last_error(env); } @@ -545,23 +544,27 @@ napi_close_escapable_handle_scope(napi_env env, napi_escapable_handle_scope esca CHECK_ARG(env) CHECK_ARG(escapableScope) - assert(LIST_FIRST(&env->handleScopeList) == escapableScope && + // Escapable scopes share the napi_handle_scope__ representation; the public + // type is opaque and distinct, so cast to operate on the members. + napi_handle_scope__ *scope = (napi_handle_scope__ *) escapableScope; + + assert(LIST_FIRST(&env->handleScopeList) == scope && "napi_close_handle_scope() or napi_close_escapable_handle_scope() should follow FILO rule."); Handle *handle, *tempHandle; - SLIST_FOREACH_SAFE(handle, &escapableScope->handleList, node, tempHandle) { + SLIST_FOREACH_SAFE(handle, &scope->handleList, node, tempHandle) { JS_FreeValue(env->context, handle->value); handle->value = JSUndefined; // Instead of freeing, return the handle to the pool for reuse - SLIST_REMOVE(&escapableScope->handleList, handle, Handle, node); + SLIST_REMOVE(&scope->handleList, handle, Handle, node); if (handle->type == HANDLE_HEAP_ALLOCATED) { mi_free(handle); } } - LIST_REMOVE(escapableScope, node); - mi_free(escapableScope); + LIST_REMOVE(scope, node); + mi_free(scope); return napi_clear_last_error(env); } @@ -574,16 +577,20 @@ napi_status napi_escape_handle(napi_env env, napi_escapable_handle_scope scope, CHECK_ARG(scope) CHECK_ARG(escapee) - RETURN_STATUS_IF_FALSE(!scope->escapeCalled, napi_escape_called_twice) + // Escapable scopes share the napi_handle_scope__ representation; the public + // type is opaque and distinct, so cast to operate on the members. + napi_handle_scope__ *hs = (napi_handle_scope__ *) scope; + + RETURN_STATUS_IF_FALSE(!hs->escapeCalled, napi_escape_called_twice) // Get the outer handle scope - napi_handle_scope handleScope = LIST_NEXT(scope, node); - RETURN_STATUS_IF_FALSE(handleScope, napi_handle_scope_empty) + napi_handle_scope handleScope = LIST_NEXT(hs, node); + RETURN_STATUS_IF_FALSE(handleScope, napi_handle_scope_mismatch) Handle *handle = (Handle *) mi_malloc(sizeof(Handle)); - RETURN_STATUS_IF_FALSE(handle, napi_memory_error) + RETURN_STATUS_IF_FALSE(handle, napi_handle_scope_mismatch) - scope->escapeCalled = true; + hs->escapeCalled = true; handle->value = JS_DupValue(env->context, *((JSValue *) escapee)); SLIST_INSERT_HEAD(&handleScope->handleList, handle, node); @@ -796,7 +803,7 @@ napi_create_reference(napi_env env, napi_value value, uint32_t initialRefCount, CHECK_ARG(result) *result = (napi_ref__ *) mi_malloc(sizeof(napi_ref__)); - RETURN_STATUS_IF_FALSE(*result, napi_memory_error) + RETURN_STATUS_IF_FALSE(*result, napi_generic_failure) JSValue jsValue = *((JSValue *) value); @@ -2043,8 +2050,15 @@ napi_status napi_get_value_string_latin1(napi_env env, napi_value value, char *s CHECK_ARG(result) *result = cstr_len; } else if (length != 0) { - strcpy(str, cstr); - str[cstr_len] = '\0'; + // Respect the destination buffer size (length includes the null + // terminator) and report the number of bytes written, excluding the + // null — matching the Node-API contract. + size_t to_copy = cstr_len < length - 1 ? cstr_len : length - 1; + memcpy(str, cstr, to_copy); + str[to_copy] = '\0'; + if (result != NULL) { + *result = to_copy; + } } else if (result != NULL) { *result = 0; } @@ -2069,8 +2083,15 @@ napi_status napi_get_value_string_utf8(napi_env env, napi_value value, char *str CHECK_ARG(result) *result = cstr_len; } else if (length != 0) { - strcpy(str, cstr); - str[cstr_len] = '\0'; + // Respect the destination buffer size (length includes the null + // terminator) and report the number of bytes written, excluding the + // null — matching the Node-API contract. + size_t to_copy = cstr_len < length - 1 ? cstr_len : length - 1; + memcpy(str, cstr, to_copy); + str[to_copy] = '\0'; + if (result != NULL) { + *result = to_copy; + } } else if (result != NULL) { *result = 0; } @@ -3210,7 +3231,7 @@ napi_create_function(napi_env env, const char *utf8name, size_t length, napi_cal CHECK_ARG(result) FunctionInfo *functionInfo = (FunctionInfo *) mi_malloc(sizeof(FunctionInfo)); - RETURN_STATUS_IF_FALSE(functionInfo, napi_memory_error) + RETURN_STATUS_IF_FALSE(functionInfo, napi_generic_failure) functionInfo->data = data; functionInfo->callback = cb; @@ -3838,169 +3859,146 @@ napi_status napi_run_script(napi_env env, } +#ifdef USE_HOST_OBJECT + +// Open/close a temporary handle scope around a host-object callback. Mirrors +// the function-callback trampoline (only heap-allocated handles are freed; +// stack handles live in the scope struct). +#define HO_SCOPE_OPEN \ + napi_handle_scope__ _hs; \ + _hs.type = HANDLE_STACK_ALLOCATED; \ + _hs.handleCount = 0; \ + _hs.escapeCalled = false; \ + SLIST_INIT(&_hs.handleList); \ + LIST_INSERT_HEAD(&env->handleScopeList, &_hs, node); +#define HO_SCOPE_CLOSE \ + do { \ + Handle *_h, *_th; \ + SLIST_FOREACH_SAFE(_h, &_hs.handleList, node, _th) { \ + JS_FreeValue(env->context, _h->value); \ + _h->value = JSUndefined; \ + SLIST_REMOVE(&_hs.handleList, _h, Handle, node); \ + if (_h->type == HANDLE_HEAP_ALLOCATED) mi_free(_h); \ + } \ + LIST_REMOVE(&_hs, node); \ + } while (0) + void host_object_finalizer(JSRuntime *rt, JSValue value) { napi_env env = (napi_env) JS_GetRuntimeOpaque(rt); - NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque(value, - env->runtime->napiHostObjectClassId); + NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque( + value, env->runtime->napiHostObjectClassId); + if (info == NULL) return; if (info->finalize_cb) { info->finalize_cb(env, info->data, NULL); } - if (info->is_array) { - napi_delete_reference(env, info->getter); - napi_delete_reference(env, info->setter); - } - - napi_delete_reference(env, info->ref); mi_free(info); } int host_object_set(JSContext *ctx, JSValue obj, JSAtom atom, JSValue value, JSValue receiver, int flags) { napi_env env = (napi_env) JS_GetContextOpaque(ctx); - NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque(obj, - env->runtime->napiHostObjectClassId); - if (info != NULL) { - if (info->is_array) { - JSValue atom_val = JS_AtomToValue(ctx, atom); - JSValue argv[4] = { - info->ref->value, - atom_val, - value, - obj - }; - JSValue result = JS_Call(ctx, info->setter->value, JS_UNDEFINED, 4, argv); - - JS_FreeValue(ctx, atom_val); - - if (JS_IsException(result) || JS_HasException(ctx)) return -1; - - return true; - } - return JS_SetProperty(ctx, info->ref->value, atom, JS_DupValue(ctx, value)); - } + NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque( + obj, env->runtime->napiHostObjectClassId); + if (info == NULL || info->methods.set == NULL) return true; + + HO_SCOPE_OPEN + napi_value host, prop, val; + CreateScopedResult(env, JS_DupValue(ctx, obj), &host); + CreateScopedResult(env, JS_AtomToValue(ctx, atom), &prop); + CreateScopedResult(env, JS_DupValue(ctx, value), &val); + info->methods.set(env, host, prop, val, info->data); + HO_SCOPE_CLOSE; + + if (JS_HasException(ctx)) return -1; return true; } JSValue host_object_get(JSContext *ctx, JSValue obj, JSAtom atom, JSValue receiver) { napi_env env = (napi_env) JS_GetContextOpaque(ctx); - NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque(obj, - env->runtime->napiHostObjectClassId); - if (info != NULL) { - if (info->is_array) { - JSValue atom_val = JS_AtomToValue(ctx, atom); - JSValue argv[3] = { - info->ref->value, - atom_val, - obj - }; - JSValue value = JS_Call(ctx, info->getter->value, JS_UNDEFINED, 3, argv); - JS_FreeValue(ctx, atom_val); - return value; - } - return JS_GetProperty(ctx, info->ref->value, atom); + NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque( + obj, env->runtime->napiHostObjectClassId); + if (info == NULL || info->methods.get == NULL) return JS_UNDEFINED; + + HO_SCOPE_OPEN + napi_value host, prop; + CreateScopedResult(env, JS_DupValue(ctx, obj), &host); + CreateScopedResult(env, JS_AtomToValue(ctx, atom), &prop); + napi_value result = info->methods.get(env, host, prop, info->data); + JSValue ret = JS_UNDEFINED; + if (result != NULL) { + ret = JS_DupValue(ctx, *((JSValue *) result)); } - return JS_UNDEFINED; + HO_SCOPE_CLOSE; + + if (JS_HasException(ctx)) { + JS_FreeValue(ctx, ret); + return JS_EXCEPTION; + } + return ret; } int host_object_has(JSContext *ctx, JSValue obj, JSAtom atom) { napi_env env = (napi_env) JS_GetContextOpaque(ctx); - NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque(obj, - env->runtime->napiHostObjectClassId); - if (info != NULL) { - return JS_HasProperty(ctx, info->ref->value, atom); - } - return false; + NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque( + obj, env->runtime->napiHostObjectClassId); + if (info == NULL || info->methods.has == NULL) return false; + + HO_SCOPE_OPEN + napi_value host, prop; + CreateScopedResult(env, JS_DupValue(ctx, obj), &host); + CreateScopedResult(env, JS_AtomToValue(ctx, atom), &prop); + bool present = info->methods.has(env, host, prop, info->data); + HO_SCOPE_CLOSE; + + if (JS_HasException(ctx)) return -1; + return present; } static int host_object_delete(JSContext *ctx, JSValue obj, JSAtom atom) { napi_env env = (napi_env) JS_GetContextOpaque(ctx); - NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque(obj, - env->runtime->napiHostObjectClassId); - if (info != NULL) { - return JS_DeleteProperty(ctx, info->ref->value, atom, 0); - } - return true; -} + NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque( + obj, env->runtime->napiHostObjectClassId); + if (info == NULL || info->methods.delete_property == NULL) return true; -static int host_object_get_own_property_names(JSContext *ctx, JSPropertyEnum **ptab, - uint32_t *plen, - JSValue obj) { - napi_env env = (napi_env) JS_GetContextOpaque(ctx); - NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque(obj, - env->runtime->napiHostObjectClassId); - if (info != NULL) { - return JS_GetOwnPropertyNames(ctx, ptab, plen, info->ref->value, - JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK | JS_GPN_ENUM_ONLY); - } - return true; -} + HO_SCOPE_OPEN + napi_value host, prop; + CreateScopedResult(env, JS_DupValue(ctx, obj), &host); + CreateScopedResult(env, JS_AtomToValue(ctx, atom), &prop); + bool deleted = info->methods.delete_property(env, host, prop, info->data); + HO_SCOPE_CLOSE; -static int host_object_get_own_property(JSContext *ctx, JSPropertyDescriptor *desc, - JSValue obj, JSAtom prop) { - napi_env env = (napi_env) JS_GetContextOpaque(ctx); - NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque(obj, - env->runtime->napiHostObjectClassId); - if (info != NULL) { - return JS_GetOwnProperty(ctx, desc, info->ref->value, prop); - } - return true; + if (JS_HasException(ctx)) return -1; + return deleted; } -static int host_object_define_own_property(JSContext *ctx, JSValue obj, - JSAtom prop, JSValue val, - JSValue getter, JSValue setter, - int flags) { - napi_env env = (napi_env) JS_GetContextOpaque(ctx); - NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque(obj, - env->runtime->napiHostObjectClassId); - if (info != NULL) { - return JS_DefineProperty(ctx, info->ref->value, prop, JS_DupValue(ctx, val), getter, setter, - flags); - } - return true; -} +#undef HO_SCOPE_OPEN +#undef HO_SCOPE_CLOSE JSClassExoticMethods NapiHostObjectExoticMethods = { .set_property = host_object_set, .get_property = host_object_get, .has_property = host_object_has, .delete_property = host_object_delete, -// .get_own_property_names = host_object_get_own_property_names, -// .get_own_property = host_object_get_own_property, -// .define_own_property = host_object_define_own_property }; - napi_status -napi_create_host_object(napi_env env, napi_value value, napi_finalize finalize, void *data, - bool is_array, napi_value getter, napi_value setter, napi_value *result) { +napi_create_host_object(napi_env env, napi_finalize finalize, void *data, + const napi_host_object_methods *methods, + napi_value *result) { CHECK_ARG(env); + CHECK_ARG(methods); CHECK_ARG(result); + RETURN_STATUS_IF_FALSE(methods->get != NULL && methods->set != NULL, + napi_invalid_arg); - napi_value constructor; - napi_get_named_property(env, value, "constructor", &constructor); - - napi_value prototype; - napi_get_named_property(env, constructor, "prototype", &prototype); + JSValue jsValue = JS_NewObjectClass(env->context, + env->runtime->napiHostObjectClassId); - JSValue jsValue = JS_NewObjectClass(env->context, env->runtime->napiHostObjectClassId); - JS_SetPrototype(env->context, jsValue, *((JSValue *) prototype)); - - NapiHostObjectInfo *info = (NapiHostObjectInfo *) mi_malloc(sizeof(NapiHostObjectInfo)); + NapiHostObjectInfo *info = + (NapiHostObjectInfo *) mi_malloc(sizeof(NapiHostObjectInfo)); info->data = data; - if (finalize) { - info->finalize_cb = finalize; - } else { - info->finalize_cb = NULL; - } - info->is_array = is_array; - - if (is_array) { - if (getter) napi_create_reference(env, getter, 1, &info->getter); - if (setter) napi_create_reference(env, setter, 1, &info->setter); - } - - napi_create_reference(env, value, 1, &info->ref); + info->finalize_cb = finalize; + info->methods = *methods; JS_SetOpaque(jsValue, info); return CreateScopedResult(env, jsValue, result); @@ -4013,13 +4011,12 @@ napi_status napi_get_host_object_data(napi_env env, napi_value object, void **da JSValue jsValue = *((JSValue *) object); - if (!JS_IsObject(jsValue)) { return napi_set_last_error(env, napi_object_expected, NULL, 0, NULL); } - NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque(jsValue, - env->runtime->napiHostObjectClassId); + NapiHostObjectInfo *info = (NapiHostObjectInfo *) JS_GetOpaque( + jsValue, env->runtime->napiHostObjectClassId); if (info) { *data = info->data; } else { @@ -4039,17 +4036,14 @@ napi_status napi_is_host_object(napi_env env, napi_value object, bool *result) { return napi_set_last_error(env, napi_object_expected, NULL, 0, NULL); } - void *data = JS_GetOpaque(jsValue, - env->runtime->napiHostObjectClassId); - if (data != NULL) { - *result = true; - } else { - *result = false; - } + void *data = JS_GetOpaque(jsValue, env->runtime->napiHostObjectClassId); + *result = data != NULL; return napi_clear_last_error(env); } +#endif // USE_HOST_OBJECT + /** * -------------------------------- * JS RUNTIME @@ -4086,8 +4080,10 @@ napi_status qjs_create_runtime(napi_runtime *runtime) { JSClassDef ExternalClassDef = {"ExternalInfo", external_finalizer, NULL, NULL, NULL}; JSClassDef FunctionClassDef = {"FunctionInfo", function_finalizer, NULL, NULL, NULL}; JSClassDef ConstructorClassDef = {"ConstructorInfo", function_finalizer, NULL, NULL, NULL}; +#ifdef USE_HOST_OBJECT JSClassDef NapiHostObjectClassDef = {"NapiHostObject", host_object_finalizer, NULL, NULL, &NapiHostObjectExoticMethods}; +#endif #ifndef __QJS_NG__ JS_NewClassID( &(*runtime)->napiHostObjectClassId); JS_NewClassID( &(*runtime)->constructorClassId); @@ -4100,7 +4096,9 @@ napi_status qjs_create_runtime(napi_runtime *runtime) { JS_NewClassID((*runtime)->runtime, &(*runtime)->externalClassId); #endif +#ifdef USE_HOST_OBJECT JS_NewClass((*runtime)->runtime, (*runtime)->napiHostObjectClassId, &NapiHostObjectClassDef); +#endif JS_NewClass((*runtime)->runtime, (*runtime)->externalClassId, &ExternalClassDef); JS_NewClass((*runtime)->runtime, (*runtime)->functionClassId, &FunctionClassDef); JS_NewClass((*runtime)->runtime, (*runtime)->constructorClassId, &ConstructorClassDef); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/quicks-runtime.h b/test-app/runtime/src/main/cpp/napi/quickjs/quicks-runtime.h index e1d969ca..1ab2501b 100644 --- a/test-app/runtime/src/main/cpp/napi/quickjs/quicks-runtime.h +++ b/test-app/runtime/src/main/cpp/napi/quickjs/quicks-runtime.h @@ -8,6 +8,12 @@ EXTERN_C_START +// QuickJS' own runtime handle. This is the engine-internal runtime (defined in +// quickjs-api.c as napi_runtime__ holding the JSRuntime and class IDs) and is +// distinct from the engine-agnostic jsr_ns_runtime used by the jsr layer. The +// jsr adapter (jsr.cpp) wraps this in a jsr_ns_runtime__. +typedef struct napi_runtime__ *napi_runtime; + NAPI_EXTERN napi_status NAPI_CDECL qjs_create_runtime(napi_runtime *runtime); NAPI_EXTERN napi_status NAPI_CDECL qjs_create_napi_env(napi_env *env, napi_runtime runtime); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source/quickjs.c b/test-app/runtime/src/main/cpp/napi/quickjs/source/quickjs.c index a3b74e08..d8822e63 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source/quickjs.c +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source/quickjs.c @@ -7802,6 +7802,13 @@ static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop, return 0; } +#ifdef USE_HOST_OBJECT +/* NativeScript host-object exotic methods (defined in quickjs-api.c). Compared + by address below so the get_property handler can be treated as a non-masking + fallback for host objects only, leaving Proxy (js_proxy_get) authoritative. */ +extern JSClassExoticMethods NapiHostObjectExoticMethods; +#endif + JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, JSAtom prop, JSValueConst this_obj, BOOL throw_ref_error) @@ -7810,6 +7817,11 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, JSProperty *pr; JSShapeProperty *prs; uint32_t tag; +#ifdef USE_HOST_OBJECT + /* A host object whose get_property we deferred: the prototype chain is + consulted first, and this is called only if nothing was found. */ + JSObject *deferred_host = NULL; +#endif tag = JS_VALUE_GET_TAG(obj); if (unlikely(tag != JS_TAG_OBJECT)) { @@ -7914,14 +7926,27 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; if (em) { if (em->get_property) { - JSValue obj1, retval; - /* XXX: should pass throw_ref_error */ - /* Note: if 'p' is a prototype, it can be - freed in the called function */ - obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); - retval = em->get_property(ctx, obj1, prop, this_obj); - JS_FreeValue(ctx, obj1); - return retval; +#ifdef USE_HOST_OBJECT + /* NativeScript host objects use get_property as a + NON-masking fallback: defer it so the prototype chain + (native methods / field accessors) is consulted first, + and call it only if nothing is found (see after loop). + Proxy and other exotics stay authoritative. */ + if (em == &NapiHostObjectExoticMethods) { + if (!deferred_host) + deferred_host = p; + } else +#endif + { + JSValue obj1, retval; + /* XXX: should pass throw_ref_error */ + /* Note: if 'p' is a prototype, it can be + freed in the called function */ + obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); + retval = em->get_property(ctx, obj1, prop, this_obj); + JS_FreeValue(ctx, obj1); + return retval; + } } if (em->get_own_property) { JSPropertyDescriptor desc; @@ -7951,6 +7976,17 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, if (!p) break; } +#ifdef USE_HOST_OBJECT + /* Nothing found on the prototype chain: now consult the deferred host + object's get_property (expandos, numeric indices, dynamic members). */ + if (deferred_host) { + JSValue obj1, retval; + obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, deferred_host)); + retval = NapiHostObjectExoticMethods.get_property(ctx, obj1, prop, this_obj); + JS_FreeValue(ctx, obj1); + return retval; + } +#endif if (unlikely(throw_ref_error)) { return JS_ThrowReferenceErrorNotDefined(ctx, prop); } else { diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.gitattributes b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.gitattributes new file mode 100755 index 00000000..0fb79755 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.gitattributes @@ -0,0 +1,4 @@ +# Don't show changes in generated files when doing git diff + +gen/** -diff +builtin-*.h -diff diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/dependabot.yml b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/dependabot.yml new file mode 100755 index 00000000..700707ce --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/dependabot.yml @@ -0,0 +1,7 @@ +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/ci.yml b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/ci.yml new file mode 100755 index 00000000..b96d6e23 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/ci.yml @@ -0,0 +1,865 @@ +name: ci + +on: + pull_request: + paths: + - '**' + - '!.gitignore' + - '!LICENSE' + - '!README.md' + - '!docs/**' + - '!examples/**' + - '.github/workflows/ci.yml' + push: + branches: + - master + paths: + - '**' + - '!.gitignore' + - '!LICENSE' + - '!README.md' + - '!docs/**' + - '!examples/**' + - '.github/workflows/ci.yml' + +jobs: + codegen: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: build + run: | + make codegen + - name: Check if the git repository is clean + run: (exit "$(git status --porcelain --untracked-files=no | head -255 | wc -l)") || (echo "Dirty git tree"; git diff; exit 1) + + ci: + runs-on: ${{ matrix.config.os }} + name: ${{ matrix.config.os }} (${{ matrix.config.configType }}${{ matrix.config.arch }}) + env: + ASAN_OPTIONS: halt_on_error=1 + MSAN_OPTIONS: halt_on_error=1 + UBSAN_OPTIONS: halt_on_error=1 + defaults: + run: + shell: ${{ matrix.config.arch == '' && 'sh' || 'alpine.sh' }} {0} + + strategy: + fail-fast: false + matrix: + config: + # see https://github.com/quickjs-ng/quickjs/issues/879 - tl;dr flaky + #- { os: ubuntu-24.04-arm, configType: Debug } + #- { os: ubuntu-24.04-arm, configType: Release, runTest262: true } + - { os: ubuntu-latest, configType: Debug } + - { os: ubuntu-latest, configType: Release, runTest262: true } + - { os: ubuntu-latest, configType: examples } + - { os: ubuntu-latest, configType: shared } + - { os: ubuntu-latest, configType: asan+ubsan, runTest262: true } + - { os: ubuntu-latest, configType: msan } + - { os: ubuntu-latest, configType: tcc } + - { os: ubuntu-latest, arch: x86, runTest262: true } + - { os: ubuntu-latest, arch: riscv64 } + + - { os: macos-14, configType: Debug } + - { os: macos-14, configType: Release } + - { os: macos-14, configType: examples } + - { os: macos-14, configType: shared } + - { os: macos-14, configType: asan+ubsan, runTest262: true } + steps: + - uses: actions/checkout@v6 + with: + submodules: true + + - name: install TCC + if: ${{ matrix.config.configType == 'tcc' }} + run: | + pushd /tmp + git clone https://repo.or.cz/tinycc.git + cd tinycc + git checkout c21576f8a32715ab439690d18184b0e02022bbbd + ./configure + make + sudo make install + tcc -v + popd + echo "CC=tcc" >> $GITHUB_ENV; + + - name: Install extra dependencies + if: ${{ matrix.config.arch != '' }} + shell: 'sh' + run: | + sudo apt update && sudo apt install -y binfmt-support + + - name: Setup Alpine + if: ${{ matrix.config.arch != '' }} + uses: jirutka/setup-alpine@v1 + with: + arch: ${{ matrix.config.arch }} + packages: "build-base make cmake git" + + - name: uname + run: uname -a + + - name: Set build ENV vars + run: | + if [ "${{ matrix.config.configType }}" = "Debug" ]; then + echo "BUILD_TYPE=Debug" >> $GITHUB_ENV; + elif [ "${{ matrix.config.configType }}" = "examples" ]; then + echo "QJS_BUILD_EXAMPLES=ON" >> $GITHUB_ENV; + elif [ "${{ matrix.config.configType }}" = "shared" ]; then + echo "BUILD_SHARED_LIBS=ON" >> $GITHUB_ENV; + elif [ "${{ matrix.config.configType }}" = "asan+ubsan" ]; then + echo "BUILD_TYPE=RelWithDebInfo" >> $GITHUB_ENV; + echo "QJS_ENABLE_ASAN=ON" >> $GITHUB_ENV; + echo "QJS_ENABLE_UBSAN=ON" >> $GITHUB_ENV; + elif [ "${{ matrix.config.configType }}" = "msan" ]; then + echo "BUILD_TYPE=RelWithDebInfo" >> $GITHUB_ENV; + echo "QJS_ENABLE_MSAN=ON" >> $GITHUB_ENV; + echo "CC=clang" >> $GITHUB_ENV; + fi + + - name: build + run: | + make \ + BUILD_TYPE=$BUILD_TYPE \ + QJS_BUILD_EXAMPLES=$QJS_BUILD_EXAMPLES \ + BUILD_SHARED_LIBS=$BUILD_SHARED_LIBS \ + QJS_ENABLE_ASAN=$QJS_ENABLE_ASAN \ + QJS_ENABLE_UBSAN=$QJS_ENABLE_UBSAN \ + QJS_ENABLE_MSAN=$QJS_ENABLE_MSAN + + - name: stats + if: ${{ matrix.config.configType != 'examples' }} + run: | + make stats + + - name: cxxtest + run: | + make cxxtest + + - name: test + if: ${{ matrix.config.configType != 'examples' }} + run: | + make test + + - name: test examples + if: ${{ matrix.config.configType == 'examples' }} + run: | + cp build/fib.so examples/ + cp build/point.so examples/ + ./build/qjs examples/test_fib.js + ./build/qjs examples/test_point.js + ./build/qjs tests/test_bjson.js + ./build/function_source + + - name: test 262 + if: ${{ matrix.config.runTest262 }} + run: | + git submodule update --init --checkout --depth 1 + make test262 + + - name: test standalone + run: | + ./build/qjs -c examples/hello.js -o hello + ./hello + + - name: test api + run: | + ./build/api-test + + - name: test lre + run: | + ./build/lre-test + + windows-msvc: + runs-on: ${{ matrix.config.os }} + strategy: + fail-fast: false + matrix: + config: + - { arch: x64, vsArch: x64, buildType: Debug, os: windows-latest, msvc: 18 } + - { arch: x64, vsArch: x64, buildType: Release, os: windows-latest, msvc: 18 } + - { arch: Win32, vsArch: x86, buildType: Debug, os: windows-latest, msvc: 18 } + - { arch: Win32, vsArch: x86, buildType: Release, os: windows-latest, msvc: 18 } + - { arch: ARM64, vsArch: arm64, buildType: Debug, os: windows-11-arm, msvc: 17 } + - { arch: ARM64, vsArch: arm64, buildType: Release, os: windows-11-arm, msvc: 17 } + steps: + - uses: actions/checkout@v6 + - name: build + run: | + cmake -B build -DQJS_BUILD_WERROR=ON -DQJS_BUILD_EXAMPLES=ON -G "Visual Studio ${{matrix.config.msvc}}" -A ${{matrix.config.arch}} + cmake --build build --config ${{matrix.config.buildType}} + - name: stats + run: | + build\${{matrix.config.buildType}}\qjs.exe -qd + - name: test + run: | + cp build\${{matrix.config.buildType}}\fib.dll examples\ + cp build\${{matrix.config.buildType}}\point.dll examples\ + build\${{matrix.config.buildType}}\qjs.exe examples\test_fib.js + build\${{matrix.config.buildType}}\qjs.exe examples\test_point.js + build\${{matrix.config.buildType}}\run-test262.exe -c tests.conf + build\${{matrix.config.buildType}}\function_source.exe + - name: test standalone + run: | + build\${{matrix.config.buildType}}\qjs.exe -c examples\hello.js -o hello.exe + .\hello.exe + - name: test api + run: | + build\${{matrix.config.buildType}}\api-test.exe + - name: test lre + run: | + build\${{matrix.config.buildType}}\lre-test.exe + - name: Set up Visual Studio shell + uses: egor-tensin/vs-shell@v2 + with: + arch: ${{ matrix.config.vsArch }} + - name: cxxtest + run: | + cl.exe /DJS_NAN_BOXING=0 /Zs cxxtest.cc + cl.exe /DJS_NAN_BOXING=1 /Zs cxxtest.cc + + windows-clang: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + buildType: [Debug, Release] + steps: + - uses: actions/checkout@v6 + - name: install ninja + run: | + choco install ninja + ninja.exe --version + - name: build + run: | + git submodule update --init --checkout --depth 1 + cmake -B build -DQJS_BUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=${{matrix.buildType}} -DCMAKE_C_COMPILER=clang.exe -G "Ninja" + cmake --build build --config ${{matrix.buildType}} + - name: stats + run: | + build\qjs.exe -qd + - name: cxxtest + run: | + clang.exe -D JS_NAN_BOXING=0 -fsyntax-only cxxtest.cc + clang.exe -D JS_NAN_BOXING=1 -fsyntax-only cxxtest.cc + - name: test + run: | + cp build\fib.dll examples\ + cp build\point.dll examples\ + build\qjs.exe examples\test_fib.js + build\qjs.exe examples\test_point.js + build\run-test262.exe -c tests.conf + build\function_source.exe + + windows-clang-cl: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + buildType: [Debug, Release] + steps: + - uses: actions/checkout@v6 + - name: build + run: | + git submodule update --init --checkout --depth 1 + cmake -B build -DQJS_BUILD_WERROR=ON -DQJS_BUILD_EXAMPLES=ON -G "Visual Studio 18" -T ClangCL + cmake --build build --config ${{matrix.buildType}} + - name: stats + run: | + build\${{matrix.buildType}}\qjs.exe -qd + - name: cxxtest + run: | + clang-cl.exe /DJS_NAN_BOXING=0 /Zs cxxtest.cc + clang-cl.exe /DJS_NAN_BOXING=1 /Zs cxxtest.cc + - name: test + run: | + cp build\${{matrix.buildType}}\fib.dll examples\ + cp build\${{matrix.buildType}}\point.dll examples\ + build\${{matrix.buildType}}\qjs.exe examples\test_fib.js + build\${{matrix.buildType}}\qjs.exe examples\test_point.js + build\${{matrix.buildType}}\run-test262.exe -c tests.conf + build\${{matrix.buildType}}\function_source.exe + - name: test api + run: | + build\${{matrix.buildType}}\api-test.exe + - name: test lre + run: | + build\${{matrix.buildType}}\lre-test.exe + + windows-ninja: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + buildType: [Debug, Release] + steps: + - uses: actions/checkout@v6 + - name: install ninja + run: | + choco install ninja + ninja.exe --version + - name: build + run: | + git submodule update --init --checkout --depth 1 + cmake -B build -DQJS_BUILD_WERROR=ON -DQJS_BUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=${{matrix.buildType}} -G "Ninja" + cmake --build build + - name: stats + run: | + build\qjs.exe -qd + - name: test + run: | + cp build\fib.dll examples\ + cp build\point.dll examples\ + build\qjs.exe examples\test_fib.js + build\qjs.exe examples\test_point.js + build\run-test262.exe -c tests.conf + build\function_source.exe + - name: test api + run: | + build\api-test.exe + - name: test lre + run: | + build\lre-test.exe + + windows-sdk: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + arch: [x64, Win32] + buildType: [Debug, Release] + steps: + - uses: actions/checkout@v6 + - name: Install windows sdk + uses: ChristopheLav/windows-sdk-install@v1 + with: + version-sdk: 26100 + features: 'OptionId.DesktopCPPx86,OptionId.DesktopCPPx64' + - name: build + run: | + cmake -B build -DQJS_BUILD_WERROR=ON -DQJS_BUILD_EXAMPLES=ON -DCMAKE_SYSTEM_VERSION="10.0.26100.0" -A ${{matrix.arch}} + cmake --build build --config ${{matrix.buildType}} + - name: stats + run: | + build\${{matrix.buildType}}\qjs.exe -qd + - name: test + run: | + cp build\${{matrix.buildType}}\fib.dll examples\ + cp build\${{matrix.buildType}}\point.dll examples\ + build\${{matrix.buildType}}\qjs.exe examples\test_fib.js + build\${{matrix.buildType}}\qjs.exe examples\test_point.js + build\${{matrix.buildType}}\run-test262.exe -c tests.conf + build\${{matrix.buildType}}\function_source.exe + - name: test api + run: | + build\${{matrix.buildType}}\api-test.exe + - name: test lre + run: | + build\${{matrix.buildType}}\lre-test.exe + + windows-mingw: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + buildType: [Debug, Release] + sys: + - mingw32 + - mingw64 + - clang64 + - ucrt64 + defaults: + run: + shell: msys2 {0} + steps: + - uses: actions/checkout@v6 + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + update: true + msystem: ${{matrix.sys}} + install: >- + git + make + pacboy: >- + cmake:p + ninja:p + toolchain:p + - name: build + run: | + make BUILD_TYPE=${{matrix.buildType}} + - name: stats + run: | + make stats + ldd build/qjs + - name: cxxtest + if: ${{ matrix.sys != 'clang64' }} + run: | + make cxxtest + - name: cxxtest + if: ${{ matrix.sys == 'clang64' }} + run: | + make cxxtest CXX=clang++ + - name: test + run: | + make test + - name: test standalone + run: | + ./build/qjs -c examples/hello.js -o hello.exe + ./hello + - name: test api + run: | + ./build/api-test + - name: test lre + run: | + ./build/lre-test + windows-mingw-shared: + runs-on: windows-latest + defaults: + run: + shell: msys2 {0} + steps: + - uses: actions/checkout@v6 + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + install: >- + git + make + pacboy: >- + cmake:p + ninja:p + toolchain:p + - name: build + run: | + make BUILD_SHARED_LIBS=ON + ldd build/qjs + - name: stats + run: | + make stats + + emscripten: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: mymindstorm/setup-emsdk@v16 + - name: check emsdk + run: emcc -v + - name: build + run: | + emcmake cmake -B build -DQJS_BUILD_WERROR=ON -DQJS_BUILD_LIBC=ON + emmake make -C build qjs_wasm "-j$(getconf _NPROCESSORS_ONLN)" + - name: result + run: ls -lh build + wasi: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v6 + - uses: jcbhmr/setup-wasmtime@v2 + - name: setup wasi-sdk + run: | + wget -nv https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-29/wasi-sdk-29.0-x86_64-linux.deb -P /tmp + sudo apt install /tmp/wasi-sdk*.deb + - name: test + run: | + cmake -B build -DQJS_BUILD_WERROR=ON -DCMAKE_TOOLCHAIN_FILE=/opt/wasi-sdk/share/cmake/wasi-sdk.cmake + make -C build qjs_exe + wasmtime run build/qjs -qd + echo "console.log('hello wasi!');" > t.js + wasmtime run --dir . build/qjs t.js + - name: build wasi reactor + run: | + cmake -B build -DQJS_BUILD_WERROR=ON -DCMAKE_TOOLCHAIN_FILE=/opt/wasi-sdk/share/cmake/wasi-sdk.cmake -DQJS_WASI_REACTOR=ON + make -C build qjs_wasi + ls -lh build/qjs.wasm + + cygwin: + runs-on: windows-latest + defaults: + run: + shell: C:\cygwin\bin\bash.exe --login --norc -eo pipefail -o igncr '{0}' + env: + CYGWIN_NOWINPATH: 1 + CHERE_INVOKING: 1 + steps: + - name: Set up Cygwin + uses: cygwin/cygwin-install-action@master + with: + packages: make cmake gcc-g++ bash + + - uses: actions/checkout@v6 + + - name: build + run: make + + - name: stats + run: make stats + + - name: cxxtest + run: | + make cxxtest + + - name: test + run: make test + + - name: test api + run: | + ./build/api-test + + - name: test lre + run: | + ./build/lre-test + + openbsd: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: build + test + uses: vmactions/openbsd-vm@v1 + with: + usesh: true + prepare: | + pkg_add cmake gmake + run: | + gmake + gmake stats + + freebsd: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: build + test + uses: vmactions/freebsd-vm@v1 + with: + usesh: true + prepare: | + pkg install -y cmake gmake + run: | + gmake + gmake stats + + android: + runs-on: ubuntu-latest + container: reactnativecommunity/react-native-android:v13.0 + steps: + - uses: actions/checkout@v6 + - name: Configure android arm64 + # see build options you can use in https://developer.android.com/ndk/guides/cmake + run: | + mkdir build + cd build + "$ANDROID_HOME/cmake/3.22.1/bin/cmake" "-DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/ndk/26.0.10792818/build/cmake/android.toolchain.cmake" -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="arm64-v8a" -DANDROID_PLATFORM=android-24 -DQJS_BUILD_LIBC=ON .. + - name: Build android arm64 + run: | + "$ANDROID_HOME/cmake/3.22.1/bin/cmake" --build build --target qjs + ls -lh build + + ios: + runs-on: macos-latest + steps: + - uses: actions/checkout@v6 + - name: configure + run: | + cmake -B build -GXcode -DQJS_BUILD_WERROR=ON -DCMAKE_SYSTEM_NAME:STRING=iOS -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED:BOOL=NO -DQJS_BUILD_LIBC=ON + - name: build + run: | + cmake --build build --config Release --target qjs + ls -lh build + + mimalloc-linux: + runs-on: ubuntu-24.04 + env: + QJS_BUILD_CLI_WITH_MIMALLOC: ON + MIMALLOC_SHOW_STATS: 1 + steps: + - uses: actions/checkout@v6 + - name: install dependencies + run: | + sudo apt update && sudo apt -y install libmimalloc-dev + - name: build + run: | + make + - name: cxxtest + run: | + make cxxtest + - name: test + run: | + make test + + mimalloc-macos: + runs-on: macos-latest + env: + QJS_BUILD_CLI_WITH_STATIC_MIMALLOC: ON + MIMALLOC_SHOW_STATS: 1 + steps: + - uses: actions/checkout@v6 + - name: install dependencies + run: | + brew install mimalloc + - name: build + run: | + make + - name: cxxtest + run: | + make cxxtest + - name: test + run: | + make test + + amalgam: + strategy: + matrix: + # TODO(bnoordhuis) test on windows + config: + - { os: ubuntu-latest } + - { os: macos-latest } + runs-on: ${{ matrix.config.os }} + steps: + - uses: actions/checkout@v6 + - name: build + run: | + make + - name: create amalgamation + run: | + make amalgam + - name: build amalgamation + run: | + unzip -d "$RUNNER_TEMP" build/quickjs-amalgam.zip + cc -Wall -I. -o "$RUNNER_TEMP/run-test262.o" -c run-test262.c + cc -Wall -I/ -DQJS_BUILD_LIBC -o "$RUNNER_TEMP/quickjs-amalgam.o" -c "$RUNNER_TEMP/quickjs-amalgam.c" + cc -o "$RUNNER_TEMP/run-test262" "$RUNNER_TEMP/run-test262.o" "$RUNNER_TEMP/quickjs-amalgam.o" -lm + - name: test + run: | + make test RUN262="$RUNNER_TEMP/run-test262" + + jscheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: jscheck + run: | + make jscheck + + parserless: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: build + run: | + make QJS_DISABLE_PARSER=ON QJS_BUILD_EXAMPLES=ON + - name: test + run: | + ./build/hello + ./build/hello_module + + + meson: + runs-on: ${{ matrix.platform }} + name: meson on ${{ matrix.platform }} (${{ matrix.mode.name }} ${{ matrix.flavor }}, ${{ matrix.features.name }}) + strategy: + fail-fast: false + matrix: + flavor: + - debug + - release + features: + - name: default + args: "" + - name: libc + args: -Dlibc=true + - name: mimalloc + args: -Dcli_mimalloc=auto + mode: + - name: default + args: -Dtests=enabled + extra_envs: {} + + # Alternative compiler setups + - name: gcc + args: -Dtests=enabled + extra_envs: + CC: gcc + CXX: g++ + - name: clang + args: -Dtests=enabled + extra_envs: + CC: clang + CXX: clang++ + + - name: sanitize + args: >- + "-Db_sanitize=address,undefined" + extra_envs: {} + + # This is for MSVC, which only supports AddressSanitizer. + # https://learn.microsoft.com/en-us/cpp/sanitizers/ + - name: sanitize+asanonly + args: -Db_sanitize=address + extra_envs: + ASAN_OPTIONS: report_globals=0:halt_on_error=1:abort_on_error=1:print_summary=1 + + - name: clang+sanitize + args: >- + "-Db_sanitize=address,undefined" + "-Db_lundef=false" + extra_envs: + CC: clang + CXX: clang++ + - name: clang+msan + args: >- + "-Db_sanitize=memory" + "-Db_lundef=false" + extra_envs: + CC: clang + CXX: clang++ + + # default clang on GitHub hosted runners is from MSYS2. + # Use Visual Studio supplied clang-cl instead. + # clang-cl's AddressSanitizer does not support the debug CRT (/MDd), + # so force the release CRT (/MD) for both debug and release builds. + - name: clang-cl+sanitize + args: >- + "-Db_sanitize=address,undefined" + "-Db_lundef=false" + "-Db_vscrt=md" + extra_envs: + CC: clang-cl + CXX: clang-cl + # clang-cl's AddressSanitizer reports false positive + # global-buffer-overflows on pooled string literals on Windows, + # same as MSVC; disable global checks (covered on Linux). + ASAN_OPTIONS: report_globals=0:halt_on_error=1:abort_on_error=1:print_summary=1 + platform: + - ubuntu-latest + - windows-latest + - macos-latest + + exclude: + # clang-cl only makes sense on windows. + - platform: ubuntu-latest + mode: + name: clang-cl+sanitize + - platform: macos-latest + mode: + name: clang-cl+sanitize + + # Use clang-cl instead of MSYS2 clang. + # + # we already tested clang+sanitize on linux, + # if this doesn't work, it should be an issue for MSYS2 team to consider. + - platform: windows-latest + mode: + name: clang + - platform: windows-latest + mode: + name: clang+sanitize + - platform: windows-latest + mode: + name: clang+msan + + # MSVC-only sanitizers + - platform: ubuntu-latest + mode: + name: sanitize+asanonly + - platform: macos-latest + mode: + name: sanitize+asanonly + - platform: windows-latest + mode: + name: sanitize + + # clang is the default on macos + # also gcc is an alias to clang + - platform: macos-latest + mode: + name: clang + - platform: macos-latest + mode: + name: gcc + + # gcc is the default on linux + - platform: ubuntu-latest + mode: + name: gcc + + # only run sanitizer tests on linux + # + # gcc/clang's codegen shouldn't massively change across platforms, + # and linux supports most of the sanitizers. + - platform: macos-latest + mode: + name: clang+sanitize + - platform: macos-latest + mode: + # macos does not support msan + name: clang+msan + - platform: macos-latest + mode: + name: sanitize + + steps: + - name: Setup meson + run: | + pipx install meson ninja + - name: Install mimalloc + if: ${{ matrix.platform == 'ubuntu-latest' && matrix.features.name == 'mimalloc' }} + run: sudo apt update && sudo apt -y install libmimalloc-dev + - name: Install mimalloc + if: ${{ matrix.platform == 'macos-latest' && matrix.features.name == 'mimalloc' }} + run: brew install mimalloc + # TODO: Install mimalloc on Windows + # You need to: + # - checkout mimalloc + # - `msbuild mimalloc\ide\vs2022\mimalloc.sln` + # - not cmake, because https://github.com/microsoft/mimalloc/issues/575#issuecomment-1112723975 + # - it is possible to integrate vcpkg with meson, but: + # - 1. the above issue + # - 2. the vcpkg port of mimalloc is outdated, and still broken on server 2019 + # - or maintain a meson port for mimalloc (and ensure it behaves correctly) + # - Make it findable with cmake + # - not the simpler pkg-config. although there was pkg-config in PATH, + # but that was from strawberry perl and thus broken + # ... good job, microsoft :)))) + + - name: Checkout + uses: actions/checkout@v6 + - name: Activate MSVC and Configure + if: ${{ matrix.platform == 'windows-latest' }} + env: ${{ matrix.mode.extra_envs }} + run: | + $extraArgs = @() + if ($env:CC -eq 'clang-cl') { + # Newer clang-cl no longer emits the asan runtime /defaultlib directives + # when -fsanitize is passed through /clang:, and meson links with lld-link + # directly (not the clang driver), so the asan/ubsan runtime is never pulled + # in. Link it explicitly and make its directory discoverable at link and run + # time (the dynamic runtime ships as a DLL). + $runtimeDir = (clang -print-runtime-dir).Trim() + $env:LIB = "$runtimeDir;$env:LIB" + "LIB=$env:LIB" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + $runtimeDir | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8 + $libs = "clang_rt.asan_dynamic-x86_64.lib clang_rt.asan_dynamic_runtime_thunk-x86_64.lib" + $extraArgs = @("-Dc_link_args=$libs", "-Dcpp_link_args=$libs") + } + meson setup build-${{ matrix.flavor }} --buildtype=${{ matrix.flavor }} ${{ matrix.mode.args }} ${{ matrix.features.args }} --vsenv @extraArgs + - name: Configuring + if: ${{ matrix.platform != 'windows-latest' }} + env: ${{ matrix.mode.extra_envs }} + run: | + meson setup build-${{ matrix.flavor }} --buildtype=${{ matrix.flavor }} ${{ matrix.mode.args }} ${{ matrix.features.args }} + - name: Building + run: | + meson compile -C build-${{ matrix.flavor }} + + - name: Running tests + env: ${{ matrix.mode.extra_envs }} + run: | + meson test -C build-${{ matrix.flavor }} --timeout-multiplier 5 --print-errorlogs + meson test --benchmark -C build-${{ matrix.flavor }} --timeout-multiplier 5 --print-errorlogs + - uses: actions/upload-artifact@v7 + if: ${{ failure() }} + with: + name: ${{ matrix.platform }}-${{ matrix.mode.name }}-${{ matrix.features.name }}-${{ matrix.flavor }}-logs + path: build-${{ matrix.flavor }}/meson-logs diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/docs.yml b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/docs.yml new file mode 100755 index 00000000..cc3c2f31 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/docs.yml @@ -0,0 +1,49 @@ +name: Docs + +on: + push: + branches: + - master + paths: + - 'docs/**' + - '.github/workflows/*docs.yml' + +jobs: + build: + name: Build Docusaurus + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: + node-version-file: 'docs/.nvmrc' + - name: Install dependencies + working-directory: ./docs + run: npm install + - name: Build + working-directory: ./docs + run: npm run build + - name: Upload Build Artifact + uses: actions/upload-pages-artifact@v5 + with: + path: docs/build + + deploy: + name: Deploy to GitHub Pages + needs: build + + # Grant GITHUB_TOKEN the permissions required to make a Pages deployment + permissions: + pages: write # to deploy to Pages + id-token: write # to verify the deployment originates from an appropriate source + + # Deploy to the github-pages environment + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + runs-on: ubuntu-latest + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v5 diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/release.yml b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/release.yml new file mode 100755 index 00000000..00c7f95b --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/release.yml @@ -0,0 +1,162 @@ +name: release + +on: + pull_request: + push: + tags: + - "v*.*.*" + +jobs: + check_meson_version: + runs-on: ubuntu-22.04 + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + steps: + - uses: actions/checkout@v6 + - name: install meson and ninja + run: | + pip install --upgrade meson ninja + - name: check meson version + run: | + MESON_VERSION=$(meson introspect meson.build --projectinfo | jq -r '.version') + test "${{ github.ref_name }}" = "v${MESON_VERSION}" + + linux: + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + arch: [aarch64, armv7, riscv64, x86, x86_64] + steps: + - uses: actions/checkout@v6 + - uses: jirutka/setup-alpine@v1 + with: + arch: ${{matrix.arch}} + packages: "build-base make cmake" + - name: build + shell: alpine.sh {0} + run: | + mkdir build + cd build + cmake -DQJS_BUILD_WERROR=ON -DQJS_BUILD_CLI_STATIC=ON .. + cd .. + cmake --build build --target qjs_exe -j$(getconf _NPROCESSORS_ONLN) + cmake --build build --target qjsc -j$(getconf _NPROCESSORS_ONLN) + mv build/qjs build/qjs-linux-${{matrix.arch}} + mv build/qjsc build/qjsc-linux-${{matrix.arch}} + - name: check + shell: alpine.sh {0} + run: | + file build/*-linux-${{matrix.arch}} + - name: upload + uses: actions/upload-artifact@v7 + with: + name: qjs-linux-${{matrix.arch}} + path: build/*-linux-${{matrix.arch}} + + macos: + runs-on: macos-latest + steps: + - uses: actions/checkout@v6 + - name: build + run: | + mkdir build + cd build + cmake -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DQJS_BUILD_WERROR=ON .. + make -j$(getconf _NPROCESSORS_ONLN) + make -C .. amalgam # writes build/quickjs-amalgam.zip + mv qjs qjs-darwin + mv qjsc qjsc-darwin + - name: check + run: | + lipo -info build/qjs-darwin build/qjsc-darwin + - name: upload amalgamation + uses: actions/upload-artifact@v7 + with: + name: quickjs-amalgam.zip + path: build/quickjs-amalgam.zip + compression-level: 0 # already compressed + - name: upload + uses: actions/upload-artifact@v7 + with: + name: qjs-darwin + path: build/*-darwin + + windows: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + arch: [x86, x86_64] + defaults: + run: + shell: msys2 {0} + steps: + - uses: actions/checkout@v6 + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: ${{ matrix.arch == 'x86' && 'mingw32' || 'ucrt64' }} + install: >- + git + make + pacboy: >- + cmake:p + ninja:p + toolchain:p + - name: build + run: | + make + mv build/qjs.exe build/qjs-windows-${{matrix.arch}}.exe + mv build/qjsc.exe build/qjsc-windows-${{matrix.arch}}.exe + - name: check + run: | + file build/qjs-windows-${{matrix.arch}}.exe + ldd build/qjs-windows-${{matrix.arch}}.exe build/qjsc-windows-${{matrix.arch}}.exe + - name: upload + uses: actions/upload-artifact@v7 + with: + name: qjs-windows-${{matrix.arch}} + path: build/*-windows-${{matrix.arch}}.exe + + wasi: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v6 + - name: setup wasi-sdk + run: | + wget -nv https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-29/wasi-sdk-29.0-x86_64-linux.deb -P /tmp + sudo apt install /tmp/wasi-sdk*.deb + - name: build + run: | + cmake -B build -DCMAKE_TOOLCHAIN_FILE=/opt/wasi-sdk/share/cmake/wasi-sdk.cmake -DQJS_BUILD_WERROR=ON + make -C build qjs_exe + mv build/qjs build/qjs-wasi.wasm + - name: build wasi reactor + run: | + cmake -B build -DCMAKE_TOOLCHAIN_FILE=/opt/wasi-sdk/share/cmake/wasi-sdk.cmake -DQJS_BUILD_WERROR=ON -DQJS_WASI_REACTOR=ON + make -C build qjs_wasi + mv build/qjs.wasm build/qjs-wasi-reactor.wasm + - name: upload + uses: actions/upload-artifact@v7 + with: + name: qjs-wasi + path: | + build/qjs-wasi.wasm + build/qjs-wasi-reactor.wasm + + upload-to-release: + needs: [linux, macos, windows, wasi, check_meson_version] + runs-on: ubuntu-22.04 + steps: + - name: get assets + uses: actions/download-artifact@v8 + with: + path: build + merge-multiple: true + - run: ls -R build + - name: release + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + uses: softprops/action-gh-release@v3 + with: + files: | + build/* diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/test-docs.yml b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/test-docs.yml new file mode 100755 index 00000000..9572d20c --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/test-docs.yml @@ -0,0 +1,23 @@ +name: Test Docs + +on: + pull_request: + paths: + - 'docs/**' + - '.github/workflows/*docs.yml' + +jobs: + test-docs: + name: Test Docusaurus build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: + node-version-file: 'docs/.nvmrc' + - name: Install dependencies + working-directory: ./docs + run: npm install + - name: Build + working-directory: ./docs + run: npm run build diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/tsan.yml b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/tsan.yml new file mode 100755 index 00000000..54125c09 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/tsan.yml @@ -0,0 +1,32 @@ +name: tsan + +on: + push: + branches: + - master + paths: + - '**' + - '!.gitignore' + - '!LICENSE' + - '!README.md' + - '!docs/**' + - '!examples/**' + - '.github/workflows/tsan.yml' + - '.github/workflows/valgrind.yml' + workflow_dispatch: + +jobs: + linux: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + submodules: true + - name: build + run: | + cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo -DQJS_BUILD_WERROR=ON -DQJS_ENABLE_TSAN=ON + cmake --build build -j`nproc` + - name: test + run: | + git submodule update --init --checkout --depth 1 + ./build/run-test262 -m -c test262.conf -c test262-fast.conf -a diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/valgrind.yml b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/valgrind.yml new file mode 100755 index 00000000..c135639e --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.github/workflows/valgrind.yml @@ -0,0 +1,33 @@ +name: valgrind + +on: + push: + branches: + - master + paths: + - '**' + - '!.gitignore' + - '!LICENSE' + - '!README.md' + - '!docs/**' + - '!examples/**' + - '.github/workflows/tsan.yml' + - '.github/workflows/valgrind.yml' + workflow_dispatch: + +jobs: + linux: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + submodules: true + - name: install valgrind + run: sudo apt-get update && sudo apt-get install valgrind + - name: build + run: | + make BUILD_TYPE=RelWithDebInfo + - name: test + run: | + git submodule update --init --checkout --depth 1 + valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --error-exitcode=1 ./build/run-test262 -m -c test262.conf -c test262-fast.conf -a diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.gitignore b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.gitignore new file mode 100755 index 00000000..ff10fcd1 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.gitignore @@ -0,0 +1,14 @@ +*.a +*.orig +*.so +.obj/ +build/ +unicode/ +.idea +cmake-* +.vs +out/ +CMakeUserPresets.json +fuzz +.vscode/ +microbench*.txt diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.gitmodules b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.gitmodules new file mode 100755 index 00000000..91828e05 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/.gitmodules @@ -0,0 +1,5 @@ +[submodule "test262"] + path = test262 + url = https://github.com/tc39/test262 + shallow = true + update = none diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/CMakeLists.txt b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/CMakeLists.txt index f2ada27e..4b4bf8e5 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/CMakeLists.txt +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/CMakeLists.txt @@ -10,6 +10,40 @@ set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS ON) set(CMAKE_C_STANDARD 11) +macro(xoption OPTION_NAME OPTION_TEXT OPTION_DEFAULT) + option(${OPTION_NAME} ${OPTION_TEXT} ${OPTION_DEFAULT}) + if(DEFINED ENV{${OPTION_NAME}}) + # Allow setting the option through an environment variable. + set(${OPTION_NAME} $ENV{${OPTION_NAME}}) + endif() + if(${OPTION_NAME}) + add_definitions(-D${OPTION_NAME}) + endif() + message(STATUS " ${OPTION_NAME}: ${${OPTION_NAME}}") +endmacro() + +# note: QJS_ENABLE_TSAN is currently incompatible with the other sanitizers but we +# don't explicitly check for that because who knows what the future will bring? +# QJS_ENABLE_MSAN only works with clang at the time of writing; also not checked +# for the same reason +xoption(BUILD_SHARED_LIBS "Build a shared library" OFF) +# if we ever require CMake 3.21, we can automatically detect this setting by looking at PROJECT_IS_TOP_LEVEL +# similar to how glslang does +xoption(QJS_ENABLE_INSTALL "Enable quickjs installation" ON) +xoption(QJS_BUILD_WERROR "Build with -Werror" OFF) +xoption(QJS_BUILD_EXAMPLES "Build examples" OFF) +xoption(QJS_BUILD_CLI_STATIC "Build a static qjs executable" OFF) +xoption(QJS_BUILD_CLI_WITH_MIMALLOC "Build the qjs executable with mimalloc" OFF) +xoption(QJS_BUILD_CLI_WITH_STATIC_MIMALLOC "Build the qjs executable with mimalloc (statically linked)" OFF) +xoption(QJS_DISABLE_PARSER "Disable JS source code parser" OFF) +xoption(QJS_ENABLE_ASAN "Enable AddressSanitizer (ASan)" OFF) +xoption(QJS_ENABLE_MSAN "Enable MemorySanitizer (MSan)" OFF) +xoption(QJS_ENABLE_TSAN "Enable ThreadSanitizer (TSan)" OFF) +xoption(QJS_ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer (UBSan)" OFF) + +# Used to properly define JS_LIBC_EXTERN. +add_compile_definitions(QUICKJS_NG_BUILD) + # MINGW doesn't exist in older cmake versions, newer versions don't know # about CMAKE_COMPILER_IS_MINGW, and there is no unique CMAKE_C_COMPILER_ID # for mingw-based compilers... @@ -32,6 +66,12 @@ else() set(WATCHOS FALSE) endif() +if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") + set(SUNOS TRUE) +else() + set(SUNOS FALSE) +endif() + if(NOT CMAKE_BUILD_TYPE) message(STATUS "No build type selected, default to Release") set(CMAKE_BUILD_TYPE "Release") @@ -50,7 +90,9 @@ endmacro() xcheck_add_c_compiler_flag(-Wall) if(NOT MSVC AND NOT IOS AND NOT TVOS AND NOT WATCHOS) - xcheck_add_c_compiler_flag(-Werror) + if(QJS_BUILD_WERROR) + xcheck_add_c_compiler_flag(-Werror) + endif() xcheck_add_c_compiler_flag(-Wextra) endif() xcheck_add_c_compiler_flag(-Wformat=2) @@ -62,7 +104,16 @@ xcheck_add_c_compiler_flag(-Wno-unused-but-set-variable) xcheck_add_c_compiler_flag(-Wno-unused-result) xcheck_add_c_compiler_flag(-Wno-stringop-truncation) xcheck_add_c_compiler_flag(-Wno-array-bounds) +if(NOT SUNOS) xcheck_add_c_compiler_flag(-funsigned-char) +endif() + +# Clang on Windows without MSVC command line fails because the codebase uses +# functions like strcpy over strcpy_s +if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND WIN32 AND NOT MSVC) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) + add_compile_definitions(_CRT_NONSTDC_NO_DEPRECATE) +endif() # ClangCL is command line compatible with MSVC, so 'MSVC' is set. if(MSVC) @@ -101,6 +152,9 @@ endif() if(WIN32) if(MSVC) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8388608") + elseif(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT MINGW) + # Clang frontend (clang.exe) targeting the MSVC ABI (using lld-link) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Xlinker /STACK:8388608") else() set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--stack,8388608") endif() @@ -130,37 +184,10 @@ if(CMAKE_BUILD_TYPE MATCHES "Debug") xcheck_add_c_compiler_flag(-fno-omit-frame-pointer) endif() -macro(xoption OPTION_NAME OPTION_TEXT OPTION_DEFAULT) - option(${OPTION_NAME} ${OPTION_TEXT} ${OPTION_DEFAULT}) - if(DEFINED ENV{${OPTION_NAME}}) - # Allow setting the option through an environment variable. - set(${OPTION_NAME} $ENV{${OPTION_NAME}}) - endif() - if(${OPTION_NAME}) - add_definitions(-D${OPTION_NAME}) - endif() - message(STATUS " ${OPTION_NAME}: ${${OPTION_NAME}}") -endmacro() - -xoption(BUILD_SHARED_LIBS "Build a shared library" OFF) if(BUILD_SHARED_LIBS) message(STATUS "Building a shared library") endif() -# note: QJS_ENABLE_TSAN is currently incompatible with the other sanitizers but we -# don't explicitly check for that because who knows what the future will bring? -# QJS_ENABLE_MSAN only works with clang at the time of writing; also not checked -# for the same reason -xoption(QJS_BUILD_EXAMPLES "Build examples" OFF) -xoption(QJS_BUILD_CLI_STATIC "Build a static qjs executable" OFF) -xoption(QJS_BUILD_CLI_WITH_MIMALLOC "Build the qjs executable with mimalloc" OFF) -xoption(QJS_BUILD_CLI_WITH_STATIC_MIMALLOC "Build the qjs executable with mimalloc (statically linked)" OFF) -xoption(QJS_DISABLE_PARSER "Disable JS source code parser" OFF) -xoption(QJS_ENABLE_ASAN "Enable AddressSanitizer (ASan)" OFF) -xoption(QJS_ENABLE_MSAN "Enable MemorySanitizer (MSan)" OFF) -xoption(QJS_ENABLE_TSAN "Enable ThreadSanitizer (TSan)" OFF) -xoption(QJS_ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer (UBSan)" OFF) - if(QJS_ENABLE_ASAN) message(STATUS "Building with ASan") add_compile_options( @@ -224,7 +251,7 @@ endif() xoption(QJS_BUILD_LIBC "Build standard library modules as part of the library" OFF) macro(add_qjs_libc_if_needed target) if(NOT QJS_BUILD_LIBC) - target_sources(${target} PRIVATE quickjs-libc.c) + target_link_libraries(${target} PRIVATE qjs-libc) endif() endmacro() macro(add_static_if_needed target) @@ -237,7 +264,6 @@ macro(add_static_if_needed target) endmacro() set(qjs_sources - cutils.c dtoa.c libregexp.c libunicode.c @@ -246,6 +272,8 @@ set(qjs_sources if(QJS_BUILD_LIBC) list(APPEND qjs_sources quickjs-libc.c) + # The definition must be added to the entire project. + add_compile_definitions(QJS_BUILD_LIBC) endif() list(APPEND qjs_defines _GNU_SOURCE) if(WIN32) @@ -278,6 +306,38 @@ target_include_directories(qjs PUBLIC ) target_link_libraries(qjs PUBLIC ${qjs_libs}) +# Pass a compiler definition so that Windows gets its declspec's right. +get_target_property(QJS_LIB_TYPE qjs TYPE) +if(QJS_LIB_TYPE STREQUAL "SHARED_LIBRARY") + target_compile_definitions(qjs + PRIVATE BUILDING_QJS_SHARED + PUBLIC USING_QJS_SHARED + ) +endif() + +# An interface library for modules. +add_library(qjs_module_lib INTERFACE) +target_include_directories(qjs_module_lib INTERFACE + $ +) +target_compile_definitions(qjs_module_lib INTERFACE + QUICKJS_NG_MODULE_BUILD + $ +) +if(WIN32) + # Since Windows cannot resolve symbols at load time, we need to + # explicitly link it to qjs. + target_link_libraries(qjs_module_lib INTERFACE + qjs + ) +endif() + +if(NOT QJS_BUILD_LIBC) + add_library(qjs-libc STATIC quickjs-libc.c) + target_compile_definitions(qjs-libc PRIVATE ${qjs_defines}) + target_link_libraries(qjs-libc PRIVATE ${qjs_libs} qjs) +endif() + if(EMSCRIPTEN) add_executable(qjs_wasm ${qjs_sources}) target_link_options(qjs_wasm PRIVATE @@ -293,7 +353,7 @@ if(EMSCRIPTEN) -sEXPORTED_RUNTIME_METHODS=ccall,cwrap ) target_compile_definitions(qjs_wasm PRIVATE ${qjs_defines}) - target_link_libraries(qjs_wasm m) + target_link_libraries(qjs_wasm PRIVATE m) endif() @@ -306,7 +366,7 @@ add_executable(qjsc add_qjs_libc_if_needed(qjsc) add_static_if_needed(qjsc) target_compile_definitions(qjsc PRIVATE ${qjs_defines}) -target_link_libraries(qjsc qjs) +target_link_libraries(qjsc PRIVATE qjs) # QuickJS CLI @@ -321,19 +381,52 @@ add_qjs_libc_if_needed(qjs_exe) add_static_if_needed(qjs_exe) set_target_properties(qjs_exe PROPERTIES OUTPUT_NAME "qjs" + PDB_NAME "qjs_cli" + COMPILE_PDB_NAME "qjs_cli" ) target_compile_definitions(qjs_exe PRIVATE ${qjs_defines}) -target_link_libraries(qjs_exe qjs) -if(NOT WIN32) +target_link_libraries(qjs_exe PRIVATE qjs) +if (NOT WIN32) set_target_properties(qjs_exe PROPERTIES ENABLE_EXPORTS TRUE) endif() + +# WASI Reactor +# + +if(CMAKE_SYSTEM_NAME STREQUAL "WASI") + option(QJS_WASI_REACTOR "Build WASI reactor (exports library functions, no _start)" OFF) + if(QJS_WASI_REACTOR) + add_executable(qjs_wasi + quickjs-libc.c + qjs-wasi-reactor.c + ) + set_target_properties(qjs_wasi PROPERTIES + OUTPUT_NAME "qjs" + SUFFIX ".wasm" + ) + target_compile_definitions(qjs_wasi PRIVATE ${qjs_defines}) + target_link_libraries(qjs_wasi qjs) + target_link_options(qjs_wasi PRIVATE + -mexec-model=reactor + # Export all symbols with default visibility (JS_EXTERN functions) + -Wl,--export-dynamic + # Memory management (libc symbols need explicit export) + -Wl,--export=malloc + -Wl,--export=free + -Wl,--export=realloc + -Wl,--export=calloc + ) + endif() +endif() + if(QJS_BUILD_CLI_WITH_MIMALLOC OR QJS_BUILD_CLI_WITH_STATIC_MIMALLOC) find_package(mimalloc REQUIRED) + target_compile_definitions(qjs_exe PRIVATE QJS_USE_MIMALLOC) # Upstream mimalloc doesn't provide a way to know if both libraries are supported. if(QJS_BUILD_CLI_WITH_STATIC_MIMALLOC) - target_link_libraries(qjs_exe mimalloc-static) + target_link_libraries(qjs_exe PRIVATE mimalloc-static) else() - target_link_libraries(qjs_exe mimalloc) + target_link_libraries(qjs_exe PRIVATE mimalloc) endif() endif() @@ -346,7 +439,7 @@ if(NOT EMSCRIPTEN) ) add_qjs_libc_if_needed(run-test262) target_compile_definitions(run-test262 PRIVATE ${qjs_defines}) - target_link_libraries(run-test262 qjs) + target_link_libraries(run-test262 PRIVATE qjs) endif() # Interrupt test @@ -356,13 +449,19 @@ add_executable(api-test api-test.c ) target_compile_definitions(api-test PRIVATE ${qjs_defines}) -target_link_libraries(api-test qjs) +target_link_libraries(api-test PRIVATE qjs) + +add_executable(lre-test + lre-test.c + libregexp.c + libunicode.c +) +target_compile_definitions(lre-test PRIVATE ${qjs_defines}) # Unicode generator # add_executable(unicode_gen EXCLUDE_FROM_ALL - cutils.c libunicode.c unicode_gen.c ) @@ -374,19 +473,28 @@ add_executable(function_source add_qjs_libc_if_needed(function_source) target_include_directories(function_source PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(function_source PRIVATE ${qjs_defines}) -target_link_libraries(function_source qjs) +target_link_libraries(function_source PRIVATE qjs) # Examples # if(QJS_BUILD_EXAMPLES) + if(WIN32 AND NOT (QJS_LIB_TYPE STREQUAL "SHARED_LIBRARY")) + message(AUTHOR_WARNING + "Binary modules used with static qjs on Windows. There might be\n" + "runtime errors when the module is used due to two copies of qjs\n" + "in memory.\n" + "Please use \"-DBUILD_SHARED_LIBS=true\" if possible." + ) + endif() + add_executable(hello gen/hello.c ) add_qjs_libc_if_needed(hello) target_include_directories(hello PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(hello PRIVATE ${qjs_defines}) - target_link_libraries(hello qjs) + target_link_libraries(hello PRIVATE qjs) add_executable(hello_module gen/hello_module.c @@ -394,68 +502,65 @@ if(QJS_BUILD_EXAMPLES) add_qjs_libc_if_needed(hello_module) target_include_directories(hello_module PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(hello_module PRIVATE ${qjs_defines}) - target_link_libraries(hello_module qjs) + target_link_libraries(hello_module PRIVATE qjs) add_library(fib MODULE examples/fib.c) set_target_properties(fib PROPERTIES PREFIX "" - C_VISIBILITY_PRESET default ) - target_compile_definitions(fib PRIVATE JS_SHARED_LIBRARY) - if(WIN32) - target_link_libraries(fib qjs) - elseif(APPLE) + target_link_libraries(fib PRIVATE qjs_module_lib) + if(APPLE) target_link_options(fib PRIVATE -undefined dynamic_lookup) endif() add_library(point MODULE examples/point.c) set_target_properties(point PROPERTIES PREFIX "" - C_VISIBILITY_PRESET default ) - target_compile_definitions(point PRIVATE JS_SHARED_LIBRARY) - if(WIN32) - target_link_libraries(point qjs) - elseif(APPLE) + target_link_libraries(point PRIVATE qjs_module_lib) + if(APPLE) target_link_options(point PRIVATE -undefined dynamic_lookup) endif() add_executable(test_fib - examples/fib.c gen/test_fib.c ) add_qjs_libc_if_needed(test_fib) target_include_directories(test_fib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(test_fib PRIVATE ${qjs_defines}) - target_link_libraries(test_fib qjs) + target_link_libraries(test_fib PRIVATE qjs) + # Loads fib.so which depends on symbols from libqjs. + set_target_properties(test_fib PROPERTIES ENABLE_EXPORTS TRUE) endif() # Install target # -file(STRINGS quickjs.h quickjs_h REGEX QJS_VERSION) -string(REGEX MATCH "QJS_VERSION_MAJOR ([0-9]*)" _ "${quickjs_h}") -set(QJS_VERSION_MAJOR ${CMAKE_MATCH_1}) -string(REGEX MATCH "QJS_VERSION_MINOR ([0-9]*)" _ "${quickjs_h}") -set(QJS_VERSION_MINOR ${CMAKE_MATCH_1}) -string(REGEX MATCH "QJS_VERSION_PATCH ([0-9]*)" _ "${quickjs_h}") -set(QJS_VERSION_PATCH ${CMAKE_MATCH_1}) -set_target_properties(qjs PROPERTIES - VERSION ${QJS_VERSION_MAJOR}.${QJS_VERSION_MINOR}.${QJS_VERSION_PATCH} - SOVERSION ${QJS_VERSION_MAJOR} -) -install(FILES quickjs.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -if(QJS_BUILD_LIBC) - install(FILES quickjs-libc.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -endif() -if(NOT IOS AND NOT TVOS AND NOT WATCHOS) - install(TARGETS qjs_exe RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - install(TARGETS qjsc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) -endif() -install(TARGETS qjs EXPORT qjsConfig - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -install(EXPORT qjsConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/quickjs) -install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR}) -install(DIRECTORY examples DESTINATION ${CMAKE_INSTALL_DOCDIR}) +if (QJS_ENABLE_INSTALL) + file(STRINGS quickjs.h quickjs_h REGEX QJS_VERSION) + string(REGEX MATCH "QJS_VERSION_MAJOR ([0-9]*)" _ "${quickjs_h}") + set(QJS_VERSION_MAJOR ${CMAKE_MATCH_1}) + string(REGEX MATCH "QJS_VERSION_MINOR ([0-9]*)" _ "${quickjs_h}") + set(QJS_VERSION_MINOR ${CMAKE_MATCH_1}) + string(REGEX MATCH "QJS_VERSION_PATCH ([0-9]*)" _ "${quickjs_h}") + set(QJS_VERSION_PATCH ${CMAKE_MATCH_1}) + set_target_properties(qjs PROPERTIES + VERSION ${QJS_VERSION_MAJOR}.${QJS_VERSION_MINOR}.${QJS_VERSION_PATCH} + SOVERSION ${QJS_VERSION_MAJOR} + ) + install(FILES quickjs.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + if(QJS_BUILD_LIBC) + install(FILES quickjs-libc.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + endif() + if(NOT IOS AND NOT TVOS AND NOT WATCHOS) + install(TARGETS qjs_exe RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + install(TARGETS qjsc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() + install(TARGETS qjs EXPORT qjsConfig + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(EXPORT qjsConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qjs) + install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR}) + install(DIRECTORY examples DESTINATION ${CMAKE_INSTALL_DOCDIR}) +endif() diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/LICENSE b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/LICENSE index 3c78b692..fae65732 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/LICENSE +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/LICENSE @@ -1,9 +1,9 @@ The MIT License (MIT) -Copyright (c) 2017-2024 Fabrice Bellard +Copyright (c) 2017-2026 Fabrice Bellard Copyright (c) 2017-2024 Charlie Gordon -Copyright (c) 2023-2025 Ben Noordhuis -Copyright (c) 2023-2025 Saúl Ibarra Corretgé +Copyright (c) 2023-2026 Ben Noordhuis +Copyright (c) 2023-2026 Saúl Ibarra Corretgé Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/Makefile b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/Makefile index 4ff8ca17..d1131c5c 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/Makefile +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/Makefile @@ -1,10 +1,10 @@ # # QuickJS Javascript Engine # -# Copyright (c) 2017-2024 Fabrice Bellard +# Copyright (c) 2017-2026 Fabrice Bellard # Copyright (c) 2017-2024 Charlie Gordon -# Copyright (c) 2023-2025 Ben Noordhuis -# Copyright (c) 2023-2025 Saúl Ibarra Corretgé +# Copyright (c) 2023-2026 Ben Noordhuis +# Copyright (c) 2023-2026 Saúl Ibarra Corretgé # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -81,6 +81,8 @@ codegen: $(QJSC) $(QJSC) -e -o gen/hello_module.c -m examples/hello_module.js $(QJSC) -e -o gen/test_fib.c -m examples/test_fib.js $(QJSC) -C -ss -o builtin-array-fromasync.h builtin-array-fromasync.js + $(QJSC) -C -ss -o builtin-iterator-zip.h builtin-iterator-zip.js + $(QJSC) -C -ss -o builtin-iterator-zip-keyed.h builtin-iterator-zip-keyed.js debug: BUILD_TYPE=Debug $(MAKE) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/SECURITY.md b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/SECURITY.md new file mode 100755 index 00000000..8d9f8ad1 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/SECURITY.md @@ -0,0 +1,96 @@ +# Security Policy + +## Reporting a Vulnerability + +Please report security vulnerabilities through GitHub's [private vulnerability +reporting](https://github.com/quickjs-ng/quickjs/security/advisories/new) +feature, **only if** your report meets the rules below. Reports that do not +meet these rules should be filed as regular public issues instead. + +## Out of Scope + +**Bytecode hardening is out of scope.** QuickJS bytecode is not designed for +adversarial input. Loading untrusted bytecode (e.g. via `JS_ReadObject` with +`JS_READ_OBJ_BYTECODE`) is equivalent to executing untrusted native code, and +crashes, memory corruption, or sandbox escapes resulting from malformed or +malicious bytecode are not considered security vulnerabilities. Only load +bytecode you produced yourself or obtained from a trusted source. See the +documentation for `JS_READ_OBJ_BYTECODE` and `JS_READ_OBJ_SAB` for details. + +## Rules for Private Reports + +Private reporting exists to protect users from issues an attacker could not +otherwise discover. + +**AI-detected bugs are by definition not secret.** If a publicly available +tool found a bug by reading our public source, anyone else running the same +tool will find the same bug. Filing such reports privately just produces +duplicate work since previous reports of the same issue are not visible. +The right place for these is a public issue, where duplicates are visible and +the fix discussion is shared. + +AI tools are welcome, but use them to add value on top of what the tool +produced. Read the code, confirm the bug, write a patch, write a test. A +"drive-by" forward of a tool's raw output, with no real understanding behind +it, is not a useful report. + +Before submitting a private report, ensure all of the following: + +- **You have manually verified the bug.** You understand the code path, you + have confirmed the issue is real, and you can explain it in your own words + without referring back to a tool's output. Reports that you cannot defend + on your own should not be filed. + +- **You have a working reproducer.** Attach a minimal reproducer (a JS file, + or a short C snippet against the public API) that triggers the bug on a + recent `master` commit. If you cannot produce one, the report should not be + filed privately. + +- **Impact is concrete and verifiable.** State what an attacker can actually + do (e.g. "out-of-bounds read of N bytes from the heap reachable from any + script"), not speculative consequences. Do not enumerate hypothetical + downstream impact. + +- **The report is concise and in plain text.** No multi-page write-ups, no + Markdown decorations, no boilerplate severity tables. Lead with the + affected file and function, the trigger, and the impact. If a triager has + to scroll to find what is broken, the report is too long. + +- **The threat model matches QuickJS.** The bug must be reachable from + untrusted JavaScript source running in an otherwise trusted embedder. Bugs + that require loading untrusted bytecode, passing crafted values through the + C API, or otherwise compromiing the embedder are out of scope (see above). + +- **A proposed fix is welcome, and must be tested.** If you include a patch, + it should compile, pass the existing test suite, and include a regression + test. Untested patches generated by a tool are worse than no patch. + +Reports that do not meet these rules may be closed without detailed response +and asked to be refiled publicly. + +## CVEs + +Not every security-relevant fix in QuickJS requires a CVE. CVE identifiers +exist to help downstream consumers track issues that meaningfully affect +their security posture, they are not a scoreboard, and inflating the count +with marginal or speculative findings makes the catalog less useful for the +people who actually rely on it. + +We **mnight** request a CVE when an issue: + +- Is reachable from untrusted JavaScript running in an otherwise trusted + embedder (matches the threat model in "Rules for Private Reports"), +- Has a concrete, demonstrated high impact (memory corruption, out-of-bounds + access, etc.), and +- Affects a released version that downstream users are likely to be running. + +We will generally **not** request a CVE for: + +- Crashes or assertion failures that require malicious bytecode, crafted C + API input, or other embedder compromise (out of scope, see above). +- Bugs found purely by running a publicly available AI tool against the code, + with no additional analysis. By definition, anyone else can run the same + tool and find the same thing. +- Issues already discoverable from the public commit history or issue + tracker by the time the report arrives. + diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/amalgam.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/amalgam.js index 028d7798..37492395 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/amalgam.js +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/amalgam.js @@ -1,6 +1,5 @@ import {loadFile, writeFile} from "qjs:std" -const cutils_c = loadFile("cutils.c") const cutils_h = loadFile("cutils.h") const dtoa_c = loadFile("dtoa.c") const dtoa_h = loadFile("dtoa.h") @@ -19,6 +18,8 @@ const quickjs_libc_c = loadFile("quickjs-libc.c") const quickjs_libc_h = loadFile("quickjs-libc.h") const quickjs_opcode_h = loadFile("quickjs-opcode.h") const gen_builtin_array_fromasync_h = loadFile("builtin-array-fromasync.h") +const gen_builtin_iterator_zip_h = loadFile("builtin-iterator-zip.h") +const gen_builtin_iterator_zip_keyed_h = loadFile("builtin-iterator-zip-keyed.h") let source = "#if defined(QJS_BUILD_LIBC) && defined(__linux__) && !defined(_GNU_SOURCE)\n" + "#define _GNU_SOURCE\n" @@ -32,7 +33,6 @@ let source = "#if defined(QJS_BUILD_LIBC) && defined(__linux__) && !defined(_GNU + libunicode_table_h + quickjs_h + quickjs_c - + cutils_c + dtoa_c + libregexp_c + libunicode_c @@ -45,5 +45,9 @@ source = source.replace(/#include "quickjs-opcode.h"/g, quickjs_opcode_h) source = source.replace(/#include "libregexp-opcode.h"/g, libregexp_opcode_h) source = source.replace(/#include "builtin-array-fromasync.h"/g, gen_builtin_array_fromasync_h) +source = source.replace(/#include "builtin-iterator-zip.h"/g, + gen_builtin_iterator_zip_h) +source = source.replace(/#include "builtin-iterator-zip-keyed.h"/g, + gen_builtin_iterator_zip_keyed_h) source = source.replace(/#include "[^"]+"/g, "") writeFile(execArgv[2] ?? "quickjs-amalgam.c", source) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/api-test.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/api-test.c index ef28a4f5..a45dfb3a 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/api-test.c +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/api-test.c @@ -7,6 +7,15 @@ #include "quickjs.h" #include "cutils.h" +static JSRuntime *new_runtime(void) +{ + JSRuntime *rt = JS_NewRuntime(); + + if (rt) + JS_SetDumpFlags(rt, JS_ABORT_ON_LEAKS); + return rt; +} + static JSValue eval(JSContext *ctx, const char *code) { return JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_GLOBAL); @@ -25,21 +34,40 @@ static JSValue cfuncdata_callback(JSContext *ctx, JSValueConst this_val, return JS_ThrowTypeError(ctx, "from cfuncdata"); } +static JSValue cclosure_callback(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, + int magic, void *func_data) +{ + return JS_ThrowTypeError(ctx, "from cclosure"); +} + +static bool closure_finalized = false; + +static void cclosure_opaque_finalize(void *opaque) +{ + if ((intptr_t)opaque == 12) + closure_finalized = true; +} + static void cfunctions(void) { uint32_t length; const char *s; JSValue ret, stack; - JSRuntime *rt = JS_NewRuntime(); + JSRuntime *rt = new_runtime(); JSContext *ctx = JS_NewContext(rt); JSValue cfunc = JS_NewCFunction(ctx, cfunc_callback, "cfunc", 42); JSValue cfuncdata = JS_NewCFunctionData2(ctx, cfuncdata_callback, "cfuncdata", /*length*/1337, /*magic*/0, /*data_len*/0, NULL); + JSValue cclosure = + JS_NewCClosure(ctx, cclosure_callback, "cclosure", cclosure_opaque_finalize, + /*length*/0xC0DE, /*magic*/11, /*opaque*/(void*)12); JSValue global = JS_GetGlobalObject(ctx); JS_SetPropertyStr(ctx, global, "cfunc", cfunc); JS_SetPropertyStr(ctx, global, "cfuncdata", cfuncdata); + JS_SetPropertyStr(ctx, global, "cclosure", cclosure); JS_FreeValue(ctx, global); ret = eval(ctx, "cfunc.name"); @@ -70,6 +98,20 @@ static void cfunctions(void) assert(0 == JS_ToUint32(ctx, &length, ret)); assert(length == 1337); + ret = eval(ctx, "cclosure.name"); + assert(!JS_IsException(ret)); + assert(JS_IsString(ret)); + s = JS_ToCString(ctx, ret); + JS_FreeValue(ctx, ret); + assert(s); + assert(!strcmp(s, "cclosure")); + JS_FreeCString(ctx, s); + ret = eval(ctx, "cclosure.length"); + assert(!JS_IsException(ret)); + assert(JS_IsNumber(ret)); + assert(0 == JS_ToUint32(ctx, &length, ret)); + assert(length == 0xC0DE); + ret = eval(ctx, "cfunc()"); assert(JS_IsException(ret)); ret = JS_GetException(ctx); @@ -104,8 +146,27 @@ static void cfunctions(void) assert(!strcmp(s, "TypeError: from cfuncdata")); JS_FreeCString(ctx, s); + ret = eval(ctx, "cclosure()"); + assert(JS_IsException(ret)); + ret = JS_GetException(ctx); + assert(JS_IsError(ret)); + stack = JS_GetPropertyStr(ctx, ret, "stack"); + assert(JS_IsString(stack)); + s = JS_ToCString(ctx, stack); + JS_FreeValue(ctx, stack); + assert(s); + assert(!strcmp(s, " at cclosure (native)\n at (:1:1)\n")); + JS_FreeCString(ctx, s); + s = JS_ToCString(ctx, ret); + JS_FreeValue(ctx, ret); + assert(s); + assert(!strcmp(s, "TypeError: from cclosure")); + JS_FreeCString(ctx, s); + JS_FreeContext(ctx); JS_FreeRuntime(rt); + + assert(closure_finalized); } #define MAX_TIME 10 @@ -127,7 +188,7 @@ static void sync_call(void) } catch (e) {} \ })();"; - JSRuntime *rt = JS_NewRuntime(); + JSRuntime *rt = new_runtime(); JSContext *ctx = JS_NewContext(rt); int time = 0; JS_SetInterruptHandler(rt, timeout_interrupt_handler, &time); @@ -154,7 +215,7 @@ static void async_call(void) await loop().catch(() => {}); \ })();"; - JSRuntime *rt = JS_NewRuntime(); + JSRuntime *rt = new_runtime(); JSContext *ctx = JS_NewContext(rt); int time = 0; JS_SetInterruptHandler(rt, timeout_interrupt_handler, &time); @@ -198,7 +259,7 @@ static void async_call_stack_overflow(void) } \ })();"; - JSRuntime *rt = JS_NewRuntime(); + JSRuntime *rt = new_runtime(); JSContext *ctx = JS_NewContext(rt); JSValue value = JS_UNDEFINED; JS_SetContextOpaque(ctx, &value); @@ -224,7 +285,7 @@ static void async_call_stack_overflow(void) // https://github.com/quickjs-ng/quickjs/issues/914 static void raw_context_global_var(void) { - JSRuntime *rt = JS_NewRuntime(); + JSRuntime *rt = new_runtime(); JSContext *ctx = JS_NewContextRaw(rt); JS_AddIntrinsicEval(ctx); { @@ -248,7 +309,7 @@ static void raw_context_global_var(void) static void is_array(void) { - JSRuntime *rt = JS_NewRuntime(); + JSRuntime *rt = new_runtime(); JSContext *ctx = JS_NewContext(rt); { JSValue ret = eval(ctx, "[]"); @@ -295,7 +356,7 @@ static JSModuleDef *loader(JSContext *ctx, const char *name, void *opaque) static void module_serde(void) { - JSRuntime *rt = JS_NewRuntime(); + JSRuntime *rt = new_runtime(); //JS_SetDumpFlags(rt, JS_DUMP_MODULE_RESOLVE); JS_SetModuleLoaderFunc(rt, NULL, loader, NULL); JSContext *ctx = JS_NewContext(rt); @@ -330,12 +391,50 @@ static void module_serde(void) JS_FreeRuntime(rt); } -static void two_byte_string(void) +static void runtime_cstring_free(void) { - JSRuntime *rt = JS_NewRuntime(); + JSRuntime *rt = new_runtime(); + JSContext *ctx = JS_NewContext(rt); + // string -> cstring + JS_FreeCStringRT + { + JSValue ret = eval(ctx, "\"testStringPleaseIgnore\""); + assert(JS_IsString(ret)); + const char *s = JS_ToCString(ctx, ret); + assert(s); + assert(strcmp(s, "testStringPleaseIgnore") == 0); + JS_FreeCStringRT(rt, s); + JS_FreeValue(ctx, ret); + } + // string -> cstring + JS_FreeCStringRT, destroying the source value first + { + JSValue ret = eval(ctx, "\"testStringPleaseIgnore\""); + assert(JS_IsString(ret)); + const char *s = JS_ToCString(ctx, ret); + assert(s); + JS_FreeValue(ctx, ret); + assert(strcmp(s, "testStringPleaseIgnore") == 0); + JS_FreeCStringRT(rt, s); + } + // number -> cstring + JS_FreeCStringRT + { + JSValue ret = eval(ctx, "123987"); + assert(JS_IsNumber(ret)); + const char *s = JS_ToCString(ctx, ret); + assert(s); + assert(strcmp(s, "123987") == 0); + JS_FreeCStringRT(rt, s); + JS_FreeValue(ctx, ret); + } + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + +static void utf16_string(void) +{ + JSRuntime *rt = new_runtime(); JSContext *ctx = JS_NewContext(rt); { - JSValue v = JS_NewTwoByteString(ctx, NULL, 0); + JSValue v = JS_NewStringUTF16(ctx, NULL, 0); assert(!JS_IsException(v)); const char *s = JS_ToCString(ctx, v); assert(s); @@ -344,24 +443,60 @@ static void two_byte_string(void) JS_FreeValue(ctx, v); } { - JSValue v = JS_NewTwoByteString(ctx, (uint16_t[]){'o','k'}, 2); + JSValue v = JS_NewStringUTF16(ctx, (uint16_t[]){'o','k'}, 2); assert(!JS_IsException(v)); const char *s = JS_ToCString(ctx, v); assert(s); assert(!strcmp(s, "ok")); JS_FreeCString(ctx, s); + size_t n; + const uint16_t *u = JS_ToCStringLenUTF16(ctx, &n, v); + assert(u); + assert(n == 2); + assert(u[0] == 'o'); + assert(u[1] == 'k'); + JS_FreeCStringUTF16(ctx, u); JS_FreeValue(ctx, v); } { - JSValue v = JS_NewTwoByteString(ctx, (uint16_t[]){0xD800}, 1); + JSValue v = JS_NewStringUTF16(ctx, (uint16_t[]){0xD800}, 1); assert(!JS_IsException(v)); const char *s = JS_ToCString(ctx, v); assert(s); // questionable but surrogates don't map to UTF-8 without WTF-8 assert(!strcmp(s, "\xED\xA0\x80")); JS_FreeCString(ctx, s); + size_t n; + const uint16_t *u = JS_ToCStringLenUTF16(ctx, &n, v); + assert(u); + assert(n == 1); + assert(u[0] == 0xD800); + JS_FreeCStringUTF16(ctx, u); JS_FreeValue(ctx, v); } + { + JSValue v = JS_NewStringLen(ctx, "ok", 2); // ascii -> ucs + assert(!JS_IsException(v)); + size_t n; + const uint16_t *u = JS_ToCStringLenUTF16(ctx, &n, v); + assert(u); + assert(n == 2); + assert(u[0] == 'o'); + assert(u[1] == 'k'); + JS_FreeCStringUTF16(ctx, u); + JS_FreeValue(ctx, v); + } + { + JSValue v = JS_NewStringUTF16(ctx, NULL, (size_t)INT_MAX + 1); + assert(JS_IsException(v)); + JSValue e = JS_GetException(ctx); + assert(JS_IsError(e)); + const char *s = JS_ToCString(ctx, e); + assert(s); + assert(strstr(s, "invalid string length") != NULL); + JS_FreeCString(ctx, s); + JS_FreeValue(ctx, e); + } JS_FreeContext(ctx); JS_FreeRuntime(rt); } @@ -378,7 +513,7 @@ function addItem() { \ }"; static const char test_code[] = "addItem()"; - JSRuntime *rt = JS_NewRuntime(); + JSRuntime *rt = new_runtime(); JSContext *ctx = JS_NewContext(rt); JSValue ret = eval(ctx, init_code); @@ -434,7 +569,7 @@ static void promise_hook(void) { int *cc = promise_hook_state.hook_type_call_count; JSContext *unused; - JSRuntime *rt = JS_NewRuntime(); + JSRuntime *rt = new_runtime(); //JS_SetDumpFlags(rt, JS_DUMP_PROMISE); JS_SetPromiseHook(rt, promise_hook_cb, &promise_hook_state); JSContext *ctx = JS_NewContext(rt); @@ -578,7 +713,7 @@ static void dump_memory_usage(void) JSRuntime *rt = NULL; JSContext *ctx = NULL; - rt = JS_NewRuntime(); + rt = new_runtime(); ctx = JS_NewContext(rt); //JS_SetDumpFlags(rt, JS_DUMP_PROMISE); @@ -619,7 +754,7 @@ static void new_errors(void) }; const Entry *e; - JSRuntime *rt = JS_NewRuntime(); + JSRuntime *rt = new_runtime(); JSContext *ctx = JS_NewContext(rt); for (e = entries; e < endof(entries); e++) { JSValue obj = (*e->func)(ctx, "the %s", "needle"); @@ -641,6 +776,37 @@ static void new_errors(void) JS_FreeRuntime(rt); } +static void backtrace_oom_current_exception(void) +{ + static const char setup_code[] = + "globalThis.f = function() { missing; };\n" + "Object.defineProperty(f, 'name', { value: 'x'.repeat(2 * 1024 * 1024) });"; + JSMemoryUsage stats; + JSValue ret, exception; + JSRuntime *rt; + JSContext *ctx; + + rt = new_runtime(); + ctx = JS_NewContext(rt); + + ret = eval(ctx, setup_code); + assert(!JS_IsException(ret)); + JS_FreeValue(ctx, ret); + + JS_ComputeMemoryUsage(rt, &stats); + JS_SetMemoryLimit(rt, (size_t)stats.malloc_size + 128 * 1024); + + ret = eval(ctx, "f()"); + assert(JS_IsException(ret)); + assert(JS_HasException(ctx)); + exception = JS_GetException(ctx); + JS_FreeValue(ctx, exception); + JS_SetMemoryLimit(rt, 0); + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + static int gop_get_own_property(JSContext *ctx, JSPropertyDescriptor *desc, JSValueConst obj, JSAtom prop) { @@ -673,7 +839,7 @@ static void global_object_prototype(void) int res; { - rt = JS_NewRuntime(); + rt = new_runtime(); ctx = JS_NewContext(rt); proto = JS_NewObject(ctx); assert(JS_IsObject(proto)); @@ -702,7 +868,7 @@ static void global_object_prototype(void) .class_name = "Global Object", .exotic = &exotic, }; - rt = JS_NewRuntime(); + rt = new_runtime(); class_id = 0; JS_NewClassID(rt, &class_id); res = JS_NewClass(rt, class_id, &def); @@ -730,7 +896,7 @@ static void global_object_prototype(void) // https://github.com/quickjs-ng/quickjs/issues/1178 static void slice_string_tocstring(void) { - JSRuntime *rt = JS_NewRuntime(); + JSRuntime *rt = new_runtime(); JSContext *ctx = JS_NewContext(rt); JSValue ret = eval(ctx, "'.'.repeat(16384).slice(1, -1)"); assert(!JS_IsException(ret)); @@ -743,6 +909,228 @@ static void slice_string_tocstring(void) JS_FreeRuntime(rt); } +static void immutable_array_buffer(void) +{ + JSValue obj, ret; + bool immutable; + char buf[96]; + int i, v; + + JSRuntime *rt = new_runtime(); + JSContext *ctx = JS_NewContext(rt); + for (i = 0; i < 2; i++) { + obj = JS_NewObject(ctx); + immutable = (i == 0); + assert(-1 == JS_IsImmutableArrayBuffer(JS_NULL)); + assert(-1 == JS_IsImmutableArrayBuffer(JS_UNDEFINED)); + assert(-1 == JS_IsImmutableArrayBuffer(obj)); + assert(-1 == JS_SetImmutableArrayBuffer(JS_NULL, immutable)); + assert(-1 == JS_SetImmutableArrayBuffer(JS_UNDEFINED, immutable)); + assert(-1 == JS_SetImmutableArrayBuffer(obj, immutable)); + JS_FreeValue(ctx, obj); + } + obj = eval(ctx, "globalThis.ab = new ArrayBuffer(1)"); + assert(!JS_IsException(obj)); + assert(JS_IsArrayBuffer(obj)); + assert(!JS_IsImmutableArrayBuffer(obj)); + for (i = 1; i <= 3; i++) { + immutable = (i == 2); + if (i > 1) + JS_SetImmutableArrayBuffer(obj, immutable); + assert(immutable == JS_IsImmutableArrayBuffer(obj)); + snprintf(buf, sizeof(buf), + "var ta = new Uint8Array(ab); ta[0] = %d; ta[0]", i); + ret = eval(ctx, buf); + assert(!JS_IsException(ret)); + assert(JS_IsNumber(ret)); + assert(0 == JS_ToInt32(ctx, &v, ret)); + JS_FreeValue(ctx, ret); + if (immutable) { + assert(v != i); + } else { + assert(v == i); + } + } + JS_FreeValue(ctx, obj); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + +static void *sab_test_alloc(void *opaque, size_t size) +{ + return malloc(size); +} + +static void sab_test_free(void *opaque, void *ptr) +{ + free(ptr); +} + +static void shared_array_buffer_growth(void) +{ + JSRuntime *rt = new_runtime(); + JSContext *ctx = JS_NewContext(rt); + JSValue ret, exception; + + ret = eval(ctx, "new SharedArrayBuffer(16)"); + assert(!JS_IsException(ret)); + JS_FreeValue(ctx, ret); + + ret = eval(ctx, + "const sab = new SharedArrayBuffer(16, { maxByteLength: 16 });" + "sab.grow(16);" + "sab.byteLength === 16 && sab.maxByteLength === 16"); + assert(!JS_IsException(ret)); + assert(JS_IsBool(ret)); + assert(JS_VALUE_GET_BOOL(ret)); + JS_FreeValue(ctx, ret); + + ret = eval(ctx, "new SharedArrayBuffer(16, { maxByteLength: 16384 })"); + assert(JS_IsException(ret)); + assert(JS_HasException(ctx)); + exception = JS_GetException(ctx); + assert(JS_IsError(exception)); + JS_FreeValue(ctx, exception); + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + + JSSharedArrayBufferFunctions funcs = { + .sab_alloc = sab_test_alloc, + .sab_free = sab_test_free, + .sab_dup = NULL, + .sab_opaque = NULL, + }; + + rt = new_runtime(); + JS_SetSharedArrayBufferFunctions(rt, &funcs); + ctx = JS_NewContext(rt); + ret = eval(ctx, + "const sab = new SharedArrayBuffer(16, { maxByteLength: 16384 });" + "const u8 = new Uint8Array(sab);" + "sab.grow(16384);" + "u8[1024] === 0 && u8.byteLength === 16384"); + assert(!JS_IsException(ret)); + assert(JS_IsBool(ret)); + assert(JS_VALUE_GET_BOOL(ret)); + JS_FreeValue(ctx, ret); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + +static void get_uint8array(void) +{ + JSRuntime *rt = new_runtime(); + JSContext *ctx = JS_NewContext(rt); + JSValue val; + uint8_t *p; + size_t size; + uint8_t buf[3] = { 1, 2, 3 }; + + val = eval(ctx, "new Uint8Array(0)"); + assert(!JS_IsException(val)); + p = JS_GetUint8Array(ctx, &size, val); + assert(p != NULL); + assert(size == 0); + JS_FreeValue(ctx, val); + + val = JS_NewUint8Array(ctx, NULL, 0, NULL, NULL, false); + assert(!JS_IsException(val)); + p = JS_GetUint8Array(ctx, &size, val); + assert(p != NULL); + assert(size == 0); + JS_FreeValue(ctx, val); + + val = JS_NewUint8ArrayCopy(ctx, NULL, 0); + assert(!JS_IsException(val)); + p = JS_GetUint8Array(ctx, &size, val); + assert(p != NULL); + assert(size == 0); + JS_FreeValue(ctx, val); + + val = JS_NewUint8ArrayCopy(ctx, buf, sizeof(buf)); + assert(!JS_IsException(val)); + p = JS_GetUint8Array(ctx, &size, val); + assert(p != NULL); + assert(size == 3); + assert(p[0] == 1 && p[1] == 2 && p[2] == 3); + JS_FreeValue(ctx, val); + + val = eval(ctx, "new Uint8Array([4, 5, 6])"); + assert(!JS_IsException(val)); + p = JS_GetUint8Array(ctx, &size, val); + assert(p != NULL); + assert(size == 3); + assert(p[0] == 4 && p[1] == 5 && p[2] == 6); + JS_FreeValue(ctx, val); + + val = eval(ctx, "new Int32Array(4)"); + assert(!JS_IsException(val)); + p = JS_GetUint8Array(ctx, &size, val); + assert(p == NULL); + assert(size == 0); + JS_FreeValue(ctx, val); + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + +static void new_symbol(void) +{ + JSRuntime *rt = new_runtime(); + JSContext *ctx = JS_NewContext(rt); + JSValue global = JS_GetGlobalObject(ctx); + JSValue sym, ret; + + /* Local symbol with NULL description -> Symbol() */ + sym = JS_NewSymbol(ctx, NULL, false); + assert(!JS_IsException(sym)); + assert(JS_IsSymbol(sym)); + JS_SetPropertyStr(ctx, global, "sym_local_null", sym); + + ret = eval(ctx, "typeof sym_local_null === 'symbol' && sym_local_null.description === undefined && Symbol.keyFor(sym_local_null) === undefined"); + assert(JS_IsBool(ret)); + assert(JS_VALUE_GET_BOOL(ret)); + JS_FreeValue(ctx, ret); + + /* Global symbol with NULL description -> Symbol.for() -> Symbol.for('undefined') */ + sym = JS_NewSymbol(ctx, NULL, true); + assert(!JS_IsException(sym)); + assert(JS_IsSymbol(sym)); + JS_SetPropertyStr(ctx, global, "sym_global_null", sym); + + ret = eval(ctx, "typeof sym_global_null === 'symbol' && sym_global_null.description === 'undefined' && Symbol.keyFor(sym_global_null) === 'undefined'"); + assert(JS_IsBool(ret)); + assert(JS_VALUE_GET_BOOL(ret)); + JS_FreeValue(ctx, ret); + + /* Local symbol with description -> Symbol('test_local') */ + sym = JS_NewSymbol(ctx, "test_local", false); + assert(!JS_IsException(sym)); + assert(JS_IsSymbol(sym)); + JS_SetPropertyStr(ctx, global, "sym_local_str", sym); + + ret = eval(ctx, "sym_local_str.description === 'test_local' && Symbol.keyFor(sym_local_str) === undefined"); + assert(JS_IsBool(ret)); + assert(JS_VALUE_GET_BOOL(ret)); + JS_FreeValue(ctx, ret); + + /* Global symbol with description -> Symbol.for('test_global') */ + sym = JS_NewSymbol(ctx, "test_global", true); + assert(!JS_IsException(sym)); + assert(JS_IsSymbol(sym)); + JS_SetPropertyStr(ctx, global, "sym_global_str", sym); + + ret = eval(ctx, "sym_global_str.description === 'test_global' && Symbol.keyFor(sym_global_str) === 'test_global'"); + assert(JS_IsBool(ret)); + assert(JS_VALUE_GET_BOOL(ret)); + JS_FreeValue(ctx, ret); + + JS_FreeValue(ctx, global); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + int main(void) { cfunctions(); @@ -752,12 +1140,18 @@ int main(void) raw_context_global_var(); is_array(); module_serde(); - two_byte_string(); + runtime_cstring_free(); + utf16_string(); weak_map_gc_check(); promise_hook(); dump_memory_usage(); new_errors(); + backtrace_oom_current_exception(); global_object_prototype(); slice_string_tocstring(); + immutable_array_buffer(); + shared_array_buffer_growth(); + get_uint8array(); + new_symbol(); return 0; } diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-array-fromasync.h b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-array-fromasync.h index 19f1f077..4901aaf1 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-array-fromasync.h +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-array-fromasync.h @@ -2,112 +2,118 @@ #include -const uint32_t qjsc_builtin_array_fromasync_size = 826; +const uint32_t qjsc_builtin_array_fromasync_size = 875; -const uint8_t qjsc_builtin_array_fromasync[826] = { - 0x15, 0x0d, 0x01, 0x1a, 0x61, 0x73, 0x79, 0x6e, - 0x63, 0x49, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x01, 0x10, 0x69, 0x74, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x01, 0x12, 0x61, 0x72, 0x72, - 0x61, 0x79, 0x4c, 0x69, 0x6b, 0x65, 0x01, 0x0a, - 0x6d, 0x61, 0x70, 0x46, 0x6e, 0x01, 0x0e, 0x74, - 0x68, 0x69, 0x73, 0x41, 0x72, 0x67, 0x01, 0x0c, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x01, 0x02, - 0x69, 0x01, 0x1a, 0x69, 0x73, 0x43, 0x6f, 0x6e, - 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x6f, 0x72, - 0x01, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x01, 0x0c, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x01, 0x08, - 0x69, 0x74, 0x65, 0x72, 0x01, 0x1c, 0x6e, 0x6f, - 0x74, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x01, 0x08, 0x63, 0x61, - 0x6c, 0x6c, 0x0c, 0x00, 0x02, 0x00, 0xa2, 0x01, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x04, 0x01, - 0xa4, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x43, 0x02, - 0x01, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x01, - 0x03, 0x05, 0xaa, 0x02, 0x00, 0x01, 0x40, 0xa0, - 0x03, 0x00, 0x01, 0x40, 0xc6, 0x03, 0x00, 0x01, - 0x40, 0xcc, 0x01, 0x00, 0x01, 0x40, 0xc8, 0x03, - 0x00, 0x01, 0x40, 0x0c, 0x60, 0x02, 0x01, 0xf8, - 0x01, 0x03, 0x0e, 0x01, 0x06, 0x05, 0x00, 0x86, - 0x04, 0x11, 0xca, 0x03, 0x00, 0x01, 0x00, 0xcc, - 0x03, 0x00, 0x01, 0x00, 0xce, 0x03, 0x00, 0x01, - 0x00, 0xca, 0x03, 0x01, 0xff, 0xff, 0xff, 0xff, - 0x0f, 0x20, 0xcc, 0x03, 0x01, 0x01, 0x20, 0xce, - 0x03, 0x01, 0x02, 0x20, 0xd0, 0x03, 0x02, 0x00, - 0x20, 0xd2, 0x03, 0x02, 0x04, 0x20, 0xd4, 0x03, - 0x02, 0x05, 0x20, 0xd6, 0x03, 0x02, 0x06, 0x20, - 0xd8, 0x03, 0x02, 0x07, 0x20, 0x64, 0x06, 0x08, - 0x20, 0x82, 0x01, 0x07, 0x09, 0x20, 0xda, 0x03, - 0x0a, 0x08, 0x30, 0x82, 0x01, 0x0d, 0x0b, 0x20, - 0xd4, 0x01, 0x0d, 0x0c, 0x20, 0x10, 0x00, 0x01, - 0x00, 0xa0, 0x03, 0x01, 0x03, 0xc6, 0x03, 0x02, - 0x03, 0xc8, 0x03, 0x04, 0x03, 0xaa, 0x02, 0x00, - 0x03, 0xcc, 0x01, 0x03, 0x03, 0x08, 0xc4, 0x0d, - 0x62, 0x02, 0x00, 0x62, 0x01, 0x00, 0x62, 0x00, - 0x00, 0xd3, 0xcb, 0xd4, 0x11, 0xf4, 0xec, 0x08, - 0x0e, 0x39, 0x46, 0x00, 0x00, 0x00, 0xdc, 0xcc, - 0xd5, 0x11, 0xf4, 0xec, 0x08, 0x0e, 0x39, 0x46, - 0x00, 0x00, 0x00, 0xdd, 0xcd, 0x62, 0x07, 0x00, - 0x62, 0x06, 0x00, 0x62, 0x05, 0x00, 0x62, 0x04, - 0x00, 0x62, 0x03, 0x00, 0xd4, 0x39, 0x46, 0x00, - 0x00, 0x00, 0xb0, 0xec, 0x16, 0xd4, 0x98, 0x04, - 0x1b, 0x00, 0x00, 0x00, 0xb0, 0xec, 0x0c, 0xdf, - 0x11, 0x04, 0xee, 0x00, 0x00, 0x00, 0x21, 0x01, - 0x00, 0x30, 0x06, 0xce, 0xb6, 0xc4, 0x04, 0xc3, - 0x0d, 0xf7, 0xc4, 0x05, 0x09, 0xc4, 0x06, 0xd3, - 0xe0, 0x48, 0xc4, 0x07, 0x63, 0x07, 0x00, 0x07, - 0xad, 0xec, 0x0f, 0x0a, 0x11, 0x64, 0x06, 0x00, - 0x0e, 0xd3, 0xe1, 0x48, 0x11, 0x64, 0x07, 0x00, - 0x0e, 0x63, 0x07, 0x00, 0x07, 0xad, 0x6a, 0xa6, - 0x00, 0x00, 0x00, 0x62, 0x08, 0x00, 0x06, 0x11, - 0xf4, 0xed, 0x0c, 0x71, 0x43, 0x32, 0x00, 0x00, - 0x00, 0xc4, 0x08, 0x0e, 0xee, 0x05, 0x0e, 0xd3, - 0xee, 0xf2, 0x63, 0x08, 0x00, 0x8e, 0x11, 0xed, - 0x03, 0x0e, 0xb6, 0x11, 0x64, 0x08, 0x00, 0x0e, - 0x63, 0x05, 0x00, 0xec, 0x0c, 0xc3, 0x0d, 0x11, - 0x63, 0x08, 0x00, 0x21, 0x01, 0x00, 0xee, 0x06, - 0xe2, 0x63, 0x08, 0x00, 0xf1, 0x11, 0x64, 0x03, - 0x00, 0x0e, 0x63, 0x04, 0x00, 0x63, 0x08, 0x00, - 0xa7, 0x6a, 0x2a, 0x01, 0x00, 0x00, 0x62, 0x09, - 0x00, 0xd3, 0x63, 0x04, 0x00, 0x48, 0xc4, 0x09, - 0x63, 0x06, 0x00, 0xec, 0x0a, 0x63, 0x09, 0x00, - 0x8c, 0x11, 0x64, 0x09, 0x00, 0x0e, 0xd4, 0xec, - 0x17, 0xd4, 0x43, 0xef, 0x00, 0x00, 0x00, 0xd5, - 0x63, 0x09, 0x00, 0x63, 0x04, 0x00, 0x24, 0x03, - 0x00, 0x8c, 0x11, 0x64, 0x09, 0x00, 0x0e, 0x5f, - 0x04, 0x00, 0x63, 0x03, 0x00, 0x63, 0x04, 0x00, - 0x92, 0x64, 0x04, 0x00, 0x0b, 0x63, 0x09, 0x00, - 0x4d, 0x41, 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x3e, - 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x3f, 0x00, 0x00, - 0x00, 0xf3, 0x0e, 0xee, 0x9e, 0x62, 0x0a, 0x00, - 0x63, 0x07, 0x00, 0x43, 0xef, 0x00, 0x00, 0x00, - 0xd3, 0x24, 0x01, 0x00, 0xc4, 0x0a, 0x63, 0x05, - 0x00, 0xec, 0x09, 0xc3, 0x0d, 0x11, 0x21, 0x00, - 0x00, 0xee, 0x03, 0xe2, 0xf0, 0x11, 0x64, 0x03, - 0x00, 0x0e, 0x6d, 0x8c, 0x00, 0x00, 0x00, 0x62, - 0x0c, 0x00, 0x62, 0x0b, 0x00, 0x06, 0x11, 0xf4, - 0xed, 0x13, 0x71, 0x43, 0x41, 0x00, 0x00, 0x00, - 0xc4, 0x0b, 0x43, 0x6a, 0x00, 0x00, 0x00, 0xc4, - 0x0c, 0x0e, 0xee, 0x10, 0x0e, 0x63, 0x0a, 0x00, - 0x43, 0x6b, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, - 0x8c, 0xee, 0xe0, 0x63, 0x0c, 0x00, 0xed, 0x4e, - 0x63, 0x06, 0x00, 0xec, 0x0a, 0x63, 0x0b, 0x00, - 0x8c, 0x11, 0x64, 0x0b, 0x00, 0x0e, 0xd4, 0xec, - 0x17, 0xd4, 0x43, 0xef, 0x00, 0x00, 0x00, 0xd5, - 0x63, 0x0b, 0x00, 0x63, 0x04, 0x00, 0x24, 0x03, - 0x00, 0x8c, 0x11, 0x64, 0x0b, 0x00, 0x0e, 0x5f, - 0x04, 0x00, 0x63, 0x03, 0x00, 0x63, 0x04, 0x00, - 0x92, 0x64, 0x04, 0x00, 0x0b, 0x63, 0x0b, 0x00, - 0x4d, 0x41, 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x3e, - 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x3f, 0x00, 0x00, - 0x00, 0xf3, 0x0e, 0xee, 0x83, 0x0e, 0x06, 0x6e, - 0x0d, 0x00, 0x00, 0x00, 0x0e, 0xee, 0x1e, 0x6e, - 0x05, 0x00, 0x00, 0x00, 0x30, 0x63, 0x0a, 0x00, - 0x42, 0x06, 0x00, 0x00, 0x00, 0xec, 0x0d, 0x63, - 0x0a, 0x00, 0x43, 0x06, 0x00, 0x00, 0x00, 0x24, - 0x00, 0x00, 0x0e, 0x6f, 0x63, 0x03, 0x00, 0x63, - 0x04, 0x00, 0x44, 0x32, 0x00, 0x00, 0x00, 0x63, - 0x03, 0x00, 0x2f, 0xc1, 0x00, 0x28, 0xc1, 0x00, - 0xcf, 0x28, +const uint8_t qjsc_builtin_array_fromasync[875] = { + 0x1a, 0x29, 0xd1, 0x7b, 0x48, 0x0e, 0x01, 0x28, + 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0xb7, 0x61, + 0x73, 0x79, 0x6e, 0x63, 0x49, 0x74, 0x65, 0x72, + 0x61, 0x74, 0x6f, 0x72, 0x01, 0x2a, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0xb7, 0x64, 0x65, 0x66, + 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, + 0x72, 0x74, 0x79, 0x01, 0x1e, 0x53, 0x79, 0x6d, + 0x62, 0x6f, 0x6c, 0xb7, 0x69, 0x74, 0x65, 0x72, + 0x61, 0x74, 0x6f, 0x72, 0x01, 0x12, 0x61, 0x72, + 0x72, 0x61, 0x79, 0x4c, 0x69, 0x6b, 0x65, 0x01, + 0x0a, 0x6d, 0x61, 0x70, 0x46, 0x6e, 0x01, 0x0e, + 0x74, 0x68, 0x69, 0x73, 0x41, 0x72, 0x67, 0x01, + 0x0c, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x01, + 0x02, 0x69, 0x01, 0x1a, 0x69, 0x73, 0x43, 0x6f, + 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x6f, + 0x72, 0x01, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x01, + 0x0c, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x01, + 0x08, 0x69, 0x74, 0x65, 0x72, 0x01, 0x1c, 0x6e, + 0x6f, 0x74, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x01, 0x08, 0x63, + 0x61, 0x6c, 0x6c, 0x0c, 0x00, 0x02, 0x00, 0xa8, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x04, 0x01, 0xaa, 0x01, 0x00, 0x00, 0x00, 0x0c, + 0x43, 0x02, 0x01, 0x00, 0x05, 0x00, 0x05, 0x01, + 0x05, 0x00, 0x01, 0x03, 0x05, 0xbe, 0x02, 0x00, + 0x01, 0x40, 0x03, 0xb4, 0x03, 0x00, 0x01, 0x40, + 0x00, 0xe4, 0x03, 0x00, 0x01, 0x40, 0x01, 0xe6, + 0x03, 0x00, 0x01, 0x40, 0x04, 0xe8, 0x03, 0x00, + 0x01, 0x40, 0x02, 0x0c, 0x60, 0x02, 0x01, 0x88, + 0x02, 0x03, 0x0e, 0x01, 0x06, 0x00, 0x05, 0x00, + 0x86, 0x04, 0x11, 0xea, 0x03, 0x00, 0x01, 0x00, + 0xec, 0x03, 0x00, 0x01, 0x00, 0xee, 0x03, 0x00, + 0x01, 0x00, 0xea, 0x03, 0x01, 0xff, 0xff, 0xff, + 0xff, 0x0f, 0x20, 0xec, 0x03, 0x01, 0x01, 0x20, + 0xee, 0x03, 0x01, 0x02, 0x20, 0xf0, 0x03, 0x02, + 0x00, 0x20, 0xf2, 0x03, 0x02, 0x04, 0x20, 0xf4, + 0x03, 0x02, 0x05, 0x20, 0xf6, 0x03, 0x02, 0x06, + 0x20, 0xf8, 0x03, 0x02, 0x07, 0x20, 0x66, 0x06, + 0x08, 0x20, 0x88, 0x01, 0x07, 0x09, 0x20, 0xfa, + 0x03, 0x0a, 0x08, 0x30, 0x88, 0x01, 0x0d, 0x0b, + 0x20, 0xe2, 0x01, 0x0d, 0x0c, 0x20, 0x10, 0x00, + 0x01, 0x00, 0xb4, 0x03, 0x01, 0x01, 0xe4, 0x03, + 0x02, 0x01, 0xe8, 0x03, 0x04, 0x01, 0xbe, 0x02, + 0x00, 0x01, 0xe6, 0x03, 0x03, 0x01, 0x08, 0xc8, + 0x0d, 0x60, 0x02, 0x00, 0x60, 0x01, 0x00, 0x60, + 0x00, 0x00, 0xd7, 0xcf, 0xd8, 0x11, 0xf8, 0xf0, + 0x08, 0x0e, 0x38, 0x49, 0x00, 0x00, 0x00, 0xe0, + 0xd0, 0xd9, 0x11, 0xf8, 0xf0, 0x08, 0x0e, 0x38, + 0x49, 0x00, 0x00, 0x00, 0xe1, 0xd1, 0x60, 0x07, + 0x00, 0x60, 0x06, 0x00, 0x60, 0x05, 0x00, 0x60, + 0x04, 0x00, 0x60, 0x03, 0x00, 0xd8, 0x38, 0x49, + 0x00, 0x00, 0x00, 0xae, 0xf0, 0x16, 0xd8, 0x96, + 0x04, 0x1b, 0x00, 0x00, 0x00, 0xae, 0xf0, 0x0c, + 0xe3, 0x11, 0x04, 0xfe, 0x00, 0x00, 0x00, 0x21, + 0x01, 0x00, 0x30, 0x06, 0xd2, 0xba, 0xc8, 0x04, + 0xc7, 0x0d, 0xfb, 0xc8, 0x05, 0x09, 0xc8, 0x06, + 0xd7, 0xe4, 0x46, 0xc8, 0x07, 0x61, 0x07, 0x00, + 0x07, 0xab, 0xf0, 0x0f, 0x0a, 0x11, 0x62, 0x06, + 0x00, 0x0e, 0xd7, 0xe5, 0x46, 0x11, 0x62, 0x07, + 0x00, 0x0e, 0x61, 0x07, 0x00, 0x07, 0xab, 0x68, + 0xa6, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x06, + 0x11, 0xf8, 0xf1, 0x0c, 0x70, 0x41, 0x33, 0x00, + 0x00, 0x00, 0xc8, 0x08, 0x0e, 0xf2, 0x05, 0x0e, + 0xd7, 0xf2, 0xf2, 0x61, 0x08, 0x00, 0x8c, 0x11, + 0xf1, 0x03, 0x0e, 0xba, 0x11, 0x62, 0x08, 0x00, + 0x0e, 0x61, 0x05, 0x00, 0xf0, 0x0c, 0xc7, 0x0d, + 0x11, 0x61, 0x08, 0x00, 0x21, 0x01, 0x00, 0xf2, + 0x06, 0xe6, 0x61, 0x08, 0x00, 0xf5, 0x11, 0x62, + 0x03, 0x00, 0x0e, 0x61, 0x04, 0x00, 0x61, 0x08, + 0x00, 0xa5, 0x68, 0x2a, 0x01, 0x00, 0x00, 0x60, + 0x09, 0x00, 0xd7, 0x61, 0x04, 0x00, 0x46, 0xc8, + 0x09, 0x61, 0x06, 0x00, 0xf0, 0x0a, 0x61, 0x09, + 0x00, 0x8a, 0x11, 0x62, 0x09, 0x00, 0x0e, 0xd8, + 0xf0, 0x17, 0xd8, 0x41, 0xff, 0x00, 0x00, 0x00, + 0xd9, 0x61, 0x09, 0x00, 0x61, 0x04, 0x00, 0x24, + 0x03, 0x00, 0x8a, 0x11, 0x62, 0x09, 0x00, 0x0e, + 0x5d, 0x04, 0x00, 0x61, 0x03, 0x00, 0x61, 0x04, + 0x00, 0x90, 0x62, 0x04, 0x00, 0x0b, 0x61, 0x09, + 0x00, 0x4b, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x4b, + 0x41, 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x42, 0x00, + 0x00, 0x00, 0xf7, 0x0e, 0xf2, 0x9e, 0x60, 0x0a, + 0x00, 0x61, 0x07, 0x00, 0x41, 0xff, 0x00, 0x00, + 0x00, 0xd7, 0x24, 0x01, 0x00, 0xc8, 0x0a, 0x61, + 0x05, 0x00, 0xf0, 0x09, 0xc7, 0x0d, 0x11, 0x21, + 0x00, 0x00, 0xf2, 0x03, 0xe6, 0xf4, 0x11, 0x62, + 0x03, 0x00, 0x0e, 0x6b, 0x8c, 0x00, 0x00, 0x00, + 0x60, 0x0c, 0x00, 0x60, 0x0b, 0x00, 0x06, 0x11, + 0xf8, 0xf1, 0x13, 0x70, 0x41, 0x44, 0x00, 0x00, + 0x00, 0xc8, 0x0b, 0x41, 0x71, 0x00, 0x00, 0x00, + 0xc8, 0x0c, 0x0e, 0xf2, 0x10, 0x0e, 0x61, 0x0a, + 0x00, 0x41, 0x72, 0x00, 0x00, 0x00, 0x24, 0x00, + 0x00, 0x8a, 0xf2, 0xe0, 0x61, 0x0c, 0x00, 0xf1, + 0x4e, 0x61, 0x06, 0x00, 0xf0, 0x0a, 0x61, 0x0b, + 0x00, 0x8a, 0x11, 0x62, 0x0b, 0x00, 0x0e, 0xd8, + 0xf0, 0x17, 0xd8, 0x41, 0xff, 0x00, 0x00, 0x00, + 0xd9, 0x61, 0x0b, 0x00, 0x61, 0x04, 0x00, 0x24, + 0x03, 0x00, 0x8a, 0x11, 0x62, 0x0b, 0x00, 0x0e, + 0x5d, 0x04, 0x00, 0x61, 0x03, 0x00, 0x61, 0x04, + 0x00, 0x90, 0x62, 0x04, 0x00, 0x0b, 0x61, 0x0b, + 0x00, 0x4b, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x4b, + 0x41, 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x42, 0x00, + 0x00, 0x00, 0xf7, 0x0e, 0xf2, 0x83, 0x0e, 0x06, + 0x6c, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0xf2, 0x1e, + 0x6c, 0x05, 0x00, 0x00, 0x00, 0x30, 0x61, 0x0a, + 0x00, 0x40, 0x06, 0x00, 0x00, 0x00, 0xf0, 0x0d, + 0x61, 0x0a, 0x00, 0x41, 0x06, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x0e, 0x6d, 0x61, 0x03, 0x00, + 0x61, 0x04, 0x00, 0x42, 0x33, 0x00, 0x00, 0x00, + 0x61, 0x03, 0x00, 0x2f, 0xc5, 0x00, 0x28, 0xc5, + 0x00, 0xd3, 0x28, }; diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-array-fromasync.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-array-fromasync.js index a07e40ef..3e425c00 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-array-fromasync.js +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-array-fromasync.js @@ -1,10 +1,10 @@ -;(function(Array, TypeError, asyncIterator, defineProperty, iterator) { +;(function(Array, TypeError, Symbol·asyncIterator, Object·defineProperty, Symbol·iterator) { "use strict" // result.length=i should throw if .length is not writable return async function fromAsync(arrayLike, mapFn=undefined, thisArg=undefined) { if (mapFn !== undefined && typeof mapFn !== "function") throw new TypeError("not a function") let result, i = 0, isConstructor = typeof this === "function" - let sync = false, method = arrayLike[asyncIterator] - if (method == null) sync = true, method = arrayLike[iterator] + let sync = false, method = arrayLike[Symbol·asyncIterator] + if (method == null) sync = true, method = arrayLike[Symbol·iterator] if (method == null) { let {length} = arrayLike length = +length || 0 @@ -13,7 +13,7 @@ let value = arrayLike[i] if (sync) value = await value if (mapFn) value = await mapFn.call(thisArg, value, i) - defineProperty(result, i++, {value, configurable: true, writable: true}) + Object·defineProperty(result, i++, {value, configurable: true, writable: true}) } } else { const iter = method.call(arrayLike) @@ -24,7 +24,7 @@ if (done) break if (sync) value = await value if (mapFn) value = await mapFn.call(thisArg, value, i) - defineProperty(result, i++, {value, configurable: true, writable: true}) + Object·defineProperty(result, i++, {value, configurable: true, writable: true}) } } finally { if (iter.return) iter.return() diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-iterator-zip-keyed.h b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-iterator-zip-keyed.h new file mode 100755 index 00000000..fd47c4a0 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-iterator-zip-keyed.h @@ -0,0 +1,332 @@ +/* File generated automatically by the QuickJS-ng compiler. */ + +#include + +const uint32_t qjsc_builtin_iterator_zip_keyed_size = 2582; + +const uint8_t qjsc_builtin_iterator_zip_keyed[2582] = { + 0x1a, 0xeb, 0x00, 0x6f, 0x50, 0x2b, 0x01, 0x1c, + 0x49, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, + 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x01, 0x08, + 0x63, 0x61, 0x6c, 0x6c, 0x01, 0x24, 0x68, 0x61, + 0x73, 0x4f, 0x77, 0x6e, 0x45, 0x6e, 0x75, 0x6d, + 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, + 0x01, 0x24, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e, + 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, + 0x4b, 0x65, 0x79, 0x73, 0x01, 0x1e, 0x53, 0x79, + 0x6d, 0x62, 0x6f, 0x6c, 0xb7, 0x69, 0x74, 0x65, + 0x72, 0x61, 0x74, 0x6f, 0x72, 0x01, 0x0a, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x01, 0x0a, 0x63, 0x6c, + 0x6f, 0x73, 0x65, 0x01, 0x10, 0x63, 0x6c, 0x6f, + 0x73, 0x65, 0x61, 0x6c, 0x6c, 0x01, 0x02, 0x76, + 0x01, 0x02, 0x73, 0x01, 0x08, 0x69, 0x74, 0x65, + 0x72, 0x01, 0x0c, 0x6d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x01, 0x02, 0x65, 0x01, 0x0a, 0x69, 0x74, + 0x65, 0x72, 0x73, 0x01, 0x0a, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x01, 0x04, 0x65, 0x78, 0x01, 0x02, + 0x69, 0x01, 0x12, 0x69, 0x74, 0x65, 0x72, 0x61, + 0x62, 0x6c, 0x65, 0x73, 0x01, 0x0e, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x01, 0x08, 0x6d, + 0x6f, 0x64, 0x65, 0x01, 0x0e, 0x70, 0x61, 0x64, + 0x64, 0x69, 0x6e, 0x67, 0x01, 0x0a, 0x6e, 0x65, + 0x78, 0x74, 0x73, 0x01, 0x08, 0x70, 0x61, 0x64, + 0x73, 0x01, 0x06, 0x6b, 0x65, 0x79, 0x01, 0x06, + 0x64, 0x65, 0x6c, 0x01, 0x02, 0x6a, 0x01, 0x0a, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x01, 0x0a, 0x61, + 0x6c, 0x69, 0x76, 0x65, 0x01, 0x0a, 0x64, 0x6f, + 0x6e, 0x65, 0x73, 0x01, 0x0e, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x73, 0x01, 0x0c, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x01, 0x1c, 0x72, 0x75, + 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x7a, 0x69, + 0x70, 0x70, 0x65, 0x72, 0x01, 0x06, 0x62, 0x75, + 0x67, 0x01, 0x0e, 0x6c, 0x6f, 0x6e, 0x67, 0x65, + 0x73, 0x74, 0x01, 0x0c, 0x73, 0x74, 0x72, 0x69, + 0x63, 0x74, 0x01, 0x22, 0x6d, 0x69, 0x73, 0x6d, + 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x69, + 0x6e, 0x70, 0x75, 0x74, 0x73, 0x01, 0x10, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x65, 0x73, 0x74, 0x01, + 0x16, 0x62, 0x75, 0x67, 0x3a, 0x20, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x3d, 0x01, 0x1a, 0x62, 0x61, + 0x64, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x62, + 0x6c, 0x65, 0x73, 0x01, 0x16, 0x62, 0x61, 0x64, + 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x01, 0x10, 0x62, 0x61, 0x64, 0x20, 0x6d, 0x6f, + 0x64, 0x65, 0x01, 0x16, 0x62, 0x61, 0x64, 0x20, + 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x01, + 0x18, 0x62, 0x61, 0x64, 0x20, 0x69, 0x74, 0x65, + 0x72, 0x61, 0x74, 0x6f, 0x72, 0x0c, 0x00, 0x02, + 0x00, 0xa8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x04, 0x01, 0xaa, 0x01, 0x00, 0x00, + 0x00, 0x0c, 0x43, 0x02, 0x00, 0x00, 0x07, 0x03, + 0x07, 0x01, 0x0a, 0x00, 0x04, 0x0c, 0x0a, 0xe4, + 0x03, 0x00, 0x01, 0x40, 0x09, 0xb8, 0x03, 0x00, + 0x01, 0x40, 0x03, 0xb4, 0x03, 0x00, 0x01, 0x40, + 0x00, 0xe6, 0x03, 0x00, 0x01, 0x40, 0x01, 0xe8, + 0x03, 0x00, 0x01, 0x40, 0x07, 0xea, 0x03, 0x00, + 0x01, 0x40, 0x06, 0xec, 0x03, 0x00, 0x01, 0x40, + 0x08, 0xee, 0x03, 0x00, 0x00, 0x40, 0x05, 0xf0, + 0x03, 0x00, 0x01, 0x40, 0x02, 0xf2, 0x03, 0x00, + 0x02, 0x40, 0x04, 0x0c, 0x43, 0x02, 0x00, 0xee, + 0x03, 0x02, 0x00, 0x02, 0x03, 0x00, 0x01, 0x00, + 0x17, 0x02, 0xf4, 0x03, 0x00, 0x01, 0x00, 0xf6, + 0x03, 0x00, 0x01, 0x00, 0xb4, 0x03, 0x02, 0x01, + 0xd7, 0x96, 0x04, 0x4d, 0x00, 0x00, 0x00, 0xad, + 0xf0, 0x07, 0xd7, 0x07, 0xae, 0xf0, 0x02, 0x29, + 0xe3, 0x11, 0xd8, 0x21, 0x01, 0x00, 0x30, 0x0c, + 0x43, 0x02, 0x00, 0xf0, 0x03, 0x01, 0x02, 0x01, + 0x04, 0x00, 0x01, 0x00, 0x2e, 0x03, 0xf8, 0x03, + 0x00, 0x01, 0x00, 0xfa, 0x03, 0x02, 0x00, 0x20, + 0xfc, 0x03, 0x05, 0x00, 0x03, 0xe6, 0x03, 0x03, + 0x01, 0x6b, 0x23, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0xd7, 0x95, 0xf0, 0x04, 0x06, 0x6e, 0x28, + 0xd7, 0x40, 0x06, 0x00, 0x00, 0x00, 0xcf, 0x61, + 0x00, 0x00, 0xf0, 0x08, 0xe3, 0xd7, 0x61, 0x00, + 0x00, 0xf6, 0x0e, 0x0e, 0x29, 0xd0, 0x6b, 0x07, + 0x00, 0x00, 0x00, 0xcc, 0x6e, 0x28, 0x30, 0x0c, + 0x43, 0x02, 0x00, 0xf2, 0x03, 0x02, 0x04, 0x02, + 0x03, 0x00, 0x01, 0x00, 0x55, 0x06, 0xfe, 0x03, + 0x00, 0x01, 0x00, 0x80, 0x04, 0x00, 0x01, 0x00, + 0x82, 0x04, 0x01, 0x00, 0x20, 0x84, 0x04, 0x02, + 0x01, 0x20, 0xf8, 0x03, 0x03, 0x02, 0x20, 0xfc, + 0x03, 0x03, 0x03, 0x20, 0xf0, 0x03, 0x01, 0x00, + 0x60, 0x00, 0x00, 0x38, 0x49, 0x00, 0x00, 0x00, + 0xcf, 0x60, 0x01, 0x00, 0xd8, 0xd0, 0x61, 0x01, + 0x00, 0x8f, 0x62, 0x01, 0x00, 0xba, 0xa7, 0xf0, + 0x39, 0x60, 0x03, 0x00, 0x60, 0x02, 0x00, 0xd7, + 0x61, 0x01, 0x00, 0x46, 0xd1, 0xd7, 0x61, 0x01, + 0x00, 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, + 0x1b, 0x1b, 0x38, 0x49, 0x00, 0x00, 0x00, 0x1b, + 0x71, 0x1b, 0x48, 0xe3, 0x61, 0x02, 0x00, 0xf5, + 0xd2, 0x61, 0x00, 0x00, 0x95, 0xf0, 0xc8, 0x61, + 0x03, 0x00, 0x11, 0x62, 0x00, 0x00, 0x0e, 0xf2, + 0xbe, 0x61, 0x00, 0x00, 0x28, 0x0c, 0x41, 0x02, + 0x00, 0xba, 0x02, 0x02, 0x15, 0x01, 0x06, 0x08, + 0x09, 0x02, 0xc9, 0x05, 0x17, 0x86, 0x04, 0x00, + 0x01, 0x00, 0x88, 0x04, 0x00, 0x01, 0x00, 0x86, + 0x04, 0x01, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x20, + 0x88, 0x04, 0x01, 0x01, 0x20, 0x8a, 0x04, 0x02, + 0x00, 0x60, 0x04, 0x8c, 0x04, 0x02, 0x03, 0x20, + 0x62, 0x02, 0x04, 0x60, 0x02, 0x80, 0x04, 0x02, + 0x05, 0x60, 0x01, 0xfe, 0x03, 0x02, 0x06, 0x60, + 0x03, 0x8e, 0x04, 0x02, 0x07, 0x60, 0x06, 0x90, + 0x04, 0x02, 0x08, 0x60, 0x05, 0x92, 0x04, 0x09, + 0x15, 0x20, 0x84, 0x04, 0x0b, 0x15, 0x20, 0x94, + 0x04, 0x0c, 0x0b, 0x20, 0x92, 0x04, 0x0c, 0x0c, + 0x20, 0xf8, 0x03, 0x0e, 0x0d, 0x20, 0xfa, 0x03, + 0x10, 0x0e, 0x20, 0x96, 0x04, 0x14, 0x0d, 0x20, + 0x84, 0x04, 0x19, 0x15, 0x20, 0x84, 0x04, 0x1b, + 0x15, 0x20, 0xfc, 0x03, 0x1c, 0x15, 0x03, 0x98, + 0x04, 0x02, 0x09, 0x60, 0x00, 0x9a, 0x04, 0x02, + 0x14, 0x60, 0x07, 0xb4, 0x03, 0x02, 0x01, 0xb8, + 0x03, 0x01, 0x01, 0xe6, 0x03, 0x03, 0x01, 0xf2, + 0x03, 0x02, 0x00, 0xee, 0x03, 0x00, 0x00, 0xea, + 0x03, 0x05, 0x01, 0xe8, 0x03, 0x04, 0x01, 0xec, + 0x03, 0x06, 0x01, 0xe4, 0x03, 0x00, 0x01, 0x0c, + 0x42, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x05, + 0x00, 0x0c, 0x00, 0xf7, 0x04, 0x09, 0x9c, 0x04, + 0x01, 0x00, 0x20, 0xe6, 0x01, 0x01, 0x01, 0x20, + 0x9e, 0x04, 0x01, 0x02, 0x20, 0x84, 0x04, 0x03, + 0x03, 0x20, 0x92, 0x04, 0x04, 0x04, 0x20, 0xf8, + 0x03, 0x04, 0x05, 0x20, 0xa0, 0x04, 0x04, 0x06, + 0x20, 0xfc, 0x03, 0x09, 0x07, 0x03, 0x82, 0x04, + 0x10, 0x07, 0x20, 0x98, 0x04, 0x13, 0x10, 0xb4, + 0x03, 0x00, 0x02, 0xb8, 0x03, 0x01, 0x02, 0x80, + 0x04, 0x05, 0x10, 0x62, 0x04, 0x10, 0xfe, 0x03, + 0x06, 0x10, 0x8a, 0x04, 0x02, 0x10, 0x90, 0x04, + 0x08, 0x10, 0xe6, 0x03, 0x02, 0x02, 0x8e, 0x04, + 0x07, 0x10, 0x9a, 0x04, 0x14, 0x10, 0xf2, 0x03, + 0x03, 0x02, 0x60, 0x02, 0x00, 0x60, 0x01, 0x00, + 0x60, 0x00, 0x00, 0x64, 0x00, 0x00, 0x11, 0xba, + 0xad, 0xf1, 0x06, 0x11, 0xbb, 0xad, 0xf0, 0x09, + 0xbc, 0x11, 0x65, 0x00, 0x00, 0x0e, 0xf2, 0x33, + 0x11, 0xbc, 0xad, 0xf0, 0x0c, 0xe4, 0x11, 0x04, + 0x11, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, 0x30, + 0x11, 0xbd, 0xad, 0xf0, 0x13, 0x0b, 0x38, 0x49, + 0x00, 0x00, 0x00, 0x4b, 0x44, 0x00, 0x00, 0x00, + 0x0a, 0x4b, 0x71, 0x00, 0x00, 0x00, 0x28, 0xe5, + 0x11, 0x04, 0x12, 0x01, 0x00, 0x00, 0x21, 0x01, + 0x00, 0x30, 0x0e, 0xba, 0xcf, 0xba, 0xd0, 0x0c, + 0x07, 0xd1, 0x60, 0x03, 0x00, 0xba, 0xd2, 0x61, + 0x03, 0x00, 0x64, 0x03, 0x00, 0xa5, 0x68, 0xdd, + 0x01, 0x00, 0x00, 0x60, 0x06, 0x00, 0x60, 0x05, + 0x00, 0x60, 0x04, 0x00, 0x64, 0x04, 0x00, 0x61, + 0x03, 0x00, 0x46, 0xc8, 0x04, 0x64, 0x05, 0x00, + 0x61, 0x03, 0x00, 0x46, 0xc8, 0x05, 0x61, 0x05, + 0x00, 0x95, 0xf0, 0x34, 0x64, 0x06, 0x00, 0x04, + 0x13, 0x01, 0x00, 0x00, 0xae, 0xf0, 0x0c, 0xe5, + 0x11, 0x04, 0x12, 0x01, 0x00, 0x00, 0x21, 0x01, + 0x00, 0x30, 0x61, 0x02, 0x00, 0x61, 0x04, 0x00, + 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, + 0x1b, 0x64, 0x07, 0x00, 0x61, 0x03, 0x00, 0x46, + 0x1b, 0x71, 0x1b, 0x48, 0xf3, 0x7c, 0x01, 0x06, + 0xc8, 0x06, 0x6b, 0x1a, 0x00, 0x00, 0x00, 0x5d, + 0x08, 0x00, 0x61, 0x05, 0x00, 0x64, 0x09, 0x00, + 0x61, 0x03, 0x00, 0x46, 0xf6, 0x11, 0x62, 0x06, + 0x00, 0x0e, 0x0e, 0xf2, 0x35, 0xc8, 0x07, 0x6b, + 0x30, 0x00, 0x00, 0x00, 0xba, 0x11, 0x65, 0x0a, + 0x00, 0x0e, 0x64, 0x05, 0x00, 0x61, 0x03, 0x00, + 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, + 0x1b, 0x38, 0x49, 0x00, 0x00, 0x00, 0x1b, 0x71, + 0x1b, 0x48, 0x5d, 0x0b, 0x00, 0x64, 0x05, 0x00, + 0x64, 0x03, 0x00, 0xf6, 0x0e, 0xc7, 0x07, 0x30, + 0x30, 0x61, 0x06, 0x00, 0x40, 0x71, 0x00, 0x00, + 0x00, 0x95, 0xf0, 0x4f, 0x64, 0x06, 0x00, 0x04, + 0x14, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x1e, 0x61, + 0x00, 0x00, 0xba, 0xa7, 0xf0, 0x17, 0x5d, 0x0b, + 0x00, 0x64, 0x05, 0x00, 0x64, 0x03, 0x00, 0xf6, + 0x0e, 0xe4, 0x11, 0x04, 0x15, 0x01, 0x00, 0x00, + 0x21, 0x01, 0x00, 0x30, 0x61, 0x02, 0x00, 0x61, + 0x04, 0x00, 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, + 0x71, 0x1b, 0x1b, 0x61, 0x06, 0x00, 0x40, 0x44, + 0x00, 0x00, 0x00, 0x1b, 0x71, 0x1b, 0x48, 0x61, + 0x01, 0x00, 0x90, 0x62, 0x01, 0x00, 0x0e, 0xf3, + 0xd1, 0x00, 0x64, 0x0a, 0x00, 0x8f, 0x65, 0x0a, + 0x00, 0x0e, 0x61, 0x00, 0x00, 0x90, 0x62, 0x00, + 0x00, 0x0e, 0x64, 0x05, 0x00, 0x61, 0x03, 0x00, + 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, + 0x1b, 0x38, 0x49, 0x00, 0x00, 0x00, 0x1b, 0x71, + 0x1b, 0x48, 0x64, 0x06, 0x00, 0x60, 0x08, 0x00, + 0x11, 0x04, 0x16, 0x01, 0x00, 0x00, 0xad, 0xf0, + 0x2e, 0x5d, 0x0b, 0x00, 0x64, 0x05, 0x00, 0x64, + 0x03, 0x00, 0xf6, 0xc8, 0x08, 0x61, 0x08, 0x00, + 0xf0, 0x05, 0x61, 0x08, 0x00, 0x30, 0xbd, 0x11, + 0x65, 0x00, 0x00, 0x0e, 0x0b, 0x38, 0x49, 0x00, + 0x00, 0x00, 0x4b, 0x44, 0x00, 0x00, 0x00, 0x0a, + 0x4b, 0x71, 0x00, 0x00, 0x00, 0x28, 0x11, 0x04, + 0x13, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x3c, 0x64, + 0x0a, 0x00, 0xbb, 0xa5, 0xf0, 0x19, 0xbd, 0x11, + 0x65, 0x00, 0x00, 0x0e, 0x0b, 0x38, 0x49, 0x00, + 0x00, 0x00, 0x4b, 0x44, 0x00, 0x00, 0x00, 0x0a, + 0x4b, 0x71, 0x00, 0x00, 0x00, 0x28, 0x61, 0x02, + 0x00, 0x61, 0x04, 0x00, 0x1b, 0x11, 0xaf, 0xf1, + 0x04, 0x1b, 0x71, 0x1b, 0x1b, 0x64, 0x07, 0x00, + 0x61, 0x03, 0x00, 0x46, 0x1b, 0x71, 0x1b, 0x48, + 0xf2, 0x27, 0x11, 0x04, 0x14, 0x01, 0x00, 0x00, + 0xad, 0xf0, 0x1e, 0x61, 0x01, 0x00, 0xba, 0xa7, + 0xf0, 0x17, 0x5d, 0x0b, 0x00, 0x64, 0x05, 0x00, + 0x64, 0x03, 0x00, 0xf6, 0x0e, 0xe4, 0x11, 0x04, + 0x15, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, 0x30, + 0x0e, 0x61, 0x03, 0x00, 0x90, 0x62, 0x03, 0x00, + 0x0e, 0xf3, 0x1d, 0xfe, 0x61, 0x01, 0x00, 0xba, + 0xad, 0xf0, 0x19, 0xbd, 0x11, 0x65, 0x00, 0x00, + 0x0e, 0x0b, 0x38, 0x49, 0x00, 0x00, 0x00, 0x4b, + 0x44, 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x71, 0x00, + 0x00, 0x00, 0x28, 0xbb, 0x11, 0x65, 0x00, 0x00, + 0x0e, 0x0b, 0x61, 0x02, 0x00, 0x4b, 0x44, 0x00, + 0x00, 0x00, 0x09, 0x4b, 0x71, 0x00, 0x00, 0x00, + 0x28, 0x0c, 0x42, 0x03, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x06, 0x00, 0x06, 0x00, 0x88, 0x01, 0x01, + 0x82, 0x04, 0x01, 0x00, 0x20, 0x98, 0x04, 0x13, + 0x10, 0xb4, 0x03, 0x00, 0x02, 0xb8, 0x03, 0x01, + 0x02, 0xf2, 0x03, 0x03, 0x02, 0xfe, 0x03, 0x06, + 0x10, 0x80, 0x04, 0x05, 0x10, 0x60, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x11, 0xba, 0xad, 0xf0, 0x09, + 0xbd, 0x11, 0x65, 0x00, 0x00, 0x0e, 0xf2, 0x4b, + 0x11, 0xbb, 0xad, 0xf0, 0x09, 0xbc, 0x11, 0x65, + 0x00, 0x00, 0x0e, 0xf2, 0x3e, 0x11, 0xbc, 0xad, + 0xf0, 0x0c, 0xe4, 0x11, 0x04, 0x11, 0x01, 0x00, + 0x00, 0x21, 0x01, 0x00, 0x30, 0x11, 0xbd, 0xad, + 0xf0, 0x13, 0x0b, 0x38, 0x49, 0x00, 0x00, 0x00, + 0x4b, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x71, + 0x00, 0x00, 0x00, 0x28, 0xe5, 0x11, 0x04, 0x17, + 0x01, 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x24, 0x01, 0x00, 0x21, 0x01, + 0x00, 0x30, 0x0e, 0xe6, 0x64, 0x04, 0x00, 0x64, + 0x05, 0x00, 0xf6, 0xcf, 0x61, 0x00, 0x00, 0xf0, + 0x05, 0x61, 0x00, 0x00, 0x30, 0xbd, 0x11, 0x65, + 0x00, 0x00, 0x0e, 0x0b, 0x38, 0x49, 0x00, 0x00, + 0x00, 0x4b, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x4b, + 0x71, 0x00, 0x00, 0x00, 0x28, 0x60, 0x01, 0x00, + 0x60, 0x00, 0x00, 0xd7, 0xcf, 0xd8, 0x11, 0xf8, + 0xf0, 0x08, 0x0e, 0x38, 0x49, 0x00, 0x00, 0x00, + 0xe0, 0xd0, 0x60, 0x14, 0x00, 0x60, 0x13, 0x00, + 0x60, 0x08, 0x00, 0x60, 0x07, 0x00, 0x60, 0x06, + 0x00, 0x60, 0x05, 0x00, 0x60, 0x04, 0x00, 0x60, + 0x03, 0x00, 0x60, 0x02, 0x00, 0x5d, 0x04, 0x00, + 0xd7, 0x04, 0x18, 0x01, 0x00, 0x00, 0xf6, 0x0e, + 0xd8, 0x38, 0x49, 0x00, 0x00, 0x00, 0xad, 0xf0, + 0x06, 0x0c, 0x07, 0xdc, 0xf2, 0x0c, 0x5d, 0x04, + 0x00, 0xd8, 0x04, 0x19, 0x01, 0x00, 0x00, 0xf6, + 0x0e, 0xd8, 0x40, 0x05, 0x01, 0x00, 0x00, 0xd1, + 0x61, 0x02, 0x00, 0x38, 0x49, 0x00, 0x00, 0x00, + 0xad, 0xf0, 0x0b, 0x04, 0x16, 0x01, 0x00, 0x00, + 0x11, 0x62, 0x02, 0x00, 0x0e, 0x61, 0x02, 0x00, + 0x04, 0x14, 0x01, 0x00, 0x00, 0xad, 0x11, 0xf1, + 0x18, 0x0e, 0x61, 0x02, 0x00, 0x04, 0x13, 0x01, + 0x00, 0x00, 0xad, 0x11, 0xf1, 0x0b, 0x0e, 0x61, + 0x02, 0x00, 0x04, 0x16, 0x01, 0x00, 0x00, 0xad, + 0x95, 0xf0, 0x0c, 0xe3, 0x11, 0x04, 0x1a, 0x01, + 0x00, 0x00, 0x21, 0x01, 0x00, 0x30, 0x38, 0x49, + 0x00, 0x00, 0x00, 0xd2, 0x61, 0x02, 0x00, 0x04, + 0x13, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x24, 0xd8, + 0x40, 0x06, 0x01, 0x00, 0x00, 0x11, 0x62, 0x03, + 0x00, 0x0e, 0x61, 0x03, 0x00, 0x38, 0x49, 0x00, + 0x00, 0x00, 0xae, 0xf0, 0x0e, 0x5d, 0x04, 0x00, + 0x61, 0x03, 0x00, 0x04, 0x1b, 0x01, 0x00, 0x00, + 0xf6, 0x0e, 0x26, 0x00, 0x00, 0xc8, 0x04, 0xba, + 0xc8, 0x05, 0x26, 0x00, 0x00, 0xc8, 0x06, 0x26, + 0x00, 0x00, 0xc8, 0x07, 0x26, 0x00, 0x00, 0xc8, + 0x08, 0x60, 0x09, 0x00, 0x5d, 0x05, 0x00, 0xd7, + 0xf5, 0x7e, 0xf2, 0x1d, 0xc8, 0x09, 0x61, 0x04, + 0x00, 0x61, 0x05, 0x00, 0x90, 0x62, 0x05, 0x00, + 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, + 0x1b, 0x61, 0x09, 0x00, 0x1b, 0x71, 0x1b, 0x48, + 0x81, 0x00, 0xf0, 0xe1, 0x0e, 0x83, 0x6b, 0x7d, + 0x01, 0x00, 0x00, 0x60, 0x0a, 0x00, 0xba, 0xc8, + 0x0a, 0x61, 0x0a, 0x00, 0x61, 0x05, 0x00, 0xa5, + 0x68, 0xf0, 0x00, 0x00, 0x00, 0x60, 0x0c, 0x00, + 0x60, 0x0b, 0x00, 0x0a, 0xc8, 0x0b, 0x61, 0x04, + 0x00, 0x61, 0x0a, 0x00, 0x46, 0xc8, 0x0c, 0x5d, + 0x06, 0x00, 0xd7, 0x61, 0x0c, 0x00, 0xf6, 0xf0, + 0x78, 0x60, 0x0d, 0x00, 0xd7, 0x61, 0x0c, 0x00, + 0x46, 0xc8, 0x0d, 0x61, 0x0d, 0x00, 0x38, 0x49, + 0x00, 0x00, 0x00, 0xae, 0xf0, 0x63, 0x60, 0x0e, + 0x00, 0x5d, 0x04, 0x00, 0x61, 0x0d, 0x00, 0x04, + 0x1c, 0x01, 0x00, 0x00, 0xf6, 0x0e, 0x61, 0x0d, + 0x00, 0x5d, 0x07, 0x00, 0x46, 0xc8, 0x0e, 0x61, + 0x0e, 0x00, 0xf0, 0x0e, 0xe5, 0x61, 0x0d, 0x00, + 0x61, 0x0e, 0x00, 0xf6, 0x11, 0x62, 0x0d, 0x00, + 0x0e, 0x61, 0x06, 0x00, 0x61, 0x0a, 0x00, 0x1b, + 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, 0x1b, + 0x61, 0x0d, 0x00, 0x1b, 0x71, 0x1b, 0x48, 0x61, + 0x07, 0x00, 0x61, 0x0a, 0x00, 0x1b, 0x11, 0xaf, + 0xf1, 0x04, 0x1b, 0x71, 0x1b, 0x1b, 0x61, 0x0d, + 0x00, 0x40, 0x72, 0x00, 0x00, 0x00, 0x1b, 0x71, + 0x1b, 0x48, 0x09, 0x11, 0x62, 0x0b, 0x00, 0x0e, + 0x61, 0x0b, 0x00, 0xf0, 0x4a, 0x60, 0x0f, 0x00, + 0x61, 0x0a, 0x00, 0xbb, 0x9c, 0xc8, 0x0f, 0x61, + 0x0f, 0x00, 0x61, 0x05, 0x00, 0xa5, 0xf0, 0x27, + 0x61, 0x04, 0x00, 0x61, 0x0f, 0x00, 0xbb, 0x9d, + 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, + 0x1b, 0x61, 0x04, 0x00, 0x61, 0x0f, 0x00, 0x46, + 0x1b, 0x71, 0x1b, 0x48, 0x61, 0x0f, 0x00, 0x90, + 0x62, 0x0f, 0x00, 0x0e, 0xf2, 0xd2, 0x61, 0x05, + 0x00, 0x8f, 0x62, 0x05, 0x00, 0x0e, 0x61, 0x0a, + 0x00, 0x8f, 0x62, 0x0a, 0x00, 0x0e, 0x61, 0x0a, + 0x00, 0x90, 0x62, 0x0a, 0x00, 0x0e, 0xf3, 0x0a, + 0xff, 0x61, 0x02, 0x00, 0x04, 0x13, 0x01, 0x00, + 0x00, 0xad, 0xf0, 0x6e, 0x61, 0x03, 0x00, 0xf0, + 0x38, 0x60, 0x10, 0x00, 0xba, 0xc8, 0x10, 0x61, + 0x10, 0x00, 0x61, 0x05, 0x00, 0xa5, 0xf0, 0x5a, + 0x61, 0x08, 0x00, 0x61, 0x10, 0x00, 0x1b, 0x11, + 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, 0x1b, 0x61, + 0x03, 0x00, 0x61, 0x04, 0x00, 0x61, 0x10, 0x00, + 0x46, 0x46, 0x1b, 0x71, 0x1b, 0x48, 0x61, 0x10, + 0x00, 0x90, 0x62, 0x10, 0x00, 0x0e, 0xf2, 0xd0, + 0x60, 0x11, 0x00, 0xba, 0xc8, 0x11, 0x61, 0x11, + 0x00, 0x61, 0x05, 0x00, 0xa5, 0xf0, 0x23, 0x61, + 0x08, 0x00, 0x61, 0x11, 0x00, 0x1b, 0x11, 0xaf, + 0xf1, 0x04, 0x1b, 0x71, 0x1b, 0x1b, 0x38, 0x49, + 0x00, 0x00, 0x00, 0x1b, 0x71, 0x1b, 0x48, 0x61, + 0x11, 0x00, 0x90, 0x62, 0x11, 0x00, 0x0e, 0xf2, + 0xd6, 0x0e, 0xf2, 0x15, 0xc8, 0x12, 0x6b, 0x10, + 0x00, 0x00, 0x00, 0xe6, 0x61, 0x06, 0x00, 0x61, + 0x05, 0x00, 0xf6, 0x0e, 0xc7, 0x12, 0x30, 0x30, + 0xba, 0xc8, 0x13, 0x61, 0x05, 0x00, 0xc8, 0x14, + 0x0b, 0x5d, 0x08, 0x00, 0x4e, 0xc5, 0x00, 0x53, + 0x72, 0x00, 0x00, 0x00, 0x04, 0xc5, 0x01, 0x53, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x28, 0xc5, 0x00, + 0xcf, 0xc5, 0x01, 0xd0, 0xc5, 0x02, 0xd1, 0xc5, + 0x03, 0x28, 0xc5, 0x00, 0xd3, 0x28, +}; + diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-iterator-zip-keyed.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-iterator-zip-keyed.js new file mode 100755 index 00000000..10aedf37 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-iterator-zip-keyed.js @@ -0,0 +1,194 @@ +;(function(IteratorHelper, InternalError, TypeError, call, + hasOwnEnumProperty, getOwnPropertyKeys, Symbol·iterator) { + function check(v, s) { + if (typeof v === "object" && v !== null) return + throw new TypeError(s) + } + function close(iter) { + try { + if (!iter) return + let method = iter.return + if (method) call(iter, method) + } catch (e) { + return e + } + } + function closeall(iters, count) { + let ex = undefined + for (let i = count; i-- > 0;) { + let iter = iters[i] + iters[i] = undefined + let e = close(iter) + if (!ex) ex = e + } + return ex + } + return function zipKeyed(iterables, options = undefined) { + check(iterables, "bad iterables") + if (options === undefined) options = {__proto__: null} + else check(options, "bad options") + let mode = options.mode + if (mode === undefined) mode = "shortest" + if (!(mode === "strict" || mode === "longest" || mode === "shortest")) + throw new TypeError("bad mode") + let padding = undefined + if (mode === "longest") { + padding = options.padding + if (padding !== undefined) check(padding, "bad padding") + } + let keys = [] + let count = 0 + let iters = [] + let nexts = [] + let pads = [] + for (let key of getOwnPropertyKeys(iterables)) keys[count++] = key + try { + for (let i = 0; i < count; i++) { + let del = true + let key = keys[i] + // test262 goes out of its way to destroy performance here: + // we must only add enumerable properties but because evil + // getters can flip the visibility of subsequent properties, + // we have to first collect *all* properties, enumerable and + // non-enumerable, then check each one when we add it to the + // final list + // TODO(bnoordhuis) optimize by introducing some kind of + // mutation observer; mutation is the uncommon case + if (hasOwnEnumProperty(iterables, key)) { + let iter = iterables[key] + if (iter !== undefined) { + check(iter, "bad iterator") + let method = iter[Symbol·iterator] + if (method) iter = call(iter, method) // iterable -> iterator + iters[i] = iter + nexts[i] = iter.next + del = false + } + } + if (del) { + // splice out property; the assumption here is that the + // vast majority of objects don't have non-enumerable + // properties, or properties whose value is undefined + for (let j = i+1; j < count; j++) keys[j-1] = keys[j] + count-- + i-- + } + } + if (mode === "longest") { + if (padding) { + for (let i = 0; i < count; i++) pads[i] = padding[keys[i]] + } else { + for (let i = 0; i < count; i++) pads[i] = undefined + } + } + } catch (e) { + closeall(iters, count) + throw e + } + // note: uses plain numbers for |state|, using + // constants grows the bytecode by about 200 bytes + let state = 0 // new, suspend, execute, complete + let alive = count + return { + __proto__: IteratorHelper, + // TODO(bnoordhuis) shows up as "at next (:0:1)" in stack + // traces when iterator throws, should be "at next (native)" + next() { + switch (state) { + case 0: // new + case 1: // suspend + state = 2 // execute + break + case 2: // execute + throw new TypeError("running zipper") + case 3: // complete + return {value:undefined, done:true} + default: + throw new InternalError("bug") + } + let dones = 0 + let values = 0 + let results = {__proto__: null} + for (let i = 0; i < count; i++) { + let key = keys[i] + let iter = iters[i] + if (!iter) { + if (mode !== "longest") throw new InternalError("bug") + results[key] = pads[i] + continue + } + let result + try { + result = call(iter, nexts[i]) + } catch (e) { + alive = 0 + iters[i] = undefined + closeall(iters, count) + throw e + } + // order of .done and .value property + // access is observable and matters + if (!result.done) { + if (mode === "strict" && dones > 0) { + closeall(iters, count) + throw new TypeError("mismatched inputs") + } + results[key] = result.value + values++ + continue + } + alive-- + dones++ + iters[i] = undefined + switch (mode) { + case "shortest": + let ex = closeall(iters, count) + if (ex) throw ex + state = 3 // complete + return {value:undefined, done:true} + case "longest": + if (alive < 1) { + state = 3 // complete + return {value:undefined, done:true} + } + results[key] = pads[i] + break + case "strict": + if (values > 0) { + closeall(iters, count) + throw new TypeError("mismatched inputs") + } + break + } + } + if (values === 0) { + state = 3 // complete + return {value:undefined, done:true} + } + state = 1 // suspend + return {value:results, done:false} + }, + return() { + switch (state) { + case 0: // new + state = 3 // complete + break + case 1: // suspend + state = 2 // execute + break + case 2: // execute + throw new TypeError("running zipper") + case 3: // complete + return {value:undefined, done:true} + default: + throw new InternalError(`bug: state=${state}`) + } + // TODO skip when already closed because of earlier exception + let ex = closeall(iters, count) + if (ex) throw ex + state = 3 // complete + return {value:undefined, done:true} + }, + } + } +}) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-iterator-zip.h b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-iterator-zip.h new file mode 100755 index 00000000..190faaa3 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-iterator-zip.h @@ -0,0 +1,337 @@ +/* File generated automatically by the QuickJS-ng compiler. */ + +#include + +const uint32_t qjsc_builtin_iterator_zip_size = 2621; + +const uint8_t qjsc_builtin_iterator_zip[2621] = { + 0x1a, 0xca, 0x2d, 0xe4, 0xa6, 0x2a, 0x01, 0x1c, + 0x49, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, + 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x01, 0x08, + 0x63, 0x61, 0x6c, 0x6c, 0x01, 0x1e, 0x53, 0x79, + 0x6d, 0x62, 0x6f, 0x6c, 0xb7, 0x69, 0x74, 0x65, + 0x72, 0x61, 0x74, 0x6f, 0x72, 0x01, 0x0a, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x01, 0x0a, 0x63, 0x6c, + 0x6f, 0x73, 0x65, 0x01, 0x10, 0x63, 0x6c, 0x6f, + 0x73, 0x65, 0x61, 0x6c, 0x6c, 0x01, 0x02, 0x76, + 0x01, 0x02, 0x73, 0x01, 0x08, 0x69, 0x74, 0x65, + 0x72, 0x01, 0x0c, 0x6d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x01, 0x02, 0x65, 0x01, 0x0a, 0x69, 0x74, + 0x65, 0x72, 0x73, 0x01, 0x0a, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x01, 0x04, 0x65, 0x78, 0x01, 0x02, + 0x69, 0x01, 0x12, 0x69, 0x74, 0x65, 0x72, 0x61, + 0x62, 0x6c, 0x65, 0x73, 0x01, 0x0e, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x01, 0x08, 0x6d, + 0x6f, 0x64, 0x65, 0x01, 0x0e, 0x70, 0x61, 0x64, + 0x64, 0x69, 0x6e, 0x67, 0x01, 0x08, 0x70, 0x61, + 0x64, 0x73, 0x01, 0x0a, 0x6e, 0x65, 0x78, 0x74, + 0x73, 0x01, 0x16, 0x70, 0x61, 0x64, 0x64, 0x69, + 0x6e, 0x67, 0x69, 0x74, 0x65, 0x72, 0x01, 0x1a, + 0x69, 0x74, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, + 0x73, 0x69, 0x74, 0x65, 0x72, 0x01, 0x08, 0x69, + 0x74, 0x65, 0x6d, 0x01, 0x02, 0x74, 0x01, 0x0a, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x01, 0x0a, 0x61, + 0x6c, 0x69, 0x76, 0x65, 0x01, 0x0a, 0x64, 0x6f, + 0x6e, 0x65, 0x73, 0x01, 0x0e, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x73, 0x01, 0x0c, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x01, 0x1c, 0x72, 0x75, + 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x7a, 0x69, + 0x70, 0x70, 0x65, 0x72, 0x01, 0x06, 0x62, 0x75, + 0x67, 0x01, 0x0e, 0x6c, 0x6f, 0x6e, 0x67, 0x65, + 0x73, 0x74, 0x01, 0x0c, 0x73, 0x74, 0x72, 0x69, + 0x63, 0x74, 0x01, 0x22, 0x6d, 0x69, 0x73, 0x6d, + 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x69, + 0x6e, 0x70, 0x75, 0x74, 0x73, 0x01, 0x10, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x65, 0x73, 0x74, 0x01, + 0x16, 0x62, 0x75, 0x67, 0x3a, 0x20, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x3d, 0x01, 0x1a, 0x62, 0x61, + 0x64, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x62, + 0x6c, 0x65, 0x73, 0x01, 0x16, 0x62, 0x61, 0x64, + 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x01, 0x10, 0x62, 0x61, 0x64, 0x20, 0x6d, 0x6f, + 0x64, 0x65, 0x01, 0x16, 0x62, 0x61, 0x64, 0x20, + 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x01, + 0x18, 0x62, 0x61, 0x64, 0x20, 0x69, 0x74, 0x65, + 0x72, 0x61, 0x74, 0x6f, 0x72, 0x0c, 0x00, 0x02, + 0x00, 0xa8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x04, 0x01, 0xaa, 0x01, 0x00, 0x00, + 0x00, 0x0c, 0x43, 0x02, 0x00, 0x00, 0x05, 0x03, + 0x05, 0x01, 0x08, 0x00, 0x04, 0x0c, 0x08, 0xe4, + 0x03, 0x00, 0x01, 0x40, 0x07, 0xb8, 0x03, 0x00, + 0x01, 0x40, 0x03, 0xb4, 0x03, 0x00, 0x01, 0x40, + 0x00, 0xe6, 0x03, 0x00, 0x01, 0x40, 0x01, 0xe8, + 0x03, 0x00, 0x01, 0x40, 0x06, 0xea, 0x03, 0x00, + 0x00, 0x40, 0x05, 0xec, 0x03, 0x00, 0x01, 0x40, + 0x02, 0xee, 0x03, 0x00, 0x02, 0x40, 0x04, 0x0c, + 0x43, 0x02, 0x00, 0xea, 0x03, 0x02, 0x00, 0x02, + 0x03, 0x00, 0x01, 0x00, 0x17, 0x02, 0xf0, 0x03, + 0x00, 0x01, 0x00, 0xf2, 0x03, 0x00, 0x01, 0x00, + 0xb4, 0x03, 0x02, 0x01, 0xd7, 0x96, 0x04, 0x4d, + 0x00, 0x00, 0x00, 0xad, 0xf0, 0x07, 0xd7, 0x07, + 0xae, 0xf0, 0x02, 0x29, 0xe3, 0x11, 0xd8, 0x21, + 0x01, 0x00, 0x30, 0x0c, 0x43, 0x02, 0x00, 0xec, + 0x03, 0x01, 0x02, 0x01, 0x04, 0x00, 0x01, 0x00, + 0x2e, 0x03, 0xf4, 0x03, 0x00, 0x01, 0x00, 0xf6, + 0x03, 0x02, 0x00, 0x20, 0xf8, 0x03, 0x05, 0x00, + 0x03, 0xe6, 0x03, 0x03, 0x01, 0x6b, 0x23, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0xd7, 0x95, 0xf0, + 0x04, 0x06, 0x6e, 0x28, 0xd7, 0x40, 0x06, 0x00, + 0x00, 0x00, 0xcf, 0x61, 0x00, 0x00, 0xf0, 0x08, + 0xe3, 0xd7, 0x61, 0x00, 0x00, 0xf6, 0x0e, 0x0e, + 0x29, 0xd0, 0x6b, 0x07, 0x00, 0x00, 0x00, 0xcc, + 0x6e, 0x28, 0x30, 0x0c, 0x43, 0x02, 0x00, 0xee, + 0x03, 0x02, 0x04, 0x02, 0x03, 0x00, 0x01, 0x00, + 0x55, 0x06, 0xfa, 0x03, 0x00, 0x01, 0x00, 0xfc, + 0x03, 0x00, 0x01, 0x00, 0xfe, 0x03, 0x01, 0x00, + 0x20, 0x80, 0x04, 0x02, 0x01, 0x20, 0xf4, 0x03, + 0x03, 0x02, 0x20, 0xf8, 0x03, 0x03, 0x03, 0x20, + 0xec, 0x03, 0x01, 0x00, 0x60, 0x00, 0x00, 0x38, + 0x49, 0x00, 0x00, 0x00, 0xcf, 0x60, 0x01, 0x00, + 0xd8, 0xd0, 0x61, 0x01, 0x00, 0x8f, 0x62, 0x01, + 0x00, 0xba, 0xa7, 0xf0, 0x39, 0x60, 0x03, 0x00, + 0x60, 0x02, 0x00, 0xd7, 0x61, 0x01, 0x00, 0x46, + 0xd1, 0xd7, 0x61, 0x01, 0x00, 0x1b, 0x11, 0xaf, + 0xf1, 0x04, 0x1b, 0x71, 0x1b, 0x1b, 0x38, 0x49, + 0x00, 0x00, 0x00, 0x1b, 0x71, 0x1b, 0x48, 0xe3, + 0x61, 0x02, 0x00, 0xf5, 0xd2, 0x61, 0x00, 0x00, + 0x95, 0xf0, 0xc8, 0x61, 0x03, 0x00, 0x11, 0x62, + 0x00, 0x00, 0x0e, 0xf2, 0xbe, 0x61, 0x00, 0x00, + 0x28, 0x0c, 0x41, 0x02, 0x00, 0xb8, 0x02, 0x02, + 0x1a, 0x01, 0x05, 0x07, 0x08, 0x02, 0x8a, 0x06, + 0x1c, 0x82, 0x04, 0x00, 0x01, 0x00, 0x84, 0x04, + 0x00, 0x01, 0x00, 0x82, 0x04, 0x01, 0xff, 0xff, + 0xff, 0xff, 0x0f, 0x20, 0x84, 0x04, 0x01, 0x01, + 0x20, 0x86, 0x04, 0x02, 0x00, 0x60, 0x03, 0x88, + 0x04, 0x02, 0x03, 0x20, 0x8a, 0x04, 0x02, 0x04, + 0x60, 0x04, 0xfa, 0x03, 0x02, 0x05, 0x60, 0x02, + 0x8c, 0x04, 0x02, 0x06, 0x60, 0x05, 0xfc, 0x03, + 0x02, 0x07, 0x60, 0x01, 0x8e, 0x04, 0x02, 0x08, + 0x20, 0x90, 0x04, 0x02, 0x09, 0x20, 0xe4, 0x01, + 0x09, 0x1a, 0x20, 0x92, 0x04, 0x0b, 0x0b, 0x20, + 0xf8, 0x03, 0x0d, 0x0f, 0x03, 0xf4, 0x03, 0x0b, + 0x0c, 0x20, 0xf6, 0x03, 0x0b, 0x0e, 0x20, 0xe4, + 0x01, 0x13, 0x0b, 0x20, 0x80, 0x04, 0x13, 0x10, + 0x20, 0xe2, 0x01, 0x13, 0x11, 0x20, 0x88, 0x01, + 0x15, 0x16, 0x20, 0x92, 0x04, 0x16, 0x13, 0x20, + 0xf8, 0x03, 0x17, 0x13, 0x03, 0x94, 0x04, 0x13, + 0x12, 0x20, 0xfe, 0x03, 0x1c, 0x16, 0x20, 0xf8, + 0x03, 0x1f, 0x1a, 0x03, 0x96, 0x04, 0x02, 0x0a, + 0x60, 0x00, 0x98, 0x04, 0x02, 0x19, 0x60, 0x06, + 0xb4, 0x03, 0x02, 0x01, 0xb8, 0x03, 0x01, 0x01, + 0xe6, 0x03, 0x03, 0x01, 0xee, 0x03, 0x02, 0x00, + 0xea, 0x03, 0x00, 0x00, 0xe8, 0x03, 0x04, 0x01, + 0xec, 0x03, 0x01, 0x00, 0xe4, 0x03, 0x00, 0x01, + 0x0c, 0x42, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x05, 0x00, 0x0b, 0x00, 0xec, 0x04, 0x08, 0x9a, + 0x04, 0x01, 0x00, 0x20, 0xe6, 0x01, 0x01, 0x01, + 0x20, 0x9c, 0x04, 0x01, 0x02, 0x20, 0x80, 0x04, + 0x03, 0x03, 0x20, 0xf4, 0x03, 0x04, 0x04, 0x20, + 0x9e, 0x04, 0x04, 0x05, 0x20, 0xf8, 0x03, 0x09, + 0x06, 0x03, 0xfe, 0x03, 0x10, 0x06, 0x20, 0x96, + 0x04, 0x18, 0x10, 0xb4, 0x03, 0x00, 0x02, 0xb8, + 0x03, 0x01, 0x02, 0xfc, 0x03, 0x07, 0x10, 0xfa, + 0x03, 0x05, 0x10, 0x86, 0x04, 0x02, 0x10, 0x8a, + 0x04, 0x04, 0x10, 0xe6, 0x03, 0x02, 0x02, 0x8c, + 0x04, 0x06, 0x10, 0x98, 0x04, 0x19, 0x10, 0xee, + 0x03, 0x03, 0x02, 0x60, 0x02, 0x00, 0x60, 0x01, + 0x00, 0x60, 0x00, 0x00, 0x64, 0x00, 0x00, 0x11, + 0xba, 0xad, 0xf1, 0x06, 0x11, 0xbb, 0xad, 0xf0, + 0x09, 0xbc, 0x11, 0x65, 0x00, 0x00, 0x0e, 0xf2, + 0x33, 0x11, 0xbc, 0xad, 0xf0, 0x0c, 0xe4, 0x11, + 0x04, 0x10, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, + 0x30, 0x11, 0xbd, 0xad, 0xf0, 0x13, 0x0b, 0x38, + 0x49, 0x00, 0x00, 0x00, 0x4b, 0x44, 0x00, 0x00, + 0x00, 0x0a, 0x4b, 0x71, 0x00, 0x00, 0x00, 0x28, + 0xe5, 0x11, 0x04, 0x11, 0x01, 0x00, 0x00, 0x21, + 0x01, 0x00, 0x30, 0x0e, 0xba, 0xcf, 0xba, 0xd0, + 0x26, 0x00, 0x00, 0xd1, 0x60, 0x03, 0x00, 0xba, + 0xd2, 0x61, 0x03, 0x00, 0x64, 0x03, 0x00, 0xa5, + 0x68, 0xd1, 0x01, 0x00, 0x00, 0x60, 0x05, 0x00, + 0x60, 0x04, 0x00, 0x64, 0x04, 0x00, 0x61, 0x03, + 0x00, 0x46, 0xc8, 0x04, 0x61, 0x04, 0x00, 0x95, + 0xf0, 0x34, 0x64, 0x05, 0x00, 0x04, 0x12, 0x01, + 0x00, 0x00, 0xae, 0xf0, 0x0c, 0xe5, 0x11, 0x04, + 0x11, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, 0x30, + 0x61, 0x02, 0x00, 0x61, 0x03, 0x00, 0x1b, 0x11, + 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, 0x1b, 0x64, + 0x06, 0x00, 0x61, 0x03, 0x00, 0x46, 0x1b, 0x71, + 0x1b, 0x48, 0xf3, 0x7c, 0x01, 0x06, 0xc8, 0x05, + 0x6b, 0x1a, 0x00, 0x00, 0x00, 0x5d, 0x07, 0x00, + 0x61, 0x04, 0x00, 0x64, 0x08, 0x00, 0x61, 0x03, + 0x00, 0x46, 0xf6, 0x11, 0x62, 0x05, 0x00, 0x0e, + 0x0e, 0xf2, 0x35, 0xc8, 0x06, 0x6b, 0x30, 0x00, + 0x00, 0x00, 0xba, 0x11, 0x65, 0x09, 0x00, 0x0e, + 0x64, 0x04, 0x00, 0x61, 0x03, 0x00, 0x1b, 0x11, + 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, 0x1b, 0x38, + 0x49, 0x00, 0x00, 0x00, 0x1b, 0x71, 0x1b, 0x48, + 0x5d, 0x0a, 0x00, 0x64, 0x04, 0x00, 0x64, 0x03, + 0x00, 0xf6, 0x0e, 0xc7, 0x06, 0x30, 0x30, 0x61, + 0x05, 0x00, 0x40, 0x71, 0x00, 0x00, 0x00, 0x95, + 0xf0, 0x4f, 0x64, 0x05, 0x00, 0x04, 0x13, 0x01, + 0x00, 0x00, 0xad, 0xf0, 0x1e, 0x61, 0x00, 0x00, + 0xba, 0xa7, 0xf0, 0x17, 0x5d, 0x0a, 0x00, 0x64, + 0x04, 0x00, 0x64, 0x03, 0x00, 0xf6, 0x0e, 0xe4, + 0x11, 0x04, 0x14, 0x01, 0x00, 0x00, 0x21, 0x01, + 0x00, 0x30, 0x61, 0x02, 0x00, 0x61, 0x03, 0x00, + 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, + 0x1b, 0x61, 0x05, 0x00, 0x40, 0x44, 0x00, 0x00, + 0x00, 0x1b, 0x71, 0x1b, 0x48, 0x61, 0x01, 0x00, + 0x90, 0x62, 0x01, 0x00, 0x0e, 0xf3, 0xd1, 0x00, + 0x64, 0x09, 0x00, 0x8f, 0x65, 0x09, 0x00, 0x0e, + 0x61, 0x00, 0x00, 0x90, 0x62, 0x00, 0x00, 0x0e, + 0x64, 0x04, 0x00, 0x61, 0x03, 0x00, 0x1b, 0x11, + 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, 0x1b, 0x38, + 0x49, 0x00, 0x00, 0x00, 0x1b, 0x71, 0x1b, 0x48, + 0x64, 0x05, 0x00, 0x60, 0x07, 0x00, 0x11, 0x04, + 0x15, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x2e, 0x5d, + 0x0a, 0x00, 0x64, 0x04, 0x00, 0x64, 0x03, 0x00, + 0xf6, 0xc8, 0x07, 0x61, 0x07, 0x00, 0xf0, 0x05, + 0x61, 0x07, 0x00, 0x30, 0xbd, 0x11, 0x65, 0x00, + 0x00, 0x0e, 0x0b, 0x38, 0x49, 0x00, 0x00, 0x00, + 0x4b, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x71, + 0x00, 0x00, 0x00, 0x28, 0x11, 0x04, 0x12, 0x01, + 0x00, 0x00, 0xad, 0xf0, 0x3c, 0x64, 0x09, 0x00, + 0xbb, 0xa5, 0xf0, 0x19, 0xbd, 0x11, 0x65, 0x00, + 0x00, 0x0e, 0x0b, 0x38, 0x49, 0x00, 0x00, 0x00, + 0x4b, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x71, + 0x00, 0x00, 0x00, 0x28, 0x61, 0x02, 0x00, 0x61, + 0x03, 0x00, 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, + 0x71, 0x1b, 0x1b, 0x64, 0x06, 0x00, 0x61, 0x03, + 0x00, 0x46, 0x1b, 0x71, 0x1b, 0x48, 0xf2, 0x27, + 0x11, 0x04, 0x13, 0x01, 0x00, 0x00, 0xad, 0xf0, + 0x1e, 0x61, 0x01, 0x00, 0xba, 0xa7, 0xf0, 0x17, + 0x5d, 0x0a, 0x00, 0x64, 0x04, 0x00, 0x64, 0x03, + 0x00, 0xf6, 0x0e, 0xe4, 0x11, 0x04, 0x14, 0x01, + 0x00, 0x00, 0x21, 0x01, 0x00, 0x30, 0x0e, 0x61, + 0x03, 0x00, 0x90, 0x62, 0x03, 0x00, 0x0e, 0xf3, + 0x29, 0xfe, 0x61, 0x01, 0x00, 0xba, 0xad, 0xf0, + 0x19, 0xbd, 0x11, 0x65, 0x00, 0x00, 0x0e, 0x0b, + 0x38, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x44, 0x00, + 0x00, 0x00, 0x0a, 0x4b, 0x71, 0x00, 0x00, 0x00, + 0x28, 0xbb, 0x11, 0x65, 0x00, 0x00, 0x0e, 0x0b, + 0x61, 0x02, 0x00, 0x4b, 0x44, 0x00, 0x00, 0x00, + 0x09, 0x4b, 0x71, 0x00, 0x00, 0x00, 0x28, 0x0c, + 0x42, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, + 0x00, 0x06, 0x00, 0x88, 0x01, 0x01, 0xfe, 0x03, + 0x01, 0x00, 0x20, 0x96, 0x04, 0x18, 0x10, 0xb4, + 0x03, 0x00, 0x02, 0xb8, 0x03, 0x01, 0x02, 0xee, + 0x03, 0x03, 0x02, 0xfa, 0x03, 0x05, 0x10, 0xfc, + 0x03, 0x07, 0x10, 0x60, 0x00, 0x00, 0x64, 0x00, + 0x00, 0x11, 0xba, 0xad, 0xf0, 0x09, 0xbd, 0x11, + 0x65, 0x00, 0x00, 0x0e, 0xf2, 0x4b, 0x11, 0xbb, + 0xad, 0xf0, 0x09, 0xbc, 0x11, 0x65, 0x00, 0x00, + 0x0e, 0xf2, 0x3e, 0x11, 0xbc, 0xad, 0xf0, 0x0c, + 0xe4, 0x11, 0x04, 0x10, 0x01, 0x00, 0x00, 0x21, + 0x01, 0x00, 0x30, 0x11, 0xbd, 0xad, 0xf0, 0x13, + 0x0b, 0x38, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x44, + 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x71, 0x00, 0x00, + 0x00, 0x28, 0xe5, 0x11, 0x04, 0x16, 0x01, 0x00, + 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, + 0x00, 0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x30, + 0x0e, 0xe6, 0x64, 0x04, 0x00, 0x64, 0x05, 0x00, + 0xf6, 0xcf, 0x61, 0x00, 0x00, 0xf0, 0x05, 0x61, + 0x00, 0x00, 0x30, 0xbd, 0x11, 0x65, 0x00, 0x00, + 0x0e, 0x0b, 0x38, 0x49, 0x00, 0x00, 0x00, 0x4b, + 0x44, 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x71, 0x00, + 0x00, 0x00, 0x28, 0x60, 0x01, 0x00, 0x60, 0x00, + 0x00, 0xd7, 0xcf, 0xd8, 0x11, 0xf8, 0xf0, 0x08, + 0x0e, 0x38, 0x49, 0x00, 0x00, 0x00, 0xe0, 0xd0, + 0x60, 0x19, 0x00, 0x60, 0x18, 0x00, 0x60, 0x09, + 0x00, 0x60, 0x08, 0x00, 0x60, 0x07, 0x00, 0x60, + 0x06, 0x00, 0x60, 0x05, 0x00, 0x60, 0x04, 0x00, + 0x60, 0x03, 0x00, 0x60, 0x02, 0x00, 0x5d, 0x04, + 0x00, 0xd7, 0x04, 0x17, 0x01, 0x00, 0x00, 0xf6, + 0x0e, 0xd8, 0x38, 0x49, 0x00, 0x00, 0x00, 0xad, + 0xf0, 0x06, 0x0c, 0x07, 0xdc, 0xf2, 0x0c, 0x5d, + 0x04, 0x00, 0xd8, 0x04, 0x18, 0x01, 0x00, 0x00, + 0xf6, 0x0e, 0xd8, 0x40, 0x03, 0x01, 0x00, 0x00, + 0xd1, 0x61, 0x02, 0x00, 0x38, 0x49, 0x00, 0x00, + 0x00, 0xad, 0xf0, 0x0b, 0x04, 0x15, 0x01, 0x00, + 0x00, 0x11, 0x62, 0x02, 0x00, 0x0e, 0x61, 0x02, + 0x00, 0x04, 0x13, 0x01, 0x00, 0x00, 0xad, 0x11, + 0xf1, 0x18, 0x0e, 0x61, 0x02, 0x00, 0x04, 0x12, + 0x01, 0x00, 0x00, 0xad, 0x11, 0xf1, 0x0b, 0x0e, + 0x61, 0x02, 0x00, 0x04, 0x15, 0x01, 0x00, 0x00, + 0xad, 0x95, 0xf0, 0x0c, 0xe3, 0x11, 0x04, 0x19, + 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, 0x30, 0x38, + 0x49, 0x00, 0x00, 0x00, 0xd2, 0x61, 0x02, 0x00, + 0x04, 0x12, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x24, + 0xd8, 0x40, 0x04, 0x01, 0x00, 0x00, 0x11, 0x62, + 0x03, 0x00, 0x0e, 0x61, 0x03, 0x00, 0x38, 0x49, + 0x00, 0x00, 0x00, 0xae, 0xf0, 0x0e, 0x5d, 0x04, + 0x00, 0x61, 0x03, 0x00, 0x04, 0x1a, 0x01, 0x00, + 0x00, 0xf6, 0x0e, 0x26, 0x00, 0x00, 0xc8, 0x04, + 0x26, 0x00, 0x00, 0xc8, 0x05, 0x26, 0x00, 0x00, + 0xc8, 0x06, 0xba, 0xc8, 0x07, 0x38, 0x49, 0x00, + 0x00, 0x00, 0xc8, 0x08, 0xd7, 0x5d, 0x05, 0x00, + 0x47, 0x24, 0x00, 0x00, 0xc8, 0x09, 0x6b, 0xcc, + 0x01, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x61, 0x09, + 0x00, 0x40, 0x72, 0x00, 0x00, 0x00, 0xc8, 0x0a, + 0x60, 0x0e, 0x00, 0x60, 0x0d, 0x00, 0x60, 0x0b, + 0x00, 0x06, 0xc8, 0x0b, 0x6b, 0x14, 0x00, 0x00, + 0x00, 0xe5, 0x61, 0x09, 0x00, 0x61, 0x0a, 0x00, + 0xf6, 0x11, 0x62, 0x0b, 0x00, 0x0e, 0x0e, 0xf2, + 0x16, 0xc8, 0x0c, 0x6b, 0x11, 0x00, 0x00, 0x00, + 0x38, 0x49, 0x00, 0x00, 0x00, 0x11, 0x62, 0x09, + 0x00, 0x0e, 0xc7, 0x0c, 0x30, 0x30, 0x61, 0x0b, + 0x00, 0x40, 0x71, 0x00, 0x00, 0x00, 0xf1, 0x6f, + 0x61, 0x0b, 0x00, 0x40, 0x44, 0x00, 0x00, 0x00, + 0xc8, 0x0d, 0x5d, 0x04, 0x00, 0x61, 0x0d, 0x00, + 0x04, 0x1b, 0x01, 0x00, 0x00, 0xf6, 0x0e, 0x61, + 0x0d, 0x00, 0x5d, 0x05, 0x00, 0x46, 0xc8, 0x0e, + 0x61, 0x0e, 0x00, 0xf0, 0x0e, 0xe5, 0x61, 0x0d, + 0x00, 0x61, 0x0e, 0x00, 0xf6, 0x11, 0x62, 0x0d, + 0x00, 0x0e, 0x61, 0x05, 0x00, 0x61, 0x07, 0x00, + 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, + 0x1b, 0x61, 0x0d, 0x00, 0x1b, 0x71, 0x1b, 0x48, + 0x61, 0x06, 0x00, 0x61, 0x07, 0x00, 0x1b, 0x11, + 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, 0x1b, 0x61, + 0x0d, 0x00, 0x40, 0x72, 0x00, 0x00, 0x00, 0x1b, + 0x71, 0x1b, 0x48, 0x61, 0x07, 0x00, 0x90, 0x62, + 0x07, 0x00, 0x0e, 0xf3, 0x54, 0xff, 0x38, 0x49, + 0x00, 0x00, 0x00, 0x11, 0x62, 0x09, 0x00, 0x0e, + 0x61, 0x03, 0x00, 0x68, 0xfc, 0x00, 0x00, 0x00, + 0x60, 0x15, 0x00, 0x60, 0x11, 0x00, 0x60, 0x10, + 0x00, 0x60, 0x0f, 0x00, 0x61, 0x03, 0x00, 0x5d, + 0x05, 0x00, 0x47, 0x24, 0x00, 0x00, 0x11, 0x62, + 0x08, 0x00, 0x0e, 0x61, 0x08, 0x00, 0x40, 0x72, + 0x00, 0x00, 0x00, 0xc8, 0x0f, 0xba, 0xc8, 0x10, + 0x09, 0xc8, 0x11, 0x61, 0x10, 0x00, 0x61, 0x07, + 0x00, 0xa5, 0xf0, 0x70, 0x60, 0x12, 0x00, 0x06, + 0xc8, 0x12, 0x6b, 0x2e, 0x00, 0x00, 0x00, 0x60, + 0x13, 0x00, 0xe5, 0x61, 0x08, 0x00, 0x61, 0x0f, + 0x00, 0xf6, 0xc8, 0x13, 0x61, 0x13, 0x00, 0x40, + 0x71, 0x00, 0x00, 0x00, 0x11, 0x62, 0x11, 0x00, + 0x0e, 0x61, 0x13, 0x00, 0x40, 0x44, 0x00, 0x00, + 0x00, 0x11, 0x62, 0x12, 0x00, 0x0e, 0x0e, 0xf2, + 0x16, 0xc8, 0x14, 0x6b, 0x11, 0x00, 0x00, 0x00, + 0x38, 0x49, 0x00, 0x00, 0x00, 0x11, 0x62, 0x08, + 0x00, 0x0e, 0xc7, 0x14, 0x30, 0x30, 0x61, 0x11, + 0x00, 0xf1, 0x21, 0x61, 0x04, 0x00, 0x61, 0x10, + 0x00, 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, + 0x1b, 0x1b, 0x61, 0x12, 0x00, 0x1b, 0x71, 0x1b, + 0x48, 0x61, 0x10, 0x00, 0x90, 0x62, 0x10, 0x00, + 0x0e, 0xf2, 0x89, 0x61, 0x08, 0x00, 0xc8, 0x15, + 0x38, 0x49, 0x00, 0x00, 0x00, 0x11, 0x62, 0x08, + 0x00, 0x0e, 0x61, 0x11, 0x00, 0x95, 0xf0, 0x16, + 0x60, 0x16, 0x00, 0x5d, 0x06, 0x00, 0x61, 0x15, + 0x00, 0xf5, 0xc8, 0x16, 0x61, 0x16, 0x00, 0xf0, + 0x05, 0x61, 0x16, 0x00, 0x30, 0x61, 0x10, 0x00, + 0x61, 0x07, 0x00, 0xa5, 0xf0, 0x23, 0x61, 0x04, + 0x00, 0x61, 0x10, 0x00, 0x1b, 0x11, 0xaf, 0xf1, + 0x04, 0x1b, 0x71, 0x1b, 0x1b, 0x38, 0x49, 0x00, + 0x00, 0x00, 0x1b, 0x71, 0x1b, 0x48, 0x61, 0x10, + 0x00, 0x90, 0x62, 0x10, 0x00, 0x0e, 0xf2, 0xd6, + 0x0e, 0xf2, 0x25, 0xc8, 0x17, 0x6b, 0x20, 0x00, + 0x00, 0x00, 0xe6, 0x61, 0x05, 0x00, 0x61, 0x07, + 0x00, 0xf6, 0x0e, 0x5d, 0x06, 0x00, 0x61, 0x09, + 0x00, 0xf5, 0x0e, 0x5d, 0x06, 0x00, 0x61, 0x08, + 0x00, 0xf5, 0x0e, 0xc7, 0x17, 0x30, 0x30, 0xba, + 0xc8, 0x18, 0x61, 0x07, 0x00, 0xc8, 0x19, 0x0b, + 0x5d, 0x07, 0x00, 0x4e, 0xc5, 0x00, 0x53, 0x72, + 0x00, 0x00, 0x00, 0x04, 0xc5, 0x01, 0x53, 0x06, + 0x00, 0x00, 0x00, 0x04, 0x28, 0xc5, 0x00, 0xcf, + 0xc5, 0x01, 0xd0, 0xc5, 0x02, 0xd1, 0xc5, 0x03, + 0x28, 0xc5, 0x00, 0xd3, 0x28, +}; + diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-iterator-zip.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-iterator-zip.js new file mode 100755 index 00000000..8d2707e7 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/builtin-iterator-zip.js @@ -0,0 +1,210 @@ +;(function(IteratorHelper, InternalError, TypeError, call, Symbol·iterator) { + function check(v, s) { + if (typeof v === "object" && v !== null) return + throw new TypeError(s) + } + function close(iter) { + try { + if (!iter) return + let method = iter.return + if (method) call(iter, method) + } catch (e) { + return e + } + } + function closeall(iters, count) { + let ex = undefined + for (let i = count; i-- > 0;) { + let iter = iters[i] + iters[i] = undefined + let e = close(iter) + if (!ex) ex = e + } + return ex + } + return function zip(iterables, options = undefined) { + check(iterables, "bad iterables") + if (options === undefined) options = {__proto__: null} + else check(options, "bad options") + let mode = options.mode + if (mode === undefined) mode = "shortest" + if (!(mode === "strict" || mode === "longest" || mode === "shortest")) + throw new TypeError("bad mode") + let padding = undefined + if (mode === "longest") { + padding = options.padding + if (padding !== undefined) check(padding, "bad padding") + } + let pads = [] + let iters = [] + let nexts = [] + let count = 0 + let paddingiter = undefined + let iterablesiter = iterables[Symbol·iterator]() + try { + let next = iterablesiter.next + for (;;) { + let item + try { + item = call(iterablesiter, next) + } catch (e) { + // *don't* close |iterablesiter| when .next() throws + iterablesiter = undefined + throw e + } + // order of .done and .value property + // access is observable and matters + if (item.done) break + let iter = item.value + check(iter, "bad iterator") + let method = iter[Symbol·iterator] + if (method) iter = call(iter, method) // iterable -> iterator + iters[count] = iter + nexts[count] = iter.next + count++ + } + iterablesiter = undefined + if (padding) { + paddingiter = padding[Symbol·iterator]() + let next = paddingiter.next + let i = 0 + let done = false + for (; i < count; i++) { + let value + try { + let item = call(paddingiter, next) + // order of .done and .value property + // access is observable and matters + done = item.done + value = item.value + } catch (e) { + // *don't* close |paddingiter| when .next() + // or .done or .value property access throws + paddingiter = undefined + throw e + } + if (done) break + pads[i] = value + } + // have to be careful to not double-close on exception + // exceptions from .return() should still bubble up though + let t = paddingiter + paddingiter = undefined + if (!done) { + let ex = close(t) + if (ex) throw ex + } + for (; i < count; i++) pads[i] = undefined + } + } catch (e) { + closeall(iters, count) + close(iterablesiter) + close(paddingiter) + throw e + } + // note: uses plain numbers for |state|, using + // constants grows the bytecode by about 200 bytes + let state = 0 // new, suspend, execute, complete + let alive = count + return { + __proto__: IteratorHelper, + // TODO(bnoordhuis) shows up as "at next (:0:1)" in stack + // traces when iterator throws, should be "at next (native)" + next() { + switch (state) { + case 0: // new + case 1: // suspend + state = 2 // execute + break + case 2: // execute + throw new TypeError("running zipper") + case 3: // complete + return {value:undefined, done:true} + default: + throw new InternalError("bug") + } + let dones = 0 + let values = 0 + let results = [] + for (let i = 0; i < count; i++) { + let iter = iters[i] + if (!iter) { + if (mode !== "longest") throw new InternalError("bug") + results[i] = pads[i] + continue + } + let result + try { + result = call(iter, nexts[i]) + } catch (e) { + alive = 0 + iters[i] = undefined + closeall(iters, count) + throw e + } + // order of .done and .value property + // access is observable and matters + if (!result.done) { + if (mode === "strict" && dones > 0) { + closeall(iters, count) + throw new TypeError("mismatched inputs") + } + results[i] = result.value + values++ + continue + } + alive-- + dones++ + iters[i] = undefined + switch (mode) { + case "shortest": + let ex = closeall(iters, count) + if (ex) throw ex + state = 3 // complete + return {value:undefined, done:true} + case "longest": + if (alive < 1) { + state = 3 // complete + return {value:undefined, done:true} + } + results[i] = pads[i] + break + case "strict": + if (values > 0) { + closeall(iters, count) + throw new TypeError("mismatched inputs") + } + break + } + } + if (values === 0) { + state = 3 // complete + return {value:undefined, done:true} + } + state = 1 // suspend + return {value:results, done:false} + }, + return() { + switch (state) { + case 0: // new + state = 3 // complete + break + case 1: // suspend + state = 2 // execute + break + case 2: // execute + throw new TypeError("running zipper") + case 3: // complete + return {value:undefined, done:true} + default: + throw new InternalError(`bug: state=${state}`) + } + // TODO skip when already closed because of earlier exception + let ex = closeall(iters, count) + if (ex) throw ex + state = 3 // complete + return {value:undefined, done:true} + }, + } + } +}) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/cutils.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/cutils.c deleted file mode 100755 index 7d36ddfd..00000000 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/cutils.c +++ /dev/null @@ -1,1342 +0,0 @@ -/* - * C utilities - * - * Copyright (c) 2017 Fabrice Bellard - * Copyright (c) 2018 Charlie Gordon - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#if !defined(_MSC_VER) -#include -#endif -#if defined(_WIN32) -#include -#include // _beginthread -#endif -#if defined(__APPLE__) -#include -#endif - -#include "cutils.h" - -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - -#ifdef __GNUC__ -#pragma GCC visibility push(default) -#endif - -void js__pstrcpy(char *buf, int buf_size, const char *str) -{ - int c; - char *q = buf; - - if (buf_size <= 0) - return; - - for(;;) { - c = *str++; - if (c == 0 || q >= buf + buf_size - 1) - break; - *q++ = c; - } - *q = '\0'; -} - -/* strcat and truncate. */ -char *js__pstrcat(char *buf, int buf_size, const char *s) -{ - int len; - len = strlen(buf); - if (len < buf_size) - js__pstrcpy(buf + len, buf_size - len, s); - return buf; -} - -int js__strstart(const char *str, const char *val, const char **ptr) -{ - const char *p, *q; - p = str; - q = val; - while (*q != '\0') { - if (*p != *q) - return 0; - p++; - q++; - } - if (ptr) - *ptr = p; - return 1; -} - -int js__has_suffix(const char *str, const char *suffix) -{ - size_t len = strlen(str); - size_t slen = strlen(suffix); - return (len >= slen && !memcmp(str + len - slen, suffix, slen)); -} - -/* Dynamic buffer package */ - -static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size) -{ - if (unlikely(size == 0)) { - free(ptr); - return NULL; - } - return realloc(ptr, size); -} - -void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func) -{ - memset(s, 0, sizeof(*s)); - if (!realloc_func) - realloc_func = dbuf_default_realloc; - s->opaque = opaque; - s->realloc_func = realloc_func; -} - -void dbuf_init(DynBuf *s) -{ - dbuf_init2(s, NULL, NULL); -} - -/* return < 0 if error */ -int dbuf_realloc(DynBuf *s, size_t new_size) -{ - size_t size; - uint8_t *new_buf; - if (new_size > s->allocated_size) { - if (s->error) - return -1; - size = s->allocated_size * 3 / 2; - if (size > new_size) - new_size = size; - new_buf = s->realloc_func(s->opaque, s->buf, new_size); - if (!new_buf) { - s->error = true; - return -1; - } - s->buf = new_buf; - s->allocated_size = new_size; - } - return 0; -} - -int dbuf_write(DynBuf *s, size_t offset, const void *data, size_t len) -{ - size_t end; - end = offset + len; - if (dbuf_realloc(s, end)) - return -1; - memcpy(s->buf + offset, data, len); - if (end > s->size) - s->size = end; - return 0; -} - -int dbuf_put(DynBuf *s, const void *data, size_t len) -{ - if (unlikely((s->size + len) > s->allocated_size)) { - if (dbuf_realloc(s, s->size + len)) - return -1; - } - if (len > 0) { - memcpy(s->buf + s->size, data, len); - s->size += len; - } - return 0; -} - -int dbuf_put_self(DynBuf *s, size_t offset, size_t len) -{ - if (unlikely((s->size + len) > s->allocated_size)) { - if (dbuf_realloc(s, s->size + len)) - return -1; - } - memcpy(s->buf + s->size, s->buf + offset, len); - s->size += len; - return 0; -} - -int dbuf_putc(DynBuf *s, uint8_t c) -{ - return dbuf_put(s, &c, 1); -} - -int dbuf_putstr(DynBuf *s, const char *str) -{ - return dbuf_put(s, (const uint8_t *)str, strlen(str)); -} - -int JS_PRINTF_FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, JS_PRINTF_FORMAT const char *fmt, ...) -{ - va_list ap; - char buf[128]; - int len; - - va_start(ap, fmt); - len = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - if (len < (int)sizeof(buf)) { - /* fast case */ - return dbuf_put(s, (uint8_t *)buf, len); - } else { - if (dbuf_realloc(s, s->size + len + 1)) - return -1; - va_start(ap, fmt); - vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size, - fmt, ap); - va_end(ap); - s->size += len; - } - return 0; -} - -void dbuf_free(DynBuf *s) -{ - /* we test s->buf as a fail safe to avoid crashing if dbuf_free() - is called twice */ - if (s->buf) { - s->realloc_func(s->opaque, s->buf, 0); - } - memset(s, 0, sizeof(*s)); -} - -/*--- UTF-8 utility functions --*/ - -/* Note: only encode valid codepoints (0x0000..0x10FFFF). - At most UTF8_CHAR_LEN_MAX bytes are output. */ - -/* Compute the number of bytes of the UTF-8 encoding for a codepoint - `c` is a code-point. - Returns the number of bytes. If a codepoint is beyond 0x10FFFF the - return value is 3 as the codepoint would be encoded as 0xFFFD. - */ -size_t utf8_encode_len(uint32_t c) -{ - if (c < 0x80) - return 1; - if (c < 0x800) - return 2; - if (c < 0x10000) - return 3; - if (c < 0x110000) - return 4; - return 3; -} - -/* Encode a codepoint in UTF-8 - `buf` points to an array of at least `UTF8_CHAR_LEN_MAX` bytes - `c` is a code-point. - Returns the number of bytes. If a codepoint is beyond 0x10FFFF the - return value is 3 and the codepoint is encoded as 0xFFFD. - No null byte is stored after the encoded bytes. - Return value is in range 1..4 - */ -size_t utf8_encode(uint8_t buf[minimum_length(UTF8_CHAR_LEN_MAX)], uint32_t c) -{ - if (c < 0x80) { - buf[0] = c; - return 1; - } - if (c < 0x800) { - buf[0] = (c >> 6) | 0xC0; - buf[1] = (c & 0x3F) | 0x80; - return 2; - } - if (c < 0x10000) { - buf[0] = (c >> 12) | 0xE0; - buf[1] = ((c >> 6) & 0x3F) | 0x80; - buf[2] = (c & 0x3F) | 0x80; - return 3; - } - if (c < 0x110000) { - buf[0] = (c >> 18) | 0xF0; - buf[1] = ((c >> 12) & 0x3F) | 0x80; - buf[2] = ((c >> 6) & 0x3F) | 0x80; - buf[3] = (c & 0x3F) | 0x80; - return 4; - } - buf[0] = (0xFFFD >> 12) | 0xE0; - buf[1] = ((0xFFFD >> 6) & 0x3F) | 0x80; - buf[2] = (0xFFFD & 0x3F) | 0x80; - return 3; -} - -/* Decode a single code point from a UTF-8 encoded array of bytes - `p` is a valid pointer to an array of bytes - `pp` is a valid pointer to a `const uint8_t *` to store a pointer - to the byte following the current sequence. - Return the code point at `p`, in the range `0..0x10FFFF` - Return 0xFFFD on error. Only a single byte is consumed in this case - The maximum length for a UTF-8 byte sequence is 4 bytes. - This implements the algorithm specified in whatwg.org, except it accepts - UTF-8 encoded surrogates as JavaScript allows them in strings. - The source string is assumed to have at least UTF8_CHAR_LEN_MAX bytes - or be null terminated. - If `p[0]` is '\0', the return value is `0` and the byte is consumed. - cf: https://encoding.spec.whatwg.org/#utf-8-encoder - */ -uint32_t utf8_decode(const uint8_t *p, const uint8_t **pp) -{ - uint32_t c; - uint8_t lower, upper; - - c = *p++; - if (c < 0x80) { - *pp = p; - return c; - } - switch(c) { - case 0xC2: case 0xC3: - case 0xC4: case 0xC5: case 0xC6: case 0xC7: - case 0xC8: case 0xC9: case 0xCA: case 0xCB: - case 0xCC: case 0xCD: case 0xCE: case 0xCF: - case 0xD0: case 0xD1: case 0xD2: case 0xD3: - case 0xD4: case 0xD5: case 0xD6: case 0xD7: - case 0xD8: case 0xD9: case 0xDA: case 0xDB: - case 0xDC: case 0xDD: case 0xDE: case 0xDF: - if (*p >= 0x80 && *p <= 0xBF) { - *pp = p + 1; - return ((c - 0xC0) << 6) + (*p - 0x80); - } - // otherwise encoding error - break; - case 0xE0: - lower = 0xA0; /* reject invalid encoding */ - goto need2; - case 0xE1: case 0xE2: case 0xE3: - case 0xE4: case 0xE5: case 0xE6: case 0xE7: - case 0xE8: case 0xE9: case 0xEA: case 0xEB: - case 0xEC: case 0xED: case 0xEE: case 0xEF: - lower = 0x80; - need2: - if (*p >= lower && *p <= 0xBF && p[1] >= 0x80 && p[1] <= 0xBF) { - *pp = p + 2; - return ((c - 0xE0) << 12) + ((*p - 0x80) << 6) + (p[1] - 0x80); - } - // otherwise encoding error - break; - case 0xF0: - lower = 0x90; /* reject invalid encoding */ - upper = 0xBF; - goto need3; - case 0xF4: - lower = 0x80; - upper = 0x8F; /* reject values above 0x10FFFF */ - goto need3; - case 0xF1: case 0xF2: case 0xF3: - lower = 0x80; - upper = 0xBF; - need3: - if (*p >= lower && *p <= upper && p[1] >= 0x80 && p[1] <= 0xBF - && p[2] >= 0x80 && p[2] <= 0xBF) { - *pp = p + 3; - return ((c - 0xF0) << 18) + ((*p - 0x80) << 12) + - ((p[1] - 0x80) << 6) + (p[2] - 0x80); - } - // otherwise encoding error - break; - default: - // invalid lead byte - break; - } - *pp = p; - return 0xFFFD; -} - -uint32_t utf8_decode_len(const uint8_t *p, size_t max_len, const uint8_t **pp) { - switch (max_len) { - case 0: - *pp = p; - return 0xFFFD; - case 1: - if (*p < 0x80) - goto good; - break; - case 2: - if (*p < 0xE0) - goto good; - break; - case 3: - if (*p < 0xF0) - goto good; - break; - default: - good: - return utf8_decode(p, pp); - } - *pp = p + 1; - return 0xFFFD; -} - -/* Scan a UTF-8 encoded buffer for content type - `buf` is a valid pointer to a UTF-8 encoded string - `len` is the number of bytes to scan - `plen` points to a `size_t` variable to receive the number of units - Return value is a mask of bits. - - `UTF8_PLAIN_ASCII`: return value for 7-bit ASCII plain text - - `UTF8_NON_ASCII`: bit for non ASCII code points (8-bit or more) - - `UTF8_HAS_16BIT`: bit for 16-bit code points - - `UTF8_HAS_NON_BMP1`: bit for non-BMP1 code points, needs UTF-16 surrogate pairs - - `UTF8_HAS_ERRORS`: bit for encoding errors - */ -int utf8_scan(const char *buf, size_t buf_len, size_t *plen) -{ - const uint8_t *p, *p_end, *p_next; - size_t i, len; - int kind; - uint8_t cbits; - - kind = UTF8_PLAIN_ASCII; - cbits = 0; - len = buf_len; - // TODO: handle more than 1 byte at a time - for (i = 0; i < buf_len; i++) - cbits |= buf[i]; - if (cbits >= 0x80) { - p = (const uint8_t *)buf; - p_end = p + buf_len; - kind = UTF8_NON_ASCII; - len = 0; - while (p < p_end) { - len++; - if (*p++ >= 0x80) { - /* parse UTF-8 sequence, check for encoding error */ - uint32_t c = utf8_decode_len(p - 1, p_end - (p - 1), &p_next); - if (p_next == p) - kind |= UTF8_HAS_ERRORS; - p = p_next; - if (c > 0xFF) { - kind |= UTF8_HAS_16BIT; - if (c > 0xFFFF) { - len++; - kind |= UTF8_HAS_NON_BMP1; - } - } - } - } - } - *plen = len; - return kind; -} - -/* Decode a string encoded in UTF-8 into an array of bytes - `src` points to the source string. It is assumed to be correctly encoded - and only contains code points below 0x800 - `src_len` is the length of the source string - `dest` points to the destination array, it can be null if `dest_len` is `0` - `dest_len` is the length of the destination array. A null - terminator is stored at the end of the array unless `dest_len` is `0`. - */ -size_t utf8_decode_buf8(uint8_t *dest, size_t dest_len, const char *src, size_t src_len) -{ - const uint8_t *p, *p_end; - size_t i; - - p = (const uint8_t *)src; - p_end = p + src_len; - for (i = 0; p < p_end; i++) { - uint32_t c = *p++; - if (c >= 0xC0) - c = (c << 6) + *p++ - ((0xC0 << 6) + 0x80); - if (i < dest_len) - dest[i] = c; - } - if (i < dest_len) - dest[i] = '\0'; - else if (dest_len > 0) - dest[dest_len - 1] = '\0'; - return i; -} - -/* Decode a string encoded in UTF-8 into an array of 16-bit words - `src` points to the source string. It is assumed to be correctly encoded. - `src_len` is the length of the source string - `dest` points to the destination array, it can be null if `dest_len` is `0` - `dest_len` is the length of the destination array. No null terminator is - stored at the end of the array. - */ -size_t utf8_decode_buf16(uint16_t *dest, size_t dest_len, const char *src, size_t src_len) -{ - const uint8_t *p, *p_end; - size_t i; - - p = (const uint8_t *)src; - p_end = p + src_len; - for (i = 0; p < p_end; i++) { - uint32_t c = *p++; - if (c >= 0x80) { - /* parse utf-8 sequence */ - c = utf8_decode_len(p - 1, p_end - (p - 1), &p); - /* encoding errors are converted as 0xFFFD and use a single byte */ - if (c > 0xFFFF) { - if (i < dest_len) - dest[i] = get_hi_surrogate(c); - i++; - c = get_lo_surrogate(c); - } - } - if (i < dest_len) - dest[i] = c; - } - return i; -} - -/* Encode a buffer of 8-bit bytes as a UTF-8 encoded string - `src` points to the source buffer. - `src_len` is the length of the source buffer - `dest` points to the destination array, it can be null if `dest_len` is `0` - `dest_len` is the length in bytes of the destination array. A null - terminator is stored at the end of the array unless `dest_len` is `0`. - */ -size_t utf8_encode_buf8(char *dest, size_t dest_len, const uint8_t *src, size_t src_len) -{ - size_t i, j; - uint32_t c; - - for (i = j = 0; i < src_len; i++) { - c = src[i]; - if (c < 0x80) { - if (j + 1 >= dest_len) - goto overflow; - dest[j++] = c; - } else { - if (j + 2 >= dest_len) - goto overflow; - dest[j++] = (c >> 6) | 0xC0; - dest[j++] = (c & 0x3F) | 0x80; - } - } - if (j < dest_len) - dest[j] = '\0'; - return j; - -overflow: - if (j < dest_len) - dest[j] = '\0'; - while (i < src_len) - j += 1 + (src[i++] >= 0x80); - return j; -} - -/* Encode a buffer of 16-bit code points as a UTF-8 encoded string - `src` points to the source buffer. - `src_len` is the length of the source buffer - `dest` points to the destination array, it can be null if `dest_len` is `0` - `dest_len` is the length in bytes of the destination array. A null - terminator is stored at the end of the array unless `dest_len` is `0`. - */ -size_t utf8_encode_buf16(char *dest, size_t dest_len, const uint16_t *src, size_t src_len) -{ - size_t i, j; - uint32_t c; - - for (i = j = 0; i < src_len;) { - c = src[i++]; - if (c < 0x80) { - if (j + 1 >= dest_len) - goto overflow; - dest[j++] = c; - } else { - if (is_hi_surrogate(c) && i < src_len && is_lo_surrogate(src[i])) - c = from_surrogate(c, src[i++]); - if (j + utf8_encode_len(c) >= dest_len) - goto overflow; - j += utf8_encode((uint8_t *)dest + j, c); - } - } - if (j < dest_len) - dest[j] = '\0'; - return j; - -overflow: - i -= 1 + (c > 0xFFFF); - if (j < dest_len) - dest[j] = '\0'; - while (i < src_len) { - c = src[i++]; - if (c < 0x80) { - j++; - } else { - if (is_hi_surrogate(c) && i < src_len && is_lo_surrogate(src[i])) - c = from_surrogate(c, src[i++]); - j += utf8_encode_len(c); - } - } - return j; -} - -/*---- sorting with opaque argument ----*/ - -typedef void (*exchange_f)(void *a, void *b, size_t size); -typedef int (*cmp_f)(const void *, const void *, void *opaque); - -static void exchange_bytes(void *a, void *b, size_t size) { - uint8_t *ap = (uint8_t *)a; - uint8_t *bp = (uint8_t *)b; - - while (size-- != 0) { - uint8_t t = *ap; - *ap++ = *bp; - *bp++ = t; - } -} - -static void exchange_one_byte(void *a, void *b, size_t size) { - uint8_t *ap = (uint8_t *)a; - uint8_t *bp = (uint8_t *)b; - uint8_t t = *ap; - *ap = *bp; - *bp = t; -} - -static void exchange_int16s(void *a, void *b, size_t size) { - uint16_t *ap = (uint16_t *)a; - uint16_t *bp = (uint16_t *)b; - - for (size /= sizeof(uint16_t); size-- != 0;) { - uint16_t t = *ap; - *ap++ = *bp; - *bp++ = t; - } -} - -static void exchange_one_int16(void *a, void *b, size_t size) { - uint16_t *ap = (uint16_t *)a; - uint16_t *bp = (uint16_t *)b; - uint16_t t = *ap; - *ap = *bp; - *bp = t; -} - -static void exchange_int32s(void *a, void *b, size_t size) { - uint32_t *ap = (uint32_t *)a; - uint32_t *bp = (uint32_t *)b; - - for (size /= sizeof(uint32_t); size-- != 0;) { - uint32_t t = *ap; - *ap++ = *bp; - *bp++ = t; - } -} - -static void exchange_one_int32(void *a, void *b, size_t size) { - uint32_t *ap = (uint32_t *)a; - uint32_t *bp = (uint32_t *)b; - uint32_t t = *ap; - *ap = *bp; - *bp = t; -} - -static void exchange_int64s(void *a, void *b, size_t size) { - uint64_t *ap = (uint64_t *)a; - uint64_t *bp = (uint64_t *)b; - - for (size /= sizeof(uint64_t); size-- != 0;) { - uint64_t t = *ap; - *ap++ = *bp; - *bp++ = t; - } -} - -static void exchange_one_int64(void *a, void *b, size_t size) { - uint64_t *ap = (uint64_t *)a; - uint64_t *bp = (uint64_t *)b; - uint64_t t = *ap; - *ap = *bp; - *bp = t; -} - -static void exchange_int128s(void *a, void *b, size_t size) { - uint64_t *ap = (uint64_t *)a; - uint64_t *bp = (uint64_t *)b; - - for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) { - uint64_t t = ap[0]; - uint64_t u = ap[1]; - ap[0] = bp[0]; - ap[1] = bp[1]; - bp[0] = t; - bp[1] = u; - } -} - -static void exchange_one_int128(void *a, void *b, size_t size) { - uint64_t *ap = (uint64_t *)a; - uint64_t *bp = (uint64_t *)b; - uint64_t t = ap[0]; - uint64_t u = ap[1]; - ap[0] = bp[0]; - ap[1] = bp[1]; - bp[0] = t; - bp[1] = u; -} - -static inline exchange_f exchange_func(const void *base, size_t size) { - switch (((uintptr_t)base | (uintptr_t)size) & 15) { - case 0: - if (size == sizeof(uint64_t) * 2) - return exchange_one_int128; - else - return exchange_int128s; - case 8: - if (size == sizeof(uint64_t)) - return exchange_one_int64; - else - return exchange_int64s; - case 4: - case 12: - if (size == sizeof(uint32_t)) - return exchange_one_int32; - else - return exchange_int32s; - case 2: - case 6: - case 10: - case 14: - if (size == sizeof(uint16_t)) - return exchange_one_int16; - else - return exchange_int16s; - default: - if (size == 1) - return exchange_one_byte; - else - return exchange_bytes; - } -} - -static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) -{ - uint8_t *basep = (uint8_t *)base; - size_t i, n, c, r; - exchange_f swap = exchange_func(base, size); - - if (nmemb > 1) { - i = (nmemb / 2) * size; - n = nmemb * size; - - while (i > 0) { - i -= size; - for (r = i; (c = r * 2 + size) < n; r = c) { - if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0) - c += size; - if (cmp(basep + r, basep + c, opaque) > 0) - break; - swap(basep + r, basep + c, size); - } - } - for (i = n - size; i > 0; i -= size) { - swap(basep, basep + i, size); - - for (r = 0; (c = r * 2 + size) < i; r = c) { - if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0) - c += size; - if (cmp(basep + r, basep + c, opaque) > 0) - break; - swap(basep + r, basep + c, size); - } - } - } -} - -static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque) -{ - return cmp(a, b, opaque) < 0 ? - (cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) : - (cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c )); -} - -/* pointer based version with local stack and insertion sort threshhold */ -void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) -{ - struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack; - uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m; - size_t m4, i, lt, gt, span, span2; - int c, depth; - exchange_f swap = exchange_func(base, size); - exchange_f swap_block = exchange_func(base, size | 128); - - if (nmemb < 2 || size <= 0) - return; - - sp->base = (uint8_t *)base; - sp->count = nmemb; - sp->depth = 0; - sp++; - - while (sp > stack) { - sp--; - ptr = sp->base; - nmemb = sp->count; - depth = sp->depth; - - while (nmemb > 6) { - if (++depth > 50) { - /* depth check to ensure worst case logarithmic time */ - heapsortx(ptr, nmemb, size, cmp, opaque); - nmemb = 0; - break; - } - /* select median of 3 from 1/4, 1/2, 3/4 positions */ - /* should use median of 5 or 9? */ - m4 = (nmemb >> 2) * size; - m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque); - swap(ptr, m, size); /* move the pivot to the start or the array */ - i = lt = 1; - pi = plt = ptr + size; - gt = nmemb; - pj = pgt = top = ptr + nmemb * size; - for (;;) { - while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) { - if (c == 0) { - swap(plt, pi, size); - lt++; - plt += size; - } - i++; - pi += size; - } - while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) { - if (c == 0) { - gt--; - pgt -= size; - swap(pgt, pj, size); - } - } - if (pi >= pj) - break; - swap(pi, pj, size); - i++; - pi += size; - } - /* array has 4 parts: - * from 0 to lt excluded: elements identical to pivot - * from lt to pi excluded: elements smaller than pivot - * from pi to gt excluded: elements greater than pivot - * from gt to n excluded: elements identical to pivot - */ - /* move elements identical to pivot in the middle of the array: */ - /* swap values in ranges [0..lt[ and [i-lt..i[ - swapping the smallest span between lt and i-lt is sufficient - */ - span = plt - ptr; - span2 = pi - plt; - lt = i - lt; - if (span > span2) - span = span2; - swap_block(ptr, pi - span, span); - /* swap values in ranges [gt..top[ and [i..top-(top-gt)[ - swapping the smallest span between top-gt and gt-i is sufficient - */ - span = top - pgt; - span2 = pgt - pi; - pgt = top - span2; - gt = nmemb - (gt - i); - if (span > span2) - span = span2; - swap_block(pi, top - span, span); - - /* now array has 3 parts: - * from 0 to lt excluded: elements smaller than pivot - * from lt to gt excluded: elements identical to pivot - * from gt to n excluded: elements greater than pivot - */ - /* stack the larger segment and keep processing the smaller one - to minimize stack use for pathological distributions */ - if (lt > nmemb - gt) { - sp->base = ptr; - sp->count = lt; - sp->depth = depth; - sp++; - ptr = pgt; - nmemb -= gt; - } else { - sp->base = pgt; - sp->count = nmemb - gt; - sp->depth = depth; - sp++; - nmemb = lt; - } - } - /* Use insertion sort for small fragments */ - for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) { - for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size) - swap(pj, pj - size, size); - } - } -} - -/*---- Portable time functions ----*/ - -#ifdef _WIN32 - // From: https://stackoverflow.com/a/26085827 -static int gettimeofday_msvc(struct timeval *tp) -{ - static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL); - - SYSTEMTIME system_time; - FILETIME file_time; - uint64_t time; - - GetSystemTime(&system_time); - SystemTimeToFileTime(&system_time, &file_time); - time = ((uint64_t)file_time.dwLowDateTime); - time += ((uint64_t)file_time.dwHighDateTime) << 32; - - tp->tv_sec = (long)((time - EPOCH) / 10000000L); - tp->tv_usec = (long)(system_time.wMilliseconds * 1000); - - return 0; -} - -uint64_t js__hrtime_ns(void) { - LARGE_INTEGER counter, frequency; - double scaled_freq; - double result; - - if (!QueryPerformanceFrequency(&frequency)) - abort(); - assert(frequency.QuadPart != 0); - - if (!QueryPerformanceCounter(&counter)) - abort(); - assert(counter.QuadPart != 0); - - /* Because we have no guarantee about the order of magnitude of the - * performance counter interval, integer math could cause this computation - * to overflow. Therefore we resort to floating point math. - */ - scaled_freq = (double) frequency.QuadPart / NANOSEC; - result = (double) counter.QuadPart / scaled_freq; - return (uint64_t) result; -} -#else -uint64_t js__hrtime_ns(void) { - struct timespec t; - - if (clock_gettime(CLOCK_MONOTONIC, &t)) - abort(); - - return t.tv_sec * NANOSEC + t.tv_nsec; -} -#endif - -int64_t js__gettimeofday_us(void) { - struct timeval tv; -#ifdef _WIN32 - gettimeofday_msvc(&tv); -#else - gettimeofday(&tv, NULL); -#endif - return ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec; -} - -#if defined(_WIN32) -int js_exepath(char *buffer, size_t *size_ptr) { - int utf8_len, utf16_buffer_len, utf16_len; - WCHAR* utf16_buffer; - - if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) - return -1; - - if (*size_ptr > 32768) { - /* Windows paths can never be longer than this. */ - utf16_buffer_len = 32768; - } else { - utf16_buffer_len = (int)*size_ptr; - } - - utf16_buffer = malloc(sizeof(WCHAR) * utf16_buffer_len); - if (!utf16_buffer) - return -1; - - /* Get the path as UTF-16. */ - utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len); - if (utf16_len <= 0) - goto error; - - /* Convert to UTF-8 */ - utf8_len = WideCharToMultiByte(CP_UTF8, - 0, - utf16_buffer, - -1, - buffer, - (int)*size_ptr, - NULL, - NULL); - if (utf8_len == 0) - goto error; - - free(utf16_buffer); - - /* utf8_len *does* include the terminating null at this point, but the - * returned size shouldn't. */ - *size_ptr = utf8_len - 1; - return 0; - -error: - free(utf16_buffer); - return -1; -} -#elif defined(__APPLE__) -int js_exepath(char *buffer, size_t *size) { - /* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */ - char abspath[PATH_MAX * 2 + 1]; - char exepath[PATH_MAX + 1]; - uint32_t exepath_size; - size_t abspath_size; - - if (buffer == NULL || size == NULL || *size == 0) - return -1; - - exepath_size = sizeof(exepath); - if (_NSGetExecutablePath(exepath, &exepath_size)) - return -1; - - if (realpath(exepath, abspath) != abspath) - return -1; - - abspath_size = strlen(abspath); - if (abspath_size == 0) - return -1; - - *size -= 1; - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - return 0; -} -#elif defined(__linux__) || defined(__GNU__) -int js_exepath(char *buffer, size_t *size) { - ssize_t n; - - if (buffer == NULL || size == NULL || *size == 0) - return -1; - - n = *size - 1; - if (n > 0) - n = readlink("/proc/self/exe", buffer, n); - - if (n == -1) - return n; - - buffer[n] = '\0'; - *size = n; - - return 0; -} -#else -int js_exepath(char* buffer, size_t* size_ptr) { - return -1; -} -#endif - -/*--- Cross-platform threading APIs. ----*/ - -#if JS_HAVE_THREADS -#if defined(_WIN32) -typedef void (*js__once_cb)(void); - -typedef struct { - js__once_cb callback; -} js__once_data_t; - -static int WINAPI js__once_inner(INIT_ONCE *once, void *param, void **context) { - js__once_data_t *data = param; - - data->callback(); - - return 1; -} - -void js_once(js_once_t *guard, js__once_cb callback) { - js__once_data_t data = { .callback = callback }; - InitOnceExecuteOnce(guard, js__once_inner, (void*) &data, NULL); -} - -void js_mutex_init(js_mutex_t *mutex) { - InitializeCriticalSection(mutex); -} - -void js_mutex_destroy(js_mutex_t *mutex) { - DeleteCriticalSection(mutex); -} - -void js_mutex_lock(js_mutex_t *mutex) { - EnterCriticalSection(mutex); -} - -void js_mutex_unlock(js_mutex_t *mutex) { - LeaveCriticalSection(mutex); -} - -void js_cond_init(js_cond_t *cond) { - InitializeConditionVariable(cond); -} - -void js_cond_destroy(js_cond_t *cond) { - /* nothing to do */ - (void) cond; -} - -void js_cond_signal(js_cond_t *cond) { - WakeConditionVariable(cond); -} - -void js_cond_broadcast(js_cond_t *cond) { - WakeAllConditionVariable(cond); -} - -void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex) { - if (!SleepConditionVariableCS(cond, mutex, INFINITE)) - abort(); -} - -int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) { - if (SleepConditionVariableCS(cond, mutex, (DWORD)(timeout / 1e6))) - return 0; - if (GetLastError() != ERROR_TIMEOUT) - abort(); - return -1; -} - -int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg, - int flags) -{ - HANDLE h, cp; - - *thrd = INVALID_HANDLE_VALUE; - if (flags & ~JS_THREAD_CREATE_DETACHED) - return -1; - h = (HANDLE)_beginthread(start, /*stacksize*/2<<20, arg); - if (!h) - return -1; - if (flags & JS_THREAD_CREATE_DETACHED) - return 0; - // _endthread() automatically closes the handle but we want to wait on - // it so make a copy. Race-y for very short-lived threads. Can be solved - // by switching to _beginthreadex(CREATE_SUSPENDED) but means changing - // |start| from __cdecl to __stdcall. - cp = GetCurrentProcess(); - if (DuplicateHandle(cp, h, cp, thrd, 0, FALSE, DUPLICATE_SAME_ACCESS)) - return 0; - return -1; -} - -int js_thread_join(js_thread_t thrd) -{ - if (WaitForSingleObject(thrd, INFINITE)) - return -1; - CloseHandle(thrd); - return 0; -} - -#else /* !defined(_WIN32) */ - -void js_once(js_once_t *guard, void (*callback)(void)) { - if (pthread_once(guard, callback)) - abort(); -} - -void js_mutex_init(js_mutex_t *mutex) { - if (pthread_mutex_init(mutex, NULL)) - abort(); -} - -void js_mutex_destroy(js_mutex_t *mutex) { - if (pthread_mutex_destroy(mutex)) - abort(); -} - -void js_mutex_lock(js_mutex_t *mutex) { - if (pthread_mutex_lock(mutex)) - abort(); -} - -void js_mutex_unlock(js_mutex_t *mutex) { - if (pthread_mutex_unlock(mutex)) - abort(); -} - -void js_cond_init(js_cond_t *cond) { -#if defined(__APPLE__) && defined(__MACH__) - if (pthread_cond_init(cond, NULL)) - abort(); -#else - pthread_condattr_t attr; - - if (pthread_condattr_init(&attr)) - abort(); - - if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) - abort(); - - if (pthread_cond_init(cond, &attr)) - abort(); - - if (pthread_condattr_destroy(&attr)) - abort(); -#endif -} - -void js_cond_destroy(js_cond_t *cond) { -#if defined(__APPLE__) && defined(__MACH__) - /* It has been reported that destroying condition variables that have been - * signalled but not waited on can sometimes result in application crashes. - * See https://codereview.chromium.org/1323293005. - */ - pthread_mutex_t mutex; - struct timespec ts; - int err; - - if (pthread_mutex_init(&mutex, NULL)) - abort(); - - if (pthread_mutex_lock(&mutex)) - abort(); - - ts.tv_sec = 0; - ts.tv_nsec = 1; - - err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts); - if (err != 0 && err != ETIMEDOUT) - abort(); - - if (pthread_mutex_unlock(&mutex)) - abort(); - - if (pthread_mutex_destroy(&mutex)) - abort(); -#endif /* defined(__APPLE__) && defined(__MACH__) */ - - if (pthread_cond_destroy(cond)) - abort(); -} - -void js_cond_signal(js_cond_t *cond) { - if (pthread_cond_signal(cond)) - abort(); -} - -void js_cond_broadcast(js_cond_t *cond) { - if (pthread_cond_broadcast(cond)) - abort(); -} - -void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex) { -#if defined(__APPLE__) && defined(__MACH__) - int r; - - errno = 0; - r = pthread_cond_wait(cond, mutex); - - /* Workaround for a bug in OS X at least up to 13.6 - * See https://github.com/libuv/libuv/issues/4165 - */ - if (r == EINVAL && errno == EBUSY) - return; - if (r) - abort(); -#else - if (pthread_cond_wait(cond, mutex)) - abort(); -#endif -} - -int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) { - int r; - struct timespec ts; - -#if !defined(__APPLE__) - timeout += js__hrtime_ns(); -#endif - - ts.tv_sec = timeout / NANOSEC; - ts.tv_nsec = timeout % NANOSEC; -#if defined(__APPLE__) && defined(__MACH__) - r = pthread_cond_timedwait_relative_np(cond, mutex, &ts); -#else - r = pthread_cond_timedwait(cond, mutex, &ts); -#endif - - if (r == 0) - return 0; - - if (r == ETIMEDOUT) - return -1; - - abort(); - - /* Pacify some compilers. */ - return -1; -} - -int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg, - int flags) -{ - union { - void (*x)(void *); - void *(*f)(void *); - } u = {start}; - pthread_attr_t attr; - int ret; - - if (flags & ~JS_THREAD_CREATE_DETACHED) - return -1; - if (pthread_attr_init(&attr)) - return -1; - ret = -1; - if (pthread_attr_setstacksize(&attr, 2<<20)) - goto fail; - if (flags & JS_THREAD_CREATE_DETACHED) - if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) - goto fail; - if (pthread_create(thrd, &attr, u.f, arg)) - goto fail; - ret = 0; -fail: - pthread_attr_destroy(&attr); - return ret; -} - -int js_thread_join(js_thread_t thrd) -{ - if (pthread_join(thrd, NULL)) - return -1; - return 0; -} - -#endif /* !defined(_WIN32) */ -#endif /* JS_HAVE_THREADS */ - -#ifdef __GNUC__ -#pragma GCC visibility pop -#endif diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/cutils.h b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/cutils.h index f5d2a8bc..c45009e1 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/cutils.h +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/cutils.h @@ -25,6 +25,16 @@ #ifndef CUTILS_H #define CUTILS_H +#include +#include +#include +#include +#if !defined(_MSC_VER) +#include +#endif +#if defined(__APPLE__) +#include +#endif #include #include #include @@ -36,7 +46,6 @@ extern "C" { #endif #if defined(_MSC_VER) -#include #include #define alloca _alloca #define ssize_t ptrdiff_t @@ -48,9 +57,11 @@ extern "C" { #elif defined(__FreeBSD__) #include #elif defined(_WIN32) +#include #include +#include // _beginthread #endif -#if !defined(_WIN32) && !defined(EMSCRIPTEN) && !defined(__wasi__) +#if !defined(_WIN32) && !defined(EMSCRIPTEN) && !defined(__wasi__) && !defined(__DJGPP) #include #include #endif @@ -59,10 +70,13 @@ extern "C" { #include #endif +#if defined(__sun) +#undef __maybe_unused +#endif + #if defined(_MSC_VER) && !defined(__clang__) # define likely(x) (x) # define unlikely(x) (x) -# define force_inline __forceinline # define no_inline __declspec(noinline) # define __maybe_unused # define __attribute__(x) @@ -70,20 +84,10 @@ extern "C" { #else # define likely(x) __builtin_expect(!!(x), 1) # define unlikely(x) __builtin_expect(!!(x), 0) -# define force_inline inline __attribute__((always_inline)) # define no_inline __attribute__((noinline)) # define __maybe_unused __attribute__((unused)) #endif -#if defined(_MSC_VER) && !defined(__clang__) -#include -#define INF INFINITY -#define NEG_INF -INFINITY -#else -#define INF (1.0/0.0) -#define NEG_INF (-1.0/0.0) -#endif - #ifndef offsetof #define offsetof(type, field) ((size_t) &((type *)0)->field) #endif @@ -106,7 +110,8 @@ extern "C" { /* Borrowed from Folly */ #ifndef JS_PRINTF_FORMAT -#ifdef _MSC_VER +/* Clang on Windows doesn't seem to support _Printf_format_string_ */ +#if defined(_MSC_VER) && !defined(__clang__) #include #define JS_PRINTF_FORMAT _Printf_format_string_ #define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) @@ -130,10 +135,10 @@ extern "C" { # define JS__PATH_MAX 8192 #endif -void js__pstrcpy(char *buf, int buf_size, const char *str); -char *js__pstrcat(char *buf, int buf_size, const char *s); -int js__strstart(const char *str, const char *val, const char **ptr); -int js__has_suffix(const char *str, const char *suffix); +static inline void js__pstrcpy(char *buf, int buf_size, const char *str); +static inline char *js__pstrcat(char *buf, int buf_size, const char *s); +static inline int js__strstart(const char *str, const char *val, const char **ptr); +static inline int js__has_suffix(const char *str, const char *suffix); static inline uint8_t is_be(void) { union { @@ -191,6 +196,16 @@ static inline int64_t min_int64(int64_t a, int64_t b) return b; } +static inline uint32_t hash32(uint32_t a) +{ + // use the negative of the golden ratio, it spreads out the bits nicely + // and is what the linux kernel does + // + // the golden ratio phi is defined as (1+sqrt(5))/2 or 1 + (sqrt(5)-1)/2 + // (approx. 1.618033988), and negated is round(2**32/phi**2) = 0x61c88647 + return a * 0x61c88647; +} + /* WARNING: undefined if a = 0 */ static inline int clz32(unsigned int a) { @@ -347,14 +362,6 @@ static inline uint64_t bswap64(uint64_t v) } #endif -static inline void inplace_bswap16(uint8_t *tab) { - put_u16(tab, bswap16(get_u16(tab))); -} - -static inline void inplace_bswap32(uint8_t *tab) { - put_u32(tab, bswap32(get_u32(tab))); -} - static inline double fromfp16(uint16_t v) { double d, s; int e; @@ -442,28 +449,49 @@ typedef struct DynBuf { void *opaque; /* for realloc_func */ } DynBuf; -void dbuf_init(DynBuf *s); -void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func); -int dbuf_realloc(DynBuf *s, size_t new_size); -int dbuf_write(DynBuf *s, size_t offset, const void *data, size_t len); -int dbuf_put(DynBuf *s, const void *data, size_t len); -int dbuf_put_self(DynBuf *s, size_t offset, size_t len); -int dbuf_putc(DynBuf *s, uint8_t c); -int dbuf_putstr(DynBuf *s, const char *str); +static inline void dbuf_init(DynBuf *s); +static inline void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func); +static inline int dbuf_claim(DynBuf *s, size_t len); +static inline int dbuf_put(DynBuf *s, const void *data, size_t len); +static inline int dbuf_put_self(DynBuf *s, size_t offset, size_t len); +static inline int __dbuf_putc(DynBuf *s, uint8_t c); +static inline int __dbuf_put_u16(DynBuf *s, uint16_t val); +static inline int __dbuf_put_u32(DynBuf *s, uint32_t val); +static inline int __dbuf_put_u64(DynBuf *s, uint64_t val); +static inline int dbuf_putstr(DynBuf *s, const char *str); +static inline int dbuf_putc(DynBuf *s, uint8_t val) +{ + if (unlikely((s->allocated_size - s->size) < 1)) + return __dbuf_putc(s, val); + s->buf[s->size++] = val; + return 0; +} static inline int dbuf_put_u16(DynBuf *s, uint16_t val) { - return dbuf_put(s, (uint8_t *)&val, 2); + if (unlikely((s->allocated_size - s->size) < 2)) + return __dbuf_put_u16(s, val); + put_u16(s->buf + s->size, val); + s->size += 2; + return 0; } static inline int dbuf_put_u32(DynBuf *s, uint32_t val) { - return dbuf_put(s, (uint8_t *)&val, 4); + if (unlikely((s->allocated_size - s->size) < 4)) + return __dbuf_put_u32(s, val); + put_u32(s->buf + s->size, val); + s->size += 4; + return 0; } static inline int dbuf_put_u64(DynBuf *s, uint64_t val) { - return dbuf_put(s, (uint8_t *)&val, 8); + if (unlikely((s->allocated_size - s->size) < 8)) + return __dbuf_put_u64(s, val); + put_u64(s->buf + s->size, val); + s->size += 8; + return 0; } -int JS_PRINTF_FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, JS_PRINTF_FORMAT const char *fmt, ...); -void dbuf_free(DynBuf *s); +static inline int JS_PRINTF_FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, JS_PRINTF_FORMAT const char *fmt, ...); +static inline void dbuf_free(DynBuf *s); static inline bool dbuf_error(DynBuf *s) { return s->error; } @@ -483,15 +511,15 @@ enum { UTF8_HAS_NON_BMP1 = 4, // has non-BMP1 code points, needs UTF-16 surrogate pairs UTF8_HAS_ERRORS = 8, // has encoding errors }; -int utf8_scan(const char *buf, size_t len, size_t *plen); -size_t utf8_encode_len(uint32_t c); -size_t utf8_encode(uint8_t buf[minimum_length(UTF8_CHAR_LEN_MAX)], uint32_t c); -uint32_t utf8_decode_len(const uint8_t *p, size_t max_len, const uint8_t **pp); -uint32_t utf8_decode(const uint8_t *p, const uint8_t **pp); -size_t utf8_decode_buf8(uint8_t *dest, size_t dest_len, const char *src, size_t src_len); -size_t utf8_decode_buf16(uint16_t *dest, size_t dest_len, const char *src, size_t src_len); -size_t utf8_encode_buf8(char *dest, size_t dest_len, const uint8_t *src, size_t src_len); -size_t utf8_encode_buf16(char *dest, size_t dest_len, const uint16_t *src, size_t src_len); +static inline int utf8_scan(const char *buf, size_t len, size_t *plen); +static inline size_t utf8_encode_len(uint32_t c); +static inline size_t utf8_encode(uint8_t buf[minimum_length(UTF8_CHAR_LEN_MAX)], uint32_t c); +static inline uint32_t utf8_decode_len(const uint8_t *p, size_t max_len, const uint8_t **pp); +static inline uint32_t utf8_decode(const uint8_t *p, const uint8_t **pp); +static inline size_t utf8_decode_buf8(uint8_t *dest, size_t dest_len, const char *src, size_t src_len); +static inline size_t utf8_decode_buf16(uint16_t *dest, size_t dest_len, const char *src, size_t src_len); +static inline size_t utf8_encode_buf8(char *dest, size_t dest_len, const uint8_t *src, size_t src_len); +static inline size_t utf8_encode_buf16(char *dest, size_t dest_len, const uint16_t *src, size_t src_len); static inline bool is_surrogate(uint32_t c) { @@ -543,7 +571,7 @@ static inline uint8_t to_upper_ascii(uint8_t c) { return c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c; } -void rqsort(void *base, size_t nmemb, size_t size, +static inline void rqsort(void *base, size_t nmemb, size_t size, int (*cmp)(const void *, const void *, void *), void *arg); @@ -567,8 +595,8 @@ static inline double uint64_as_float64(uint64_t u64) return u.d; } -int64_t js__gettimeofday_us(void); -uint64_t js__hrtime_ns(void); +static inline int64_t js__gettimeofday_us(void); +static inline uint64_t js__hrtime_ns(void); static inline size_t js__malloc_usable_size(const void *ptr) { @@ -583,11 +611,11 @@ static inline size_t js__malloc_usable_size(const void *ptr) #endif } -int js_exepath(char* buffer, size_t* size); +static inline int js_exepath(char* buffer, size_t* size); /* Cross-platform threading APIs. */ -#if defined(EMSCRIPTEN) || defined(__wasi__) +#if defined(EMSCRIPTEN) || defined(__wasi__) || defined(__DJGPP) #define JS_HAVE_THREADS 0 @@ -609,28 +637,28 @@ typedef pthread_cond_t js_cond_t; typedef pthread_t js_thread_t; #endif -void js_once(js_once_t *guard, void (*callback)(void)); +static inline void js_once(js_once_t *guard, void (*callback)(void)); -void js_mutex_init(js_mutex_t *mutex); -void js_mutex_destroy(js_mutex_t *mutex); -void js_mutex_lock(js_mutex_t *mutex); -void js_mutex_unlock(js_mutex_t *mutex); +static inline void js_mutex_init(js_mutex_t *mutex); +static inline void js_mutex_destroy(js_mutex_t *mutex); +static inline void js_mutex_lock(js_mutex_t *mutex); +static inline void js_mutex_unlock(js_mutex_t *mutex); -void js_cond_init(js_cond_t *cond); -void js_cond_destroy(js_cond_t *cond); -void js_cond_signal(js_cond_t *cond); -void js_cond_broadcast(js_cond_t *cond); -void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex); -int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout); +static inline void js_cond_init(js_cond_t *cond); +static inline void js_cond_destroy(js_cond_t *cond); +static inline void js_cond_signal(js_cond_t *cond); +static inline void js_cond_broadcast(js_cond_t *cond); +static inline void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex); +static inline int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout); enum { JS_THREAD_CREATE_DETACHED = 1, }; // creates threads with 2 MB stacks (glibc default) -int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg, +static inline int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg, int flags); -int js_thread_join(js_thread_t thrd); +static inline int js_thread_join(js_thread_t thrd); #endif /* !defined(EMSCRIPTEN) && !defined(__wasi__) */ @@ -653,6 +681,1315 @@ int js_thread_join(js_thread_t thrd); #define JS_X87_FPCW_RESTORE(cw) #endif +#undef NANOSEC +#define NANOSEC ((uint64_t) 1e9) + +static inline void js__pstrcpy(char *buf, int buf_size, const char *str) +{ + int c; + char *q = buf; + + if (buf_size <= 0) + return; + + for(;;) { + c = *str++; + if (c == 0 || q >= buf + buf_size - 1) + break; + *q++ = c; + } + *q = '\0'; +} + +/* strcat and truncate. */ +static inline char *js__pstrcat(char *buf, int buf_size, const char *s) +{ + int len; + len = strlen(buf); + if (len < buf_size) + js__pstrcpy(buf + len, buf_size - len, s); + return buf; +} + +static inline int js__strstart(const char *str, const char *val, const char **ptr) +{ + const char *p, *q; + p = str; + q = val; + while (*q != '\0') { + if (*p != *q) + return 0; + p++; + q++; + } + if (ptr) + *ptr = p; + return 1; +} + +static inline int js__has_suffix(const char *str, const char *suffix) +{ + size_t len = strlen(str); + size_t slen = strlen(suffix); + return (len >= slen && !memcmp(str + len - slen, suffix, slen)); +} + +/* Dynamic buffer package */ + +static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size) +{ + if (unlikely(size == 0)) { + free(ptr); + return NULL; + } + return realloc(ptr, size); +} + +static inline void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func) +{ + memset(s, 0, sizeof(*s)); + if (!realloc_func) + realloc_func = dbuf_default_realloc; + s->opaque = opaque; + s->realloc_func = realloc_func; +} + +static inline void dbuf_init(DynBuf *s) +{ + dbuf_init2(s, NULL, NULL); +} + +/* Try to allocate 'len' more bytes. return < 0 if error */ +static inline int dbuf_claim(DynBuf *s, size_t len) +{ + size_t new_size, size, new_allocated_size; + uint8_t *new_buf; + new_size = s->size + len; + if (new_size < len) + return -1; /* overflow */ + if (new_size > s->allocated_size) { + if (s->error) + return -1; + size = s->allocated_size + (s->allocated_size / 2); + if (size < new_size || size < s->allocated_size) /* overflow test */ + new_allocated_size = new_size; + else + new_allocated_size = size; + new_buf = s->realloc_func(s->opaque, s->buf, new_allocated_size); + if (!new_buf) { + s->error = true; + return -1; + } + s->buf = new_buf; + s->allocated_size = new_allocated_size; + } + return 0; +} + +static inline int dbuf_put(DynBuf *s, const void *data, size_t len) +{ + if (unlikely((s->size + len) > s->allocated_size)) { + if (dbuf_claim(s, len)) + return -1; + } + if (len > 0) { + memcpy(s->buf + s->size, data, len); + s->size += len; + } + return 0; +} + +static inline int dbuf_put_self(DynBuf *s, size_t offset, size_t len) +{ + if (unlikely((s->size + len) > s->allocated_size)) { + if (dbuf_claim(s, len)) + return -1; + } + if (len > 0) { + memcpy(s->buf + s->size, s->buf + offset, len); + s->size += len; + } + return 0; +} + +static inline int __dbuf_putc(DynBuf *s, uint8_t c) +{ + return dbuf_put(s, &c, 1); +} + +static inline int __dbuf_put_u16(DynBuf *s, uint16_t val) +{ + return dbuf_put(s, (uint8_t *)&val, 2); +} + +static inline int __dbuf_put_u32(DynBuf *s, uint32_t val) +{ + return dbuf_put(s, (uint8_t *)&val, 4); +} + +static inline int __dbuf_put_u64(DynBuf *s, uint64_t val) +{ + return dbuf_put(s, (uint8_t *)&val, 8); +} + +static inline int dbuf_putstr(DynBuf *s, const char *str) +{ + return dbuf_put(s, (const uint8_t *)str, strlen(str)); +} + +static inline int JS_PRINTF_FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, JS_PRINTF_FORMAT const char *fmt, ...) +{ + va_list ap; + char buf[128]; + int len; + + va_start(ap, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + if (len < (int)sizeof(buf)) { + /* fast case */ + return dbuf_put(s, (uint8_t *)buf, len); + } else { + if (dbuf_claim(s, len + 1)) + return -1; + va_start(ap, fmt); + vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size, + fmt, ap); + va_end(ap); + s->size += len; + } + return 0; +} + +static inline void dbuf_free(DynBuf *s) +{ + /* we test s->buf as a fail safe to avoid crashing if dbuf_free() + is called twice */ + if (s->buf) { + s->realloc_func(s->opaque, s->buf, 0); + } + memset(s, 0, sizeof(*s)); +} + +/*--- UTF-8 utility functions --*/ + +/* Note: only encode valid codepoints (0x0000..0x10FFFF). + At most UTF8_CHAR_LEN_MAX bytes are output. */ + +/* Compute the number of bytes of the UTF-8 encoding for a codepoint + `c` is a code-point. + Returns the number of bytes. If a codepoint is beyond 0x10FFFF the + return value is 3 as the codepoint would be encoded as 0xFFFD. + */ +static inline size_t utf8_encode_len(uint32_t c) +{ + if (c < 0x80) + return 1; + if (c < 0x800) + return 2; + if (c < 0x10000) + return 3; + if (c < 0x110000) + return 4; + return 3; +} + +/* Encode a codepoint in UTF-8 + `buf` points to an array of at least `UTF8_CHAR_LEN_MAX` bytes + `c` is a code-point. + Returns the number of bytes. If a codepoint is beyond 0x10FFFF the + return value is 3 and the codepoint is encoded as 0xFFFD. + No null byte is stored after the encoded bytes. + Return value is in range 1..4 + */ +static inline size_t utf8_encode(uint8_t buf[minimum_length(UTF8_CHAR_LEN_MAX)], uint32_t c) +{ + if (c < 0x80) { + buf[0] = c; + return 1; + } + if (c < 0x800) { + buf[0] = (c >> 6) | 0xC0; + buf[1] = (c & 0x3F) | 0x80; + return 2; + } + if (c < 0x10000) { + buf[0] = (c >> 12) | 0xE0; + buf[1] = ((c >> 6) & 0x3F) | 0x80; + buf[2] = (c & 0x3F) | 0x80; + return 3; + } + if (c < 0x110000) { + buf[0] = (c >> 18) | 0xF0; + buf[1] = ((c >> 12) & 0x3F) | 0x80; + buf[2] = ((c >> 6) & 0x3F) | 0x80; + buf[3] = (c & 0x3F) | 0x80; + return 4; + } + buf[0] = (0xFFFD >> 12) | 0xE0; + buf[1] = ((0xFFFD >> 6) & 0x3F) | 0x80; + buf[2] = (0xFFFD & 0x3F) | 0x80; + return 3; +} + +/* Decode a single code point from a UTF-8 encoded array of bytes + `p` is a valid pointer to an array of bytes + `pp` is a valid pointer to a `const uint8_t *` to store a pointer + to the byte following the current sequence. + Return the code point at `p`, in the range `0..0x10FFFF` + Return 0xFFFD on error. Only a single byte is consumed in this case + The maximum length for a UTF-8 byte sequence is 4 bytes. + This implements the algorithm specified in whatwg.org, except it accepts + UTF-8 encoded surrogates as JavaScript allows them in strings. + The source string is assumed to have at least UTF8_CHAR_LEN_MAX bytes + or be null terminated. + If `p[0]` is '\0', the return value is `0` and the byte is consumed. + cf: https://encoding.spec.whatwg.org/#utf-8-encoder + */ +static inline uint32_t utf8_decode(const uint8_t *p, const uint8_t **pp) +{ + uint32_t c; + uint8_t lower, upper; + + c = *p++; + if (c < 0x80) { + *pp = p; + return c; + } + switch(c) { + case 0xC2: case 0xC3: + case 0xC4: case 0xC5: case 0xC6: case 0xC7: + case 0xC8: case 0xC9: case 0xCA: case 0xCB: + case 0xCC: case 0xCD: case 0xCE: case 0xCF: + case 0xD0: case 0xD1: case 0xD2: case 0xD3: + case 0xD4: case 0xD5: case 0xD6: case 0xD7: + case 0xD8: case 0xD9: case 0xDA: case 0xDB: + case 0xDC: case 0xDD: case 0xDE: case 0xDF: + if (*p >= 0x80 && *p <= 0xBF) { + *pp = p + 1; + return ((c - 0xC0) << 6) + (*p - 0x80); + } + // otherwise encoding error + break; + case 0xE0: + lower = 0xA0; /* reject invalid encoding */ + goto need2; + case 0xE1: case 0xE2: case 0xE3: + case 0xE4: case 0xE5: case 0xE6: case 0xE7: + case 0xE8: case 0xE9: case 0xEA: case 0xEB: + case 0xEC: case 0xED: case 0xEE: case 0xEF: + lower = 0x80; + need2: + if (*p >= lower && *p <= 0xBF && p[1] >= 0x80 && p[1] <= 0xBF) { + *pp = p + 2; + return ((c - 0xE0) << 12) + ((*p - 0x80) << 6) + (p[1] - 0x80); + } + // otherwise encoding error + break; + case 0xF0: + lower = 0x90; /* reject invalid encoding */ + upper = 0xBF; + goto need3; + case 0xF4: + lower = 0x80; + upper = 0x8F; /* reject values above 0x10FFFF */ + goto need3; + case 0xF1: case 0xF2: case 0xF3: + lower = 0x80; + upper = 0xBF; + need3: + if (*p >= lower && *p <= upper && p[1] >= 0x80 && p[1] <= 0xBF + && p[2] >= 0x80 && p[2] <= 0xBF) { + *pp = p + 3; + return ((c - 0xF0) << 18) + ((*p - 0x80) << 12) + + ((p[1] - 0x80) << 6) + (p[2] - 0x80); + } + // otherwise encoding error + break; + default: + // invalid lead byte + break; + } + *pp = p; + return 0xFFFD; +} + +static inline uint32_t utf8_decode_len(const uint8_t *p, size_t max_len, const uint8_t **pp) { + switch (max_len) { + case 0: + *pp = p; + return 0xFFFD; + case 1: + if (*p < 0x80) + goto good; + break; + case 2: + if (*p < 0xE0) + goto good; + break; + case 3: + if (*p < 0xF0) + goto good; + break; + default: + good: + return utf8_decode(p, pp); + } + *pp = p + 1; + return 0xFFFD; +} + +/* Scan a UTF-8 encoded buffer for content type + `buf` is a valid pointer to a UTF-8 encoded string + `len` is the number of bytes to scan + `plen` points to a `size_t` variable to receive the number of units + Return value is a mask of bits. + - `UTF8_PLAIN_ASCII`: return value for 7-bit ASCII plain text + - `UTF8_NON_ASCII`: bit for non ASCII code points (8-bit or more) + - `UTF8_HAS_16BIT`: bit for 16-bit code points + - `UTF8_HAS_NON_BMP1`: bit for non-BMP1 code points, needs UTF-16 surrogate pairs + - `UTF8_HAS_ERRORS`: bit for encoding errors + */ +static inline int utf8_scan(const char *buf, size_t buf_len, size_t *plen) +{ + const uint8_t *p, *p_end, *p_next; + size_t i, len; + int kind; + uint8_t cbits; + + kind = UTF8_PLAIN_ASCII; + cbits = 0; + len = buf_len; + // TODO: handle more than 1 byte at a time + for (i = 0; i < buf_len; i++) + cbits |= buf[i]; + if (cbits >= 0x80) { + p = (const uint8_t *)buf; + p_end = p + buf_len; + kind = UTF8_NON_ASCII; + len = 0; + while (p < p_end) { + len++; + if (*p++ >= 0x80) { + /* parse UTF-8 sequence, check for encoding error */ + uint32_t c = utf8_decode_len(p - 1, p_end - (p - 1), &p_next); + if (p_next == p) + kind |= UTF8_HAS_ERRORS; + p = p_next; + if (c > 0xFF) { + kind |= UTF8_HAS_16BIT; + if (c > 0xFFFF) { + len++; + kind |= UTF8_HAS_NON_BMP1; + } + } + } + } + } + *plen = len; + return kind; +} + +/* Decode a string encoded in UTF-8 into an array of bytes + `src` points to the source string. It is assumed to be correctly encoded + and only contains code points below 0x800 + `src_len` is the length of the source string + `dest` points to the destination array, it can be null if `dest_len` is `0` + `dest_len` is the length of the destination array. A null + terminator is stored at the end of the array unless `dest_len` is `0`. + */ +static inline size_t utf8_decode_buf8(uint8_t *dest, size_t dest_len, const char *src, size_t src_len) +{ + const uint8_t *p, *p_end; + size_t i; + + p = (const uint8_t *)src; + p_end = p + src_len; + for (i = 0; p < p_end; i++) { + uint32_t c = *p++; + if (c >= 0xC0) + c = (c << 6) + *p++ - ((0xC0 << 6) + 0x80); + if (i < dest_len) + dest[i] = c; + } + if (i < dest_len) + dest[i] = '\0'; + else if (dest_len > 0) + dest[dest_len - 1] = '\0'; + return i; +} + +/* Decode a string encoded in UTF-8 into an array of 16-bit words + `src` points to the source string. It is assumed to be correctly encoded. + `src_len` is the length of the source string + `dest` points to the destination array, it can be null if `dest_len` is `0` + `dest_len` is the length of the destination array. No null terminator is + stored at the end of the array. + */ +static inline size_t utf8_decode_buf16(uint16_t *dest, size_t dest_len, const char *src, size_t src_len) +{ + const uint8_t *p, *p_end; + size_t i; + + p = (const uint8_t *)src; + p_end = p + src_len; + for (i = 0; p < p_end; i++) { + uint32_t c = *p++; + if (c >= 0x80) { + /* parse utf-8 sequence */ + c = utf8_decode_len(p - 1, p_end - (p - 1), &p); + /* encoding errors are converted as 0xFFFD and use a single byte */ + if (c > 0xFFFF) { + if (i < dest_len) + dest[i] = get_hi_surrogate(c); + i++; + c = get_lo_surrogate(c); + } + } + if (i < dest_len) + dest[i] = c; + } + return i; +} + +/* Encode a buffer of 8-bit bytes as a UTF-8 encoded string + `src` points to the source buffer. + `src_len` is the length of the source buffer + `dest` points to the destination array, it can be null if `dest_len` is `0` + `dest_len` is the length in bytes of the destination array. A null + terminator is stored at the end of the array unless `dest_len` is `0`. + */ +static inline size_t utf8_encode_buf8(char *dest, size_t dest_len, const uint8_t *src, size_t src_len) +{ + size_t i, j; + uint32_t c; + + for (i = j = 0; i < src_len; i++) { + c = src[i]; + if (c < 0x80) { + if (j + 1 >= dest_len) + goto overflow; + dest[j++] = c; + } else { + if (j + 2 >= dest_len) + goto overflow; + dest[j++] = (c >> 6) | 0xC0; + dest[j++] = (c & 0x3F) | 0x80; + } + } + if (j < dest_len) + dest[j] = '\0'; + return j; + +overflow: + if (j < dest_len) + dest[j] = '\0'; + while (i < src_len) + j += 1 + (src[i++] >= 0x80); + return j; +} + +/* Encode a buffer of 16-bit code points as a UTF-8 encoded string + `src` points to the source buffer. + `src_len` is the length of the source buffer + `dest` points to the destination array, it can be null if `dest_len` is `0` + `dest_len` is the length in bytes of the destination array. A null + terminator is stored at the end of the array unless `dest_len` is `0`. + */ +static inline size_t utf8_encode_buf16(char *dest, size_t dest_len, const uint16_t *src, size_t src_len) +{ + size_t i, j; + uint32_t c; + + for (i = j = 0; i < src_len;) { + c = src[i++]; + if (c < 0x80) { + if (j + 1 >= dest_len) + goto overflow; + dest[j++] = c; + } else { + if (is_hi_surrogate(c) && i < src_len && is_lo_surrogate(src[i])) + c = from_surrogate(c, src[i++]); + if (j + utf8_encode_len(c) >= dest_len) + goto overflow; + j += utf8_encode((uint8_t *)dest + j, c); + } + } + if (j < dest_len) + dest[j] = '\0'; + return j; + +overflow: + i -= 1 + (c > 0xFFFF); + if (j < dest_len) + dest[j] = '\0'; + while (i < src_len) { + c = src[i++]; + if (c < 0x80) { + j++; + } else { + if (is_hi_surrogate(c) && i < src_len && is_lo_surrogate(src[i])) + c = from_surrogate(c, src[i++]); + j += utf8_encode_len(c); + } + } + return j; +} + +/*---- sorting with opaque argument ----*/ + +typedef void (*exchange_f)(void *a, void *b, size_t size); +typedef int (*cmp_f)(const void *, const void *, void *opaque); + +static void exchange_bytes(void *a, void *b, size_t size) { + uint8_t *ap = (uint8_t *)a; + uint8_t *bp = (uint8_t *)b; + + while (size-- != 0) { + uint8_t t = *ap; + *ap++ = *bp; + *bp++ = t; + } +} + +static void exchange_one_byte(void *a, void *b, size_t size) { + uint8_t *ap = (uint8_t *)a; + uint8_t *bp = (uint8_t *)b; + uint8_t t = *ap; + *ap = *bp; + *bp = t; +} + +static void exchange_int16s(void *a, void *b, size_t size) { + uint16_t *ap = (uint16_t *)a; + uint16_t *bp = (uint16_t *)b; + + for (size /= sizeof(uint16_t); size-- != 0;) { + uint16_t t = *ap; + *ap++ = *bp; + *bp++ = t; + } +} + +static void exchange_one_int16(void *a, void *b, size_t size) { + uint16_t *ap = (uint16_t *)a; + uint16_t *bp = (uint16_t *)b; + uint16_t t = *ap; + *ap = *bp; + *bp = t; +} + +static void exchange_int32s(void *a, void *b, size_t size) { + uint32_t *ap = (uint32_t *)a; + uint32_t *bp = (uint32_t *)b; + + for (size /= sizeof(uint32_t); size-- != 0;) { + uint32_t t = *ap; + *ap++ = *bp; + *bp++ = t; + } +} + +static void exchange_one_int32(void *a, void *b, size_t size) { + uint32_t *ap = (uint32_t *)a; + uint32_t *bp = (uint32_t *)b; + uint32_t t = *ap; + *ap = *bp; + *bp = t; +} + +static void exchange_int64s(void *a, void *b, size_t size) { + uint64_t *ap = (uint64_t *)a; + uint64_t *bp = (uint64_t *)b; + + for (size /= sizeof(uint64_t); size-- != 0;) { + uint64_t t = *ap; + *ap++ = *bp; + *bp++ = t; + } +} + +static void exchange_one_int64(void *a, void *b, size_t size) { + uint64_t *ap = (uint64_t *)a; + uint64_t *bp = (uint64_t *)b; + uint64_t t = *ap; + *ap = *bp; + *bp = t; +} + +static void exchange_int128s(void *a, void *b, size_t size) { + uint64_t *ap = (uint64_t *)a; + uint64_t *bp = (uint64_t *)b; + + for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) { + uint64_t t = ap[0]; + uint64_t u = ap[1]; + ap[0] = bp[0]; + ap[1] = bp[1]; + bp[0] = t; + bp[1] = u; + } +} + +static void exchange_one_int128(void *a, void *b, size_t size) { + uint64_t *ap = (uint64_t *)a; + uint64_t *bp = (uint64_t *)b; + uint64_t t = ap[0]; + uint64_t u = ap[1]; + ap[0] = bp[0]; + ap[1] = bp[1]; + bp[0] = t; + bp[1] = u; +} + +static inline exchange_f exchange_func(const void *base, size_t size) { + switch (((uintptr_t)base | (uintptr_t)size) & 15) { + case 0: + if (size == sizeof(uint64_t) * 2) + return exchange_one_int128; + else + return exchange_int128s; + case 8: + if (size == sizeof(uint64_t)) + return exchange_one_int64; + else + return exchange_int64s; + case 4: + case 12: + if (size == sizeof(uint32_t)) + return exchange_one_int32; + else + return exchange_int32s; + case 2: + case 6: + case 10: + case 14: + if (size == sizeof(uint16_t)) + return exchange_one_int16; + else + return exchange_int16s; + default: + if (size == 1) + return exchange_one_byte; + else + return exchange_bytes; + } +} + +static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) +{ + uint8_t *basep = (uint8_t *)base; + size_t i, n, c, r; + exchange_f swap = exchange_func(base, size); + + if (nmemb > 1) { + i = (nmemb / 2) * size; + n = nmemb * size; + + while (i > 0) { + i -= size; + for (r = i; (c = r * 2 + size) < n; r = c) { + if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0) + c += size; + if (cmp(basep + r, basep + c, opaque) > 0) + break; + swap(basep + r, basep + c, size); + } + } + for (i = n - size; i > 0; i -= size) { + swap(basep, basep + i, size); + + for (r = 0; (c = r * 2 + size) < i; r = c) { + if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0) + c += size; + if (cmp(basep + r, basep + c, opaque) > 0) + break; + swap(basep + r, basep + c, size); + } + } + } +} + +static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque) +{ + return cmp(a, b, opaque) < 0 ? + (cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) : + (cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c )); +} + +/* pointer based version with local stack and insertion sort threshhold */ +static inline void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) +{ + struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack; + uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m; + size_t m4, i, lt, gt, span, span2; + int c, depth; + exchange_f swap = exchange_func(base, size); + exchange_f swap_block = exchange_func(base, size | 128); + + if (nmemb < 2 || size <= 0) + return; + + sp->base = (uint8_t *)base; + sp->count = nmemb; + sp->depth = 0; + sp++; + + while (sp > stack) { + sp--; + ptr = sp->base; + nmemb = sp->count; + depth = sp->depth; + + while (nmemb > 6) { + if (++depth > 50) { + /* depth check to ensure worst case logarithmic time */ + heapsortx(ptr, nmemb, size, cmp, opaque); + nmemb = 0; + break; + } + /* select median of 3 from 1/4, 1/2, 3/4 positions */ + /* should use median of 5 or 9? */ + m4 = (nmemb >> 2) * size; + m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque); + swap(ptr, m, size); /* move the pivot to the start or the array */ + i = lt = 1; + pi = plt = ptr + size; + gt = nmemb; + pj = pgt = top = ptr + nmemb * size; + for (;;) { + while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) { + if (c == 0) { + swap(plt, pi, size); + lt++; + plt += size; + } + i++; + pi += size; + } + while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) { + if (c == 0) { + gt--; + pgt -= size; + swap(pgt, pj, size); + } + } + if (pi >= pj) + break; + swap(pi, pj, size); + i++; + pi += size; + } + /* array has 4 parts: + * from 0 to lt excluded: elements identical to pivot + * from lt to pi excluded: elements smaller than pivot + * from pi to gt excluded: elements greater than pivot + * from gt to n excluded: elements identical to pivot + */ + /* move elements identical to pivot in the middle of the array: */ + /* swap values in ranges [0..lt[ and [i-lt..i[ + swapping the smallest span between lt and i-lt is sufficient + */ + span = plt - ptr; + span2 = pi - plt; + lt = i - lt; + if (span > span2) + span = span2; + swap_block(ptr, pi - span, span); + /* swap values in ranges [gt..top[ and [i..top-(top-gt)[ + swapping the smallest span between top-gt and gt-i is sufficient + */ + span = top - pgt; + span2 = pgt - pi; + pgt = top - span2; + gt = nmemb - (gt - i); + if (span > span2) + span = span2; + swap_block(pi, top - span, span); + + /* now array has 3 parts: + * from 0 to lt excluded: elements smaller than pivot + * from lt to gt excluded: elements identical to pivot + * from gt to n excluded: elements greater than pivot + */ + /* stack the larger segment and keep processing the smaller one + to minimize stack use for pathological distributions */ + if (lt > nmemb - gt) { + sp->base = ptr; + sp->count = lt; + sp->depth = depth; + sp++; + ptr = pgt; + nmemb -= gt; + } else { + sp->base = pgt; + sp->count = nmemb - gt; + sp->depth = depth; + sp++; + nmemb = lt; + } + } + /* Use insertion sort for small fragments */ + for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) { + for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size) + swap(pj, pj - size, size); + } + } +} + +/*---- Portable time functions ----*/ + +#ifdef _WIN32 + // From: https://stackoverflow.com/a/26085827 +static int gettimeofday_msvc(struct timeval *tp) +{ + static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL); + + SYSTEMTIME system_time; + FILETIME file_time; + uint64_t time; + + GetSystemTime(&system_time); + SystemTimeToFileTime(&system_time, &file_time); + time = ((uint64_t)file_time.dwLowDateTime); + time += ((uint64_t)file_time.dwHighDateTime) << 32; + + tp->tv_sec = (long)((time - EPOCH) / 10000000L); + tp->tv_usec = (long)(system_time.wMilliseconds * 1000); + + return 0; +} + +static inline uint64_t js__hrtime_ns(void) { + LARGE_INTEGER counter, frequency; + double scaled_freq; + double result; + + if (!QueryPerformanceFrequency(&frequency)) + abort(); + assert(frequency.QuadPart != 0); + + if (!QueryPerformanceCounter(&counter)) + abort(); + assert(counter.QuadPart != 0); + + /* Because we have no guarantee about the order of magnitude of the + * performance counter interval, integer math could cause this computation + * to overflow. Therefore we resort to floating point math. + */ + scaled_freq = (double) frequency.QuadPart / NANOSEC; + result = (double) counter.QuadPart / scaled_freq; + return (uint64_t) result; +} +#else +static inline uint64_t js__hrtime_ns(void) { +#ifdef __DJGPP + struct timeval tv; + if (gettimeofday(&tv, NULL)) + abort(); + return tv.tv_sec * NANOSEC + tv.tv_usec * 1000; +#else + struct timespec t; + + if (clock_gettime(CLOCK_MONOTONIC, &t)) + abort(); + + return t.tv_sec * NANOSEC + t.tv_nsec; +#endif +} +#endif + +static inline int64_t js__gettimeofday_us(void) { + struct timeval tv; +#ifdef _WIN32 + gettimeofday_msvc(&tv); +#else + gettimeofday(&tv, NULL); +#endif + return ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec; +} + +#if defined(_WIN32) +static inline int js_exepath(char *buffer, size_t *size_ptr) { + int utf8_len, utf16_buffer_len, utf16_len; + WCHAR* utf16_buffer; + + if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) + return -1; + + if (*size_ptr > 32768) { + /* Windows paths can never be longer than this. */ + utf16_buffer_len = 32768; + } else { + utf16_buffer_len = (int)*size_ptr; + } + + utf16_buffer = malloc(sizeof(WCHAR) * utf16_buffer_len); + if (!utf16_buffer) + return -1; + + /* Get the path as UTF-16. */ + utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len); + if (utf16_len <= 0) + goto error; + + /* Convert to UTF-8 */ + utf8_len = WideCharToMultiByte(CP_UTF8, + 0, + utf16_buffer, + -1, + buffer, + (int)*size_ptr, + NULL, + NULL); + if (utf8_len == 0) + goto error; + + free(utf16_buffer); + + /* utf8_len *does* include the terminating null at this point, but the + * returned size shouldn't. */ + *size_ptr = utf8_len - 1; + return 0; + +error: + free(utf16_buffer); + return -1; +} +#elif defined(__APPLE__) +static inline int js_exepath(char *buffer, size_t *size) { + /* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */ + char abspath[PATH_MAX * 2 + 1]; + char exepath[PATH_MAX + 1]; + uint32_t exepath_size; + size_t abspath_size; + + if (buffer == NULL || size == NULL || *size == 0) + return -1; + + exepath_size = sizeof(exepath); + if (_NSGetExecutablePath(exepath, &exepath_size)) + return -1; + + if (realpath(exepath, abspath) != abspath) + return -1; + + abspath_size = strlen(abspath); + if (abspath_size == 0) + return -1; + + *size -= 1; + if (*size > abspath_size) + *size = abspath_size; + + memcpy(buffer, abspath, *size); + buffer[*size] = '\0'; + + return 0; +} +#elif defined(__linux__) || defined(__GNU__) +static inline int js_exepath(char *buffer, size_t *size) { + ssize_t n; + + if (buffer == NULL || size == NULL || *size == 0) + return -1; + + n = *size - 1; + if (n > 0) + n = readlink("/proc/self/exe", buffer, n); + + if (n == -1) + return n; + + buffer[n] = '\0'; + *size = n; + + return 0; +} +#else +static inline int js_exepath(char* buffer, size_t* size_ptr) { + return -1; +} +#endif + +/*--- Cross-platform threading APIs. ----*/ + +#if JS_HAVE_THREADS +#if defined(_WIN32) +typedef void (*js__once_cb)(void); + +typedef struct { + js__once_cb callback; +} js__once_data_t; + +static int WINAPI js__once_inner(INIT_ONCE *once, void *param, void **context) { + js__once_data_t *data = param; + + data->callback(); + + return 1; +} + +static inline void js_once(js_once_t *guard, js__once_cb callback) { + js__once_data_t data = { .callback = callback }; + InitOnceExecuteOnce(guard, js__once_inner, (void*) &data, NULL); +} + +static inline void js_mutex_init(js_mutex_t *mutex) { + InitializeCriticalSection(mutex); +} + +static inline void js_mutex_destroy(js_mutex_t *mutex) { + DeleteCriticalSection(mutex); +} + +static inline void js_mutex_lock(js_mutex_t *mutex) { + EnterCriticalSection(mutex); +} + +static inline void js_mutex_unlock(js_mutex_t *mutex) { + LeaveCriticalSection(mutex); +} + +static inline void js_cond_init(js_cond_t *cond) { + InitializeConditionVariable(cond); +} + +static inline void js_cond_destroy(js_cond_t *cond) { + /* nothing to do */ + (void) cond; +} + +static inline void js_cond_signal(js_cond_t *cond) { + WakeConditionVariable(cond); +} + +static inline void js_cond_broadcast(js_cond_t *cond) { + WakeAllConditionVariable(cond); +} + +static inline void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex) { + if (!SleepConditionVariableCS(cond, mutex, INFINITE)) + abort(); +} + +static inline int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) { + if (SleepConditionVariableCS(cond, mutex, (DWORD)(timeout / 1e6))) + return 0; + if (GetLastError() != ERROR_TIMEOUT) + abort(); + return -1; +} + +static inline int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg, + int flags) +{ + HANDLE h, cp; + + *thrd = INVALID_HANDLE_VALUE; + if (flags & ~JS_THREAD_CREATE_DETACHED) + return -1; + h = (HANDLE)_beginthread(start, /*stacksize*/2<<20, arg); + if (!h) + return -1; + if (flags & JS_THREAD_CREATE_DETACHED) + return 0; + // _endthread() automatically closes the handle but we want to wait on + // it so make a copy. Race-y for very short-lived threads. Can be solved + // by switching to _beginthreadex(CREATE_SUSPENDED) but means changing + // |start| from __cdecl to __stdcall. + cp = GetCurrentProcess(); + if (DuplicateHandle(cp, h, cp, thrd, 0, FALSE, DUPLICATE_SAME_ACCESS)) + return 0; + return -1; +} + +static inline int js_thread_join(js_thread_t thrd) +{ + if (WaitForSingleObject(thrd, INFINITE)) + return -1; + CloseHandle(thrd); + return 0; +} + +#else /* !defined(_WIN32) */ + +static inline void js_once(js_once_t *guard, void (*callback)(void)) { + if (pthread_once(guard, callback)) + abort(); +} + +static inline void js_mutex_init(js_mutex_t *mutex) { + if (pthread_mutex_init(mutex, NULL)) + abort(); +} + +static inline void js_mutex_destroy(js_mutex_t *mutex) { + if (pthread_mutex_destroy(mutex)) + abort(); +} + +static inline void js_mutex_lock(js_mutex_t *mutex) { + if (pthread_mutex_lock(mutex)) + abort(); +} + +static inline void js_mutex_unlock(js_mutex_t *mutex) { + if (pthread_mutex_unlock(mutex)) + abort(); +} + +static inline void js_cond_init(js_cond_t *cond) { +#if defined(__APPLE__) && defined(__MACH__) + if (pthread_cond_init(cond, NULL)) + abort(); +#else + pthread_condattr_t attr; + + if (pthread_condattr_init(&attr)) + abort(); + + if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) + abort(); + + if (pthread_cond_init(cond, &attr)) + abort(); + + if (pthread_condattr_destroy(&attr)) + abort(); +#endif +} + +static inline void js_cond_destroy(js_cond_t *cond) { +#if defined(__APPLE__) && defined(__MACH__) + /* It has been reported that destroying condition variables that have been + * signalled but not waited on can sometimes result in application crashes. + * See https://codereview.chromium.org/1323293005. + */ + pthread_mutex_t mutex; + struct timespec ts; + int err; + + if (pthread_mutex_init(&mutex, NULL)) + abort(); + + if (pthread_mutex_lock(&mutex)) + abort(); + + ts.tv_sec = 0; + ts.tv_nsec = 1; + + err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts); + if (err != 0 && err != ETIMEDOUT) + abort(); + + if (pthread_mutex_unlock(&mutex)) + abort(); + + if (pthread_mutex_destroy(&mutex)) + abort(); +#endif /* defined(__APPLE__) && defined(__MACH__) */ + + if (pthread_cond_destroy(cond)) + abort(); +} + +static inline void js_cond_signal(js_cond_t *cond) { + if (pthread_cond_signal(cond)) + abort(); +} + +static inline void js_cond_broadcast(js_cond_t *cond) { + if (pthread_cond_broadcast(cond)) + abort(); +} + +static inline void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex) { +#if defined(__APPLE__) && defined(__MACH__) + int r; + + errno = 0; + r = pthread_cond_wait(cond, mutex); + + /* Workaround for a bug in OS X at least up to 13.6 + * See https://github.com/libuv/libuv/issues/4165 + */ + if (r == EINVAL && errno == EBUSY) + return; + if (r) + abort(); +#else + if (pthread_cond_wait(cond, mutex)) + abort(); +#endif +} + +static inline int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) { + int r; + struct timespec ts; + +#if !defined(__APPLE__) + timeout += js__hrtime_ns(); +#endif + + ts.tv_sec = timeout / NANOSEC; + ts.tv_nsec = timeout % NANOSEC; +#if defined(__APPLE__) && defined(__MACH__) + r = pthread_cond_timedwait_relative_np(cond, mutex, &ts); +#else + r = pthread_cond_timedwait(cond, mutex, &ts); +#endif + + if (r == 0) + return 0; + + if (r == ETIMEDOUT) + return -1; + + abort(); + + /* Pacify some compilers. */ + return -1; +} + +static inline int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg, + int flags) +{ + union { + void (*x)(void *); + void *(*f)(void *); + } u = {start}; + pthread_attr_t attr; + int ret; + + if (flags & ~JS_THREAD_CREATE_DETACHED) + return -1; + if (pthread_attr_init(&attr)) + return -1; + ret = -1; + if (pthread_attr_setstacksize(&attr, 2<<20)) + goto fail; + if (flags & JS_THREAD_CREATE_DETACHED) + if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) + goto fail; + if (pthread_create(thrd, &attr, u.f, arg)) + goto fail; + ret = 0; +fail: + pthread_attr_destroy(&attr); + return ret; +} + +static inline int js_thread_join(js_thread_t thrd) +{ + if (pthread_join(thrd, NULL)) + return -1; + return 0; +} + +#endif /* !defined(_WIN32) */ +#endif /* JS_HAVE_THREADS */ + #ifdef __cplusplus } /* extern "C" { */ #endif diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/.gitignore b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/.gitignore new file mode 100755 index 00000000..b2d6de30 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/.gitignore @@ -0,0 +1,20 @@ +# Dependencies +/node_modules + +# Production +/build + +# Generated files +.docusaurus +.cache-loader + +# Misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/.nvmrc b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/.nvmrc new file mode 100755 index 00000000..3c032078 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/.nvmrc @@ -0,0 +1 @@ +18 diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/babel.config.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/babel.config.js new file mode 100755 index 00000000..e00595da --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: [require.resolve('@docusaurus/core/lib/babel/preset')], +}; diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/building.md b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/building.md new file mode 100755 index 00000000..0bf87746 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/building.md @@ -0,0 +1,63 @@ +--- +sidebar_position: 2 +--- + +# Building + +QuickJS uses [CMake] as its main build system, with an additional helper [Makefile]. + +:::note +Windows users will need to run the CMake commands manually. +::: + +## Getting the source + +```bash +git clone https://github.com/quickjs-ng/quickjs.git +cd quickjs +``` + +## Compiling everything + +```bash +make +``` + +This will build the `qjs` and `qjsc` executables and other test tools. Head over [here](./cli) for +instructions on how to use them. + +## Amalgamated builds + +The amalgamated build rolls individual source files into a single big file. +It's a good choice for projects that want to use QuickJS without CMake. + +Download quickjs-amalgam.zip from [Releases](https://github.com/quickjs-ng/quickjs/releases) + +To enable the std, os and bjson modules, compile quickjs-amalgam.c with +`-DQJS_BUILD_LIBC`. + +## Debug builds + +```bash +make debug +``` + +This will produce a debug build without optimizations, suitable for developers. + +## Running test262 + +```bash +make test262 +``` + +This will run the test262 suite. + +```bash +make test262-update +``` + +This will run the test262 suite and update the error / pass report, useful after +implementing a new feature that would alter the result of the test suite. + +[CMake]: https://cmake.org +[Makefile]: https://www.gnu.org/software/make/ diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/cli.md b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/cli.md new file mode 100755 index 00000000..d859439f --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/cli.md @@ -0,0 +1,130 @@ +--- +sidebar_position: 4 +--- + +# The qjs and qjsc CLI tools + +## `qjs` - The QuickJS JavaScript interpreter + +The `qjs` executable runs the JavaScript interpreter. It includes a simple standard +library and REPL. + +``` +$ qjs +usage: qjs [options] [file [args]] +-h --help list options +-e --eval EXPR evaluate EXPR +-i --interactive go to interactive mode +-m --module load as ES6 module (default=autodetect) + --script load as ES6 script (default=autodetect) +-I --include file include an additional file + --std make 'std', 'os' and 'bjson' available to script +-T --trace trace memory allocation +-d --dump dump the memory usage stats +-D --dump-flags flags for dumping debug data (see DUMP_* defines) +-c --compile FILE compile the given JS file as a standalone executable +-o --out FILE output file for standalone executables + --exe select the executable to use as the base, defaults to the current one + --memory-limit n limit the memory usage to 'n' Kbytes + --stack-size n limit the stack size to 'n' Kbytes + --unhandled-rejection dump unhandled promise rejections +-q --quit just instantiate the interpreter and quit +``` + +The following dump flags are supported: + +``` +DUMP_BYTECODE_FINAL 0x01 /* dump pass 3 final byte code */ +DUMP_BYTECODE_PASS2 0x02 /* dump pass 2 code */ +DUMP_BYTECODE_PASS1 0x04 /* dump pass 1 code */ +DUMP_BYTECODE_HEX 0x10 /* dump bytecode in hex */ +DUMP_BYTECODE_PC2LINE 0x20 /* dump line number table */ +DUMP_BYTECODE_STACK 0x40 /* dump compute_stack_size */ +DUMP_BYTECODE_STEP 0x80 /* dump executed bytecode */ +DUMP_READ_OBJECT 0x100 /* dump the marshalled objects at load time */ +DUMP_FREE 0x200 /* dump every object free */ +DUMP_GC 0x400 /* dump the occurrence of the automatic GC */ +DUMP_GC_FREE 0x800 /* dump objects freed by the GC */ +DUMP_MODULE_RESOLVE 0x1000 /* dump module resolution steps */ +DUMP_PROMISE 0x2000 /* dump promise steps */ +DUMP_LEAKS 0x4000 /* dump leaked objects and strings in JS_FreeRuntime */ +DUMP_ATOM_LEAKS 0x8000 /* dump leaked atoms in JS_FreeRuntime */ +DUMP_MEM 0x10000 /* dump memory usage in JS_FreeRuntime */ +DUMP_OBJECTS 0x20000 /* dump objects in JS_FreeRuntime */ +DUMP_ATOMS 0x40000 /* dump atoms in JS_FreeRuntime */ +DUMP_SHAPES 0x80000 /* dump shapes in JS_FreeRuntime */ +``` + +### Creating standalone executables + +With the `qjs` CLI it's possible to create standalone executables that will bundle the given JavaScript file +alongside the binary. + +``` +$ qjs -c app.js -o app --exe qjs +``` + +The resulting `app` binary will have the same runtime dependencies as the `qjs` binary. This is acomplished +by compiling the target JavaScript file to bytecode and adding it a copy of the executable, with a little +trailer to help locate it. `--exe` expects the absolute path to `qjs`, e.g., `~/bin/qjs` or `$HOME/bin/qjs`. + +Rather than using the current executable, it's possible to use the `--exe` switch to create standalone +executables for other platforms. + +No JavaScript bundling is performed, the specified JS file cannot depend on other files. A bundler such +as `esbuild` can be used to generate an app bundle which can then be turned into the executable. + +``` +npx esbuild my-app/index.js \ + --bundle \ + --outfile=app.js \ + --external:qjs:* \ + --minify \ + --target=es2023 \ + --platform=neutral \ + --format=esm \ + --main-fields=main,module +``` + +## `qjsc` - The QuickJS JavaScript compiler + +The `qjsc` executable runs the JavaScript compiler, it can generate bytecode from +source files which can then be embedded in an executable, or it can generate the necessary +scaffolding to build a C application which embeds QuickJS. + +``` +$ qjsc +usage: qjsc [options] [files] + +options are: +-b output raw bytecode instead of C code +-e output main() and bytecode in a C file +-o output set the output filename +-n script_name set the script name (as used in stack traces) +-N cname set the C name of the generated data +-m compile as JavaScript module (default=autodetect) +-D module_name compile a dynamically loaded module or worker +-M module_name[,cname] add initialization code for an external C module +-p prefix set the prefix of the generated C names +-s strip the source code, specify twice to also strip debug info +-S n set the maximum stack size to 'n' bytes (default=262144) +``` + +Here is an example on how to create a standalone executable that embeds QuickJS +and the `examples/hello.js` JavaScript file: + +```bash +# Make sure you are in the QuickJS source directory. +$ cc hello.c dtoa.c libregexp.c libunicode.c quickjs.c quickjs-libc.c -I. -o hello +``` + +The resulting binary `hello` will be in the current directory. + +```bash +$ ./hello +Hello World +``` + +:::note +See the ["Creating standalone executables"](#creating-standalone-executables) section for a simpler way. +::: diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/developer-guide/_category_.json b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/developer-guide/_category_.json new file mode 100755 index 00000000..60504771 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/developer-guide/_category_.json @@ -0,0 +1,7 @@ +{ + "label": "Developer Guide", + "position": 6, + "link": { + "type": "generated-index" + } +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/developer-guide/api.md b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/developer-guide/api.md new file mode 100755 index 00000000..78bec942 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/developer-guide/api.md @@ -0,0 +1,3 @@ +# API Reference + +WIP. diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/developer-guide/internals.md b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/developer-guide/internals.md new file mode 100755 index 00000000..4c9afea9 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/developer-guide/internals.md @@ -0,0 +1,117 @@ +# Internals + +## Bytecode + +The compiler generates bytecode directly with no intermediate +representation such as a parse tree, hence it is very fast. Several +optimizations passes are done over the generated bytecode. + +A stack-based bytecode was chosen because it is simple and generates +compact code. + +For each function, the maximum stack size is computed at compile time so that +no runtime stack overflow tests are needed. + +A separate compressed line number table is maintained for the debug +information. + +Access to closure variables is optimized and is almost as fast as local +variables. + +Direct `eval` in strict mode is optimized. + +## Runtime + +### Strings + +Strings are stored either as an 8 bit or a 16 bit array of +characters. Hence random access to characters is always fast. + +The C API provides functions to convert JavaScript Strings to C UTF-8 encoded +strings. The most common case where the JavaScript string contains +only ASCII characters involves no copying. + +### Objects + +The object shapes (object prototype, property names and flags) are shared +between objects to save memory. + +Arrays with no holes (except at the end of the array) are optimized. + +TypedArray accesses are optimized. + +### Atoms + +Object property names and some strings are stored as Atoms (unique +strings) to save memory and allow fast comparison. Atoms are +represented as a 32 bit integer. Half of the atom range is reserved for +immediate integer literals from 0 to 2^31-1. + +### Numbers + +Numbers are represented either as 32-bit signed integers or 64-bit IEEE-754 +floating point values. Most operations have fast paths for the 32-bit +integer case. + +### Garbage collection + +Reference counting is used to free objects automatically and +deterministically. A separate cycle removal pass is done when the allocated +memory becomes too large. The cycle removal algorithm only uses the +reference counts and the object content, so no explicit garbage +collection roots need to be manipulated in the C code. + +### JSValue + +It is a JavaScript value which can be a primitive type (such as +Number, String, ...) or an Object. NaN boxing is used in the 32-bit version +to store 64-bit floating point numbers. The representation is +optimized so that 32-bit integers and reference counted values can be +efficiently tested. + +In 64-bit code, JSValue are 128-bit large and no NaN boxing is used. The +rationale is that in 64-bit code memory usage is less critical. + +In both cases (32 or 64 bits), JSValue exactly fits two CPU registers, +so it can be efficiently returned by C functions. + +### Function call + +The engine is optimized so that function calls are fast. The system +stack holds the JavaScript parameters and local variables. + +### RegExp + +A specific regular expression engine was developed. It is both small +and efficient and supports all the ES2020+ features including the +Unicode properties. As the JavaScript compiler, it directly generates +bytecode without a parse tree. + +Backtracking with an explicit stack is used so that there is no +recursion on the system stack. Simple quantifiers are specifically +optimized to avoid recursions. + +Infinite recursions coming from quantifiers with empty terms are +avoided. + +The full regexp library weighs about 15 KiB (x86 code), excluding the +Unicode library. + +### Unicode + +A specific Unicode library was developed so that there is no +dependency on an external large Unicode library such as ICU. All the +Unicode tables are compressed while keeping a reasonable access +speed. + +The library supports case conversion, Unicode normalization, Unicode +script queries, Unicode general category queries and all Unicode +binary properties. + +The full Unicode library weighs about 45 KiB (x86 code). + +### BigInt + +BigInt is implemented with the [libbf](https://bellard.org/libbf) library. +It weights about 90 KiB (x86 code) and provides arbitrary precision IEEE 754 floating +point operations and transcendental functions with exact rounding. diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/developer-guide/intro.md b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/developer-guide/intro.md new file mode 100755 index 00000000..4d85efb0 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/developer-guide/intro.md @@ -0,0 +1,113 @@ +--- +sidebar_position: 1 +--- + +# The QuickJS C API + +The C API was designed to be simple and efficient. The C API is +defined in the header `quickjs.h`. + +## Runtime and contexts + +`JSRuntime` represents a JavaScript runtime corresponding to an +object heap. Several runtimes can exist at the same time but they +cannot exchange objects. Inside a given runtime, no multi-threading is +supported. + +`JSContext` represents a JavaScript context (or Realm). Each +JSContext has its own global objects and system objects. There can be +several JSContexts per JSRuntime and they can share objects, similar +to frames of the same origin sharing JavaScript objects in a +web browser. + +## JSValue + +`JSValue` represents a JavaScript value which can be a primitive +type or an object. Reference counting is used, so it is important to +explicitly duplicate (`JS_DupValue()`, increment the reference +count) or free (`JS_FreeValue()`, decrement the reference count) +JSValues. + +## C functions + +C functions can be created with +`JS_NewCFunction()`. `JS_SetPropertyFunctionList()` is a +shortcut to easily add functions, setters and getters properties to a +given object. + +Unlike other embedded JavaScript engines, there is no implicit stack, +so C functions get their parameters as normal C parameters. As a +general rule, C functions take constant `JSValue`s as parameters +(so they don't need to free them) and return a newly allocated (=live) +`JSValue`. + +## Exceptions + +Most C functions can return a JavaScript exception. It +must be explicitly tested and handled by the C code. The specific +`JSValue` `JS_EXCEPTION` indicates that an exception +occurred. The actual exception object is stored in the +`JSContext` and can be retrieved with `JS_GetException()`. + +## Script evaluation + +Use `JS_Eval()` to evaluate a script or module source. + +If the script or module was compiled to bytecode with `qjsc`, it +can be evaluated by calling `js_std_eval_binary()`. The advantage +is that no compilation is needed so it is faster and smaller because +the compiler can be removed from the executable if no `eval` is +required. + +Note: the bytecode format is linked to a given QuickJS +version. Moreover, no security check is done before its +execution. Hence the bytecode should not be loaded from untrusted +sources. + +## JS Classes + +C opaque data can be attached to a JavaScript object. The type of the +C opaque data is determined with the class ID (`JSClassID`) of +the object. Hence the first step is to register a new class ID and JS +class (`JS_NewClassID()`, `JS_NewClass()`). Then you can +create objects of this class with `JS_NewObjectClass()` and get or +set the C opaque point with `JS_GetOpaque()` / `JS_SetOpaque()`. + +When defining a new JS class, it is possible to declare a finalizer +which is called when the object is destroyed. The finalizer should be +used to release C resources. It is invalid to execute JS code from +it. A `gc_mark` method can be provided so that the cycle removal +algorithm can find the other objects referenced by this object. Other +methods are available to define exotic object behaviors. + +The Class ID are allocated per-runtime. The +`JSClass` are allocated per `JSRuntime`. `JS_SetClassProto()` +is used to define a prototype for a given class in a given +`JSContext`. `JS_NewObjectClass()` sets this prototype in the +created object. + +Examples are available in `quickjs-libc.c`. + +## C Modules + +Native ES6 modules are supported and can be dynamically or statically +linked. The standard library `quickjs-libc.c` is a good example +of a native module. + +## Memory handling + +Use `JS_SetMemoryLimit()` to set a global memory allocation limit +to a given `JSRuntime`. + +Custom memory allocation functions can be provided with `JS_NewRuntime2()`. + +The maximum system stack size can be set with `JS_SetMaxStackSize()`. + +## Execution timeout and interrupts + +Use `JS_SetInterruptHandler()` to set a callback which is +regularly called by the engine when it is executing code. This +callback can be used to implement an execution timeout. + +It is used by the command line interpreter to implement a +`Ctrl-C` handler. diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/diff.md b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/diff.md new file mode 100755 index 00000000..adf81eef --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/diff.md @@ -0,0 +1,68 @@ +# Differences with bellard/quickjs + +This project aims to be a drop-in replacement for those already using QuickJS. +Minimal API changes might be necessary. + +## Community development + +NG is developed in the open, interacting with the wider community and through +these interactions many improvements have already been made, including the incorporation +of patches previously maintained in other forks. + +Each PR is reviewed, iterated on, and merged in GitHub. + +To date, NG has had over 40 distinct contributors and over 400 PRs. + +## Consistent release cadence + +As the project moves forward, a steady cadence of releases has been maintained, with an +average of a new release every 2 months. + +## Testing + +Since its inception testing has been a focus. Each PR is tested in over 50 configurations, +involving different operating systems, build types and sanitizers. + +The `test262` suite is also run for every change. + +## Cross-platform support + +In order to better support other platforms such as Windows the build system was +changed to use [CMake]. + +In addition, Windows is treated as a first class citizen, with the addition of support +for the MSVC compiler. + +[CMake]: https://cmake.org/ + +## Performance + +While being an interpreter limits the performance in comparison with other engines which +use a JIT, several significant performance improvements have been made: + +- Opcode fusion +- Polymorphic inline caching +- Memory allocation improvements +- Improved parse speeds + +## New ECMAScript APIs + +The main focus of NG is to deliver state-of-the-art JavaScript features. Typically once they +are stable (stage 4) but sometimes even at earlier stages. Here is a non-exhaustive list +of ES features present in NG: + +- Resizable ArrayBuffer +- Float16Array +- WeakRef +- FinalizationRegistry +- Iterator Helpers +- Promise.try +- Error.isError +- Set operations + +Some non-standard but widely used APIs have also been added: + +- V8's [stack trace API](https://v8.dev/docs/stack-trace-api) + - `Error.captureStackTrace` + - `Error.prepareStackTrace` + - `Error.stackTraceLimit` diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/es_features.md b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/es_features.md new file mode 100755 index 00000000..d57754c9 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/es_features.md @@ -0,0 +1,11 @@ +--- +sidebar_position: 7 +--- + +# ECMAScript Features + +QuickJS aims to support the latest available ECMAScript features once they hit the spec. + +Progress on _test262_ compliance can be checked [here](https://test262.fyi/#|qjs_ng). + +Due to size constraints it is unlikely QuickJS will ever support the [Intl](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) APIs. diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/installation.md b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/installation.md new file mode 100755 index 00000000..5df467c2 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/installation.md @@ -0,0 +1,34 @@ +--- +sidebar_position: 3 +--- + +# Installation + +Installing QuickJS is simple, and we provide several ways to do so. + + +## Build from source + +If you built it from source as outlined in [building](./building) you can just run: + +```bash +make install +``` + +and it will be installed in your system. The default installation path is `/usr/local`. + + +## Using a prebuilt binary + +Each [release on GitHub] includes binaries for several systems and architectures. + + +## Using jsvu + +As of version 2.2.0 of `jsvu`, QuickJS-ng will be installed when the `quickjs` engine is requested. + +```bash +npm install jsvu -g +``` + +[release on GitHub]: https://github.com/quickjs-ng/quickjs/releases diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/intro.md b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/intro.md new file mode 100755 index 00000000..cb63ed5d --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/intro.md @@ -0,0 +1,33 @@ +--- +slug: / +sidebar_position: 1 +sidebar_label: Welcome +--- + +# Welcome to QuickJS-NG + +QuickJS is a small and embeddable JavaScript engine. It aims to support the latest +[ECMAScript] specification. + +This project is a _fork_ of the [original QuickJS project] by Fabrice Bellard and Charlie Gordon, after it went dormant, with the intent of reigniting its development. + +This project is focused on (but not limited to): + +- Community development +- Testing +- Cross-platform support +- ES features + +You can check the differences with the original project [here.](./diff) + +:::note +This site is under construction, the entire API is not yet documented. +::: + +## Getting Started + +Head over to [building](./building) if you want to build QuickJS from source or [installation](./installation) +for installing it from prebuilt binaries. + +[ECMAScript]: https://tc39.es/ecma262/ +[original QuickJS project]: https://bellard.org/quickjs diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/projects.md b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/projects.md new file mode 100755 index 00000000..7dbc21cf --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/projects.md @@ -0,0 +1,94 @@ +# Projects using NG + +Here is a list of projects currently using, supporting or migrating to QuickJS-NG. +If you want yours to be listed here, please open a PR! + +## [txiki.js](https://github.com/saghul/txiki.js) + +A tiny JavaScript runtime. + +## [radare2](https://github.com/radareorg/radare2) + +Reverse engineering framework. + +## [rquickjs](https://github.com/DelSkayn/rquickjs) + +High level Rust bindings. + +## [llrt](https://github.com/awslabs/llrt) + +Lightweight JS runtime for serverless applications. + +## [nx.js](https://github.com/TooTallNate/nx.js) + +JavaScript runtime for Nintendo Switch homebrew applications. + +## [quickjs-rusty](https://github.com/Icemic/quickjs-rusty) + +Rust wrapper focus on embedding-ready and no-pain type conversion and interoperability. + +## [CSPro](https://github.com/csprousers/cspro) + +CSPro incorporates the QuickJS-NG engine as its embedded JavaScript runtime for executing logic, complementing its own domain-specific language, CSPro Logic. + +## [GodotJS](https://github.com/godotjs/GodotJS) + +This project adds TypeScript/JavaScript support for Godot 4.x. It supports multiple javascript runtimes, including QuickJS-NG. + +## [quickjs_es_runtime](https://github.com/HiRoFa/quickjs_es_runtime) + +Rust wrapper with typescript, modules, promises, async/await and much more. + +## [Lua jsregexp](https://github.com/kmarius/jsregexp) + +JavaScript regular expressions for Lua. + +## [Edbrowse](https://edbrowse.org) + +A combination editor, web-browser, and mail client that is 100% text based. + +## [go-quickjs-wasi-reactor](https://github.com/aperturerobotics/go-quickjs-wasi-reactor) + +Go module that embeds QuickJS-NG compiled to WebAssembly using the WASI reactor model. Provides re-entrant execution via exported C API functions, a high-level Go API with wazero, non-blocking event loop control, and a command-line REPL. + +## [js-quickjs-wasi-reactor](https://github.com/aperturerobotics/js-quickjs-wasi-reactor) + +JavaScript/TypeScript harness for running QuickJS-NG in WASI reactor mode. Includes a browser-compatible WASI shim, virtual filesystem, custom I/O handlers, and non-blocking event loop integration for browser and Node.js/Bun environments. + +## [quickjs.ml](https://github.com/ml-in-barcelona/quickjs.ml) + +OCaml bindings to quickjs-ng. Exposing both low-level C library access (libregexp, libunicode, js_dtoa, js_atod, and cutils) and a high-level API mirroring JavaScript built-ins like RegExp, String, and Number. + +## [Python quickjs-ng](https://github.com/genotrance/quickjs-ng) + +Python bindings for quickjs-ng based on https://github.com/PetterS/quickjs. + +## [Px](https://github.com/genotrance/px) + +Proxy server using quickjs-ng for PAC file processing. + +## [std::slop](https://github.com/hsaliak/std_slop) + +A C++/SQL based Coding agent. It exposes a QuickJS-ng environment to the LLM. The Agent accomplishes all it's work through this QuickJS-NG based "control plane". + +## [QuickBEAM](https://github.com/elixir-volt/quickbeam) + +JavaScript runtime for the BEAM - Web APIs backed by OTP, native DOM, and a built-in TypeScript toolchain. + +## [quickjs-go](https://github.com/buke/quickjs-go) + +Golang bindings for QuickJS-NG using cgo + +## [Nordstjernen](https://github.com/nordstjernen-web/nordstjernen) + +Nordstjernen web browser. + +## [quickjs-cpp](https://github.com/qr243vbi/quickjs-cpp) + +Header only library for quickjs-ng with modern C++ interface (Archived). + +## [NekoBox](https://github.com/qr243vbi/nekobox) + +A lightweight proxy client, empowered by sing-box and thrift. + + diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/stdlib.md b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/stdlib.md new file mode 100755 index 00000000..f579760d --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/stdlib.md @@ -0,0 +1,605 @@ +--- +sidebar_position: 5 +--- + +# Standard library + +The standard libary is provided as part of the `qjs` executable and the `quickjs-libc.c` source file +and it's not part of the core engine. + +## Globals + +### `argv0` + +Provides the executable path. + +### `scriptArgs` + +Provides the command line arguments. The first argument is the script name. + +### `print(...args)` + +Print the arguments separated by spaces and a trailing newline. + +### `console.log(...args)` + +Same as `print()`. + +### `navigator.userAgent` + +Returns `quickjs-ng/`. + +### `gc()` + +Shorthand for `std.gc()`. + +## `qjs:bjson` module + +### `bjson.write(obj, [flags])` + +Serializes the given object into the QuickJS internal serialization format. +Returns an ArrayBuffer with the serialized data. + +Supported flags: + +- `WRITE_OBJ_BYTECODE`: allow serializing functions and modules +- `WRITE_OBJ_REFERENCE`: allow serializing object references +- `WRITE_OBJ_SAB`: allow serializing SharedArrayBuffer instances +- `WRITE_OBJ_STRIP_DEBUG`: strip debugging information when serializing +- `WRITE_OBJ_STRIP_SOURCE`: strip the source information when serializing + +### `bjson.read(buf, [pos], [len], [flags])` + +De-serialize the given ArrayBuffer (in QuickJS internal serialization format) back into a JavaScript value. + +Supported flags: + +- `READ_OBJ_BYTECODE`: allow de-serializing functions and modules +- `READ_OBJ_REFERENCE`: allow de-serializing object references + +Security caveat: `bjson.read()` is resilient against malformed input (the wire +format is checksummed) but is not designed to withstand adversarial attacks. +Don't feed it untrusted input. + +## `qjs:os` module + +The `os` module provides Operating System specific functions: + +- low level file access +- signals +- timers +- basic asynchronous I/O +- workers (threads) + +The OS functions usually return 0 if OK or an OS specific negative +error code. + +### `open(filename, flags, mode = 0o666)` + +Open a file. Return a handle or < 0 if error. + +Supported flags: + +- `O_RDONLY` +- `O_WRONLY` +- `O_RDWR` +- `O_APPEND` +- `O_CREAT` +- `O_EXCL` +- `O_TRUNC` + +POSIX open flags. + +- `O_TEXT` + +(Windows specific). Open the file in text mode. The default is binary mode. + +### `close(fd)` + +Close the file handle `fd`. + +### `seek(fd, offset, whence)` + +Seek in the file. Use `std.SEEK_*` for +`whence`. `offset` is either a number or a BigInt. If +`offset` is a BigInt, a BigInt is returned too. + +### `read(fd, buffer, offset, length)` + +Read `length` bytes from the file handle `fd` to the +ArrayBuffer `buffer` at byte position `offset`. +Return the number of read bytes or < 0 if error. + +### `write(fd, buffer, offset, length)` + +Write `length` bytes to the file handle `fd` from the +ArrayBuffer `buffer` at byte position `offset`. +Return the number of written bytes or < 0 if error. + +### `isatty(fd)` + +Return `true` is `fd` is a TTY (terminal) handle. + +### `ttyGetWinSize(fd)` + +Return the TTY size as `[width, height]` or `null` if not available. + +### `ttySetRaw(fd)` + +Set the TTY in raw mode. + +### `remove(filename)` + +Remove a file. Return 0 if OK or `-errno`. + +### `rename(oldname, newname)` + +Rename a file. Return 0 if OK or `-errno`. + +### `realpath(path)` + +Return `[str, err]` where `str` is the canonicalized absolute +pathname of `path` and `err` the error code. + +### `getcwd()` + +Return `[str, err]` where `str` is the current working directory +and `err` the error code. + +### `exePath()` + +Returns the full path of the current executable or `undefined` if not available / supported. + +### `chdir(path)` + +Change the current directory. Return 0 if OK or `-errno`. + +### `mkdir(path, mode = 0o777)` + +Create a directory at `path`. Return 0 if OK or `-errno`. + +### `mkdtemp(pattern = "tmpXXXXXX")` + +Create a temporary directory. `XXXXXX` must be at the end of the pattern +string and is replaced with a random name. The directory is created with +file mode `0o700`. + +Return `[path, err]` where `path` is a string and `err` is 0 or `-errno`. + +Not available on Windows and WASI. + +### `mkstemp(pattern = "tmpXXXXXX")` + +Create a temporary file and open it. `XXXXXX` must be at the end of the +pattern string and is replaced with a random name. The file is created with +file mode `0o600` and opened in read/write mode. + +Return `[path, fd]` where `path` is a string and `fd` is the file descriptor +or `-errno`, i.e., the error code if less than zero. + +Unlike `std.tmpfile()`, the file is not automatically deleted on close. + +See also `std.fdopen()`. + +Not available on Windows and WASI. + +### `stat(path)` / `lstat(path)` + +Return `[obj, err]` where `obj` is an object containing the +file status of `path`. `err` is the error code. The +following fields are defined in `obj`: `dev`, `ino`, `mode`, `nlink`, +`uid`, `gid`, `rdev`, `size`, `blocks`, `atime`, `mtime`, `ctime`. The times are +specified in milliseconds since 1970. `lstat()` is the same as +`stat()` excepts that it returns information about the link +itself. + +- `S_IFMT` +- `S_IFIFO` +- `S_IFCHR` +- `S_IFDIR` +- `S_IFBLK` +- `S_IFREG` +- `S_IFSOCK` +- `S_IFLNK` +- `S_ISGID` +- `S_ISUID` + +Constants to interpret the `mode` property returned by +`stat()`. They have the same value as in the C system header +`sys/stat.h`. + +### `utimes(path, atime, mtime)` + +Change the access and modification times of the file `path`. The +times are specified in milliseconds since 1970. Return 0 if OK or `-errno`. + +### `symlink(target, linkpath)` + +Create a link at `linkpath` containing the string `target`. Return 0 if OK or `-errno`. + +### `readlink(path)` + +Return `[str, err]` where `str` is the link target and `err` +the error code. + +### `readdir(path)` + +Return `[array, err]` where `array` is an array of strings +containing the filenames of the directory `path`. `err` is +the error code. `array` contains at least `"."` and `".."` +if successful. + +### `setReadHandler(fd, func)` + +Add a read handler to the file handle `fd`. `func` is called +each time there is data pending for `fd`. A single read handler +per file handle is supported. Use `func = null` to remove the +handler. + +### `setWriteHandler(fd, func)` + +Add a write handler to the file handle `fd`. `func` is +called each time data can be written to `fd`. A single write +handler per file handle is supported. Use `func = null` to remove +the handler. + +### `signal(signal, func)` + +Call the function `func` when the signal `signal` +happens. Only a single handler per signal number is supported. Use +`null` to set the default handler or `undefined` to ignore +the signal. Signal handlers can only be defined in the main thread. + +- `SIGINT` +- `SIGABRT` +- `SIGFPE` +- `SIGILL` +- `SIGSEGV` +- `SIGTERM` + +POSIX signal numbers. + +### `kill(pid, sig)` + +Send the signal `sig` to the process `pid`. + +### `exec(args[, options])` + +Execute a process with the arguments `args`. `options` is an +object containing optional parameters: + +- `block` - Boolean (default = true). If true, wait until the process is + terminated. In this case, `exec` return the exit code if positive + or the negated signal number if the process was interrupted by a + signal. If false, do not block and return the process id of the child. +- `usePath` - Boolean (default = true). If true, the file is searched in the + `PATH` environment variable. +- `file` - String (default = `args[0]`). Set the file to be executed. +- `cwd` - String. If present, set the working directory of the new process. +- `stdin`, `stdout`, `stderr` - If present, set the handle in the child for stdin, stdout or stderr. +- `env` - Object. If present, set the process environment from the object + key-value pairs. Otherwise use the same environment as the current + process. +- `uid` - Integer. If present, the process uid with `setuid`. +- `gid` - Integer. If present, the process gid with `setgid`. +- `groups` - Array of integer. If present, the supplementary + group IDs with `setgroup`. + +### `waitpid(pid, options)` + +`waitpid` Unix system call. Return the array `[ret, status]`. +`ret` contains `-errno` in case of error. + +- `WNOHANG` + +Constant for the `options` argument of `waitpid`. + +### `dup(fd)` + +`dup` Unix system call. + +### `dup2(oldfd, newfd)` + +`dup2` Unix system call. + +### `pipe()` + +`pipe` Unix system call. Return two handles as `[read_fd, write_fd]` or null in case of error. + +### `sleep(delay_ms)` + +Sleep during `delay_ms` milliseconds. + +### `sleepAsync(delay_ms)` + +Asynchronouse sleep during `delay_ms` milliseconds. Returns a promise. Example: + +```js +await os.sleepAsync(500); +``` + +### `setTimeout(func, delay)` + +Call the function `func` after `delay` ms. Return a timer ID. + +### `clearTimeout(id)` + +Cancel a timer. + +### `platform` + +Return a string representing the platform: `"linux"`, `"darwin"`, `"win32"` or `"js"`. + +### `Worker(module_filename)` + +Constructor to create a new thread (worker) with an API close to that of +`WebWorkers`. `module_filename` is a string specifying the +module filename which is executed in the newly created thread. As for +dynamically imported module, it is relative to the current script or +module path. Threads normally don't share any data and communicate +between each other with messages. Nested workers are not supported. An +example is available in `tests/test_worker.js`. + +The worker class has the following static properties: + +- `parent` - In the created worker, `Worker.parent` represents the parent + worker and is used to send or receive messages. + +The worker instances have the following properties: + +- `postMessage(msg)` - Send a message to the corresponding worker. `msg` is cloned in + the destination worker using an algorithm similar to the `HTML` + structured clone algorithm. `SharedArrayBuffer` are shared + between workers. + +- `onmessage` - Getter and setter. Set a function which is called each time a + message is received. The function is called with a single + argument. It is an object with a `data` property containing the + received message. The thread is not terminated if there is at least + one non `null` `onmessage` handler. + +## `qjs:std` module + +The `std` module provides wrappers to libc (`stdlib.h` and `stdio.h`) and a few other utilities. + +### `exit(n)` + +Exit the process. + +### `evalScript(str, options = undefined)` + +Evaluate the string `str` as a script (global +eval). `options` is an optional object containing the following +optional properties: + +- `backtrace_barrier` - Boolean (default = false). If true, error backtraces do not list the + stack frames below the evalScript. +- `async` - Boolean (default = false). If true, `await` is accepted in the + script and a promise is returned. The promise is resolved with an + object whose `value` property holds the value returned by the + script. + +### `loadScript(filename)` + +Evaluate the file `filename` as a script (global eval). + +### `loadFile(filename, [options])` + +Load the file `filename` and return it as a string assuming UTF-8 +encoding. Return `null` in case of I/O error. + +If `options.binary` is set to `true` a `Uint8Array` is returned instead. + +### `writeFile(filename, data)` + +Create the file `filename` and write `data` into it. + +`data` can be a string, a typed array or an `ArrayBuffer`. `undefined` is +treated as the empty string. + +When `data` is a string, the file is opened in text mode; otherwise it is +opened in binary mode. (This distinction is only relevant on Windows.) + +Throws an exception if the file cannot be created or written to. + +### `open(filename, flags, errorObj = undefined)` + +Open a file (wrapper to the libc `fopen()`). Return the FILE +object or `null` in case of I/O error. If `errorObj` is not +undefined, set its `errno` property to the error code or to 0 if +no error occurred. + +### `popen(command, flags, errorObj = undefined)` + +Open a process by creating a pipe (wrapper to the libc +`popen()`). Return the FILE +object or `null` in case of I/O error. If `errorObj` is not +undefined, set its `errno` property to the error code or to 0 if +no error occurred. + +### `fdopen(fd, flags, errorObj = undefined)` + +Open a file from a file handle (wrapper to the libc +`fdopen()`). Return the FILE +object or null` in case of I/O error. If `errorObj` is not +undefined, set its `errno` property to the error code or to 0 if +no error occurred. + +### `tmpfile(errorObj = undefined)` + +Open a temporary file. Return the FILE +object or `null` in case of I/O error. If `errorObj` is not +undefined, set its `errno` property to the error code or to 0 if +no error occurred. + +### `puts(str)` + +Equivalent to `std.out.puts(str)`. + +### `printf(fmt, ...args)` + +Equivalent to `std.out.printf(fmt, ...args)`. + +### `sprintf(fmt, ...args)` + +Equivalent to the libc sprintf(). + +### `in`, `out`, `err` + +Wrappers to the libc file `stdin`, `stdout`, `stderr`. + +### `Error` + +Enumeration object containing the integer value of common errors +(additional error codes may be defined): + +- `EINVAL` +- `EIO` +- `EACCES` +- `EEXIST` +- `ENOSPC` +- `ENOSYS` +- `EBUSY` +- `ENOENT` +- `EPERM` +- `EPIPE` + +### `strerror(errno)` + +Return a string that describes the error `errno`. + +### `gc()` + +Manually invoke the cycle removal algorithm. The cycle removal +algorithm is automatically started when needed, so this function is +useful in case of specific memory constraints or for testing. + +### `getenv(name)` + +Return the value of the environment variable `name` or +`undefined` if it is not defined. + +### `setenv(name, value)` + +Set the value of the environment variable `name` to the string +`value`. + +### `unsetenv(name)` + +Delete the environment variable `name`. + +### `getenviron()` + +Return an object containing the environment variables as key-value pairs. + +### `urlGet(url, options = undefined)` + +Download `url` using the `curl` command line +utility. `options` is an optional object containing the following +optional properties: + +- `binary` - Boolean (default = false). If true, the response is an ArrayBuffer + instead of a string. When a string is returned, the data is assumed + to be UTF-8 encoded. +- `full` - Boolean (default = false). If true, return the an object contains + the properties `response` (response content), + `responseHeaders` (headers separated by CRLF), `status` + (status code). `response` is `null` is case of protocol or + network error. If `full` is false, only the response is + returned if the status is between 200 and 299. Otherwise `null` + is returned. + +### `FILE` + +File object. + +#### `close()` + +Close the file. Return 0 if OK or `-errno` in case of I/O error. + +#### `puts(str)` + +Outputs the string with the UTF-8 encoding. + +#### `printf(fmt, ...args)` + +Formatted printf. + +The same formats as the standard C library `printf` are +supported. Integer format types (e.g. `%d`) truncate the Numbers +or BigInts to 32 bits. Use the `l` modifier (e.g. `%ld`) to +truncate to 64 bits. + +#### `flush()` + +Flush the buffered file. + +#### `seek(offset, whence)` + +Seek to a give file position (whence is +`std.SEEK_*`). `offset` can be a number or a BigInt. Return +0 if OK or `-errno` in case of I/O error. + +- `SEEK_SET` +- `SEEK_CUR` +- `SEEK_END` + +Constants for seek(). + +#### `tell()` + +Return the current file position. + +#### `tello()` + +Return the current file position as a BigInt. + +#### `eof()` + +Return true if end of file. + +#### `fileno()` + +Return the associated OS handle. + +#### `error()` + +Return true if there was an error. + +#### `clearerr()` + +Clear the error indication. + +#### `read(buffer, position = 0, length = buffer.length)` + +Read `length` bytes from the file to the ArrayBuffer `buffer` at byte +position `position`. Wrapper to the libc function `fread`. + +#### `write(buffer, position = 0, length = buffer.length)` + +Write `length` bytes to the file from the ArrayBuffer or string `buffer` +at byte position `position`. Wrapper to the libc function `fwrite`. + +#### `getline()` + +Return the next line from the file, assuming UTF-8 encoding, excluding +the trailing line feed. + +#### `readAsArrayBuffer(max_size = undefined)` + +Read `max_size` bytes from the file and return them as an ArrayBuffer. +If `max_size` is not present, the file is read until its end. + +#### `readAsString(max_size = undefined)` + +Read `max_size` bytes from the file and return them as a string +assuming UTF-8 encoding. If `max_size` is not present, the file +is read until its end. + +#### `getByte()` + +Return the next byte from the file. Return -1 if the end of file is reached. + +#### `putByte(c)` + +Write one byte to the file. diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/supported_platforms.md b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/supported_platforms.md new file mode 100755 index 00000000..bb817b3d --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docs/supported_platforms.md @@ -0,0 +1,20 @@ +--- +sidebar_position: 8 +--- + +# Supported Platforms + +| System | Supported versions | Notes | +|---|---|---| +| GNU/Linux | * | glibc and musl are supported | +| macOS | macOS >= 11 | Currently supported macOS releases | +| Windows | >= Windows 7* | VS >= 2022 and Clang are supported; requires `` | +| FreeBSD | * | Limited testing | +| OpenBSD | * | Limited testing | +| NetBSD | * | Limited testing | +| Android | NDK >= 26.0.10792818 | Limited testing | +| iOS | * | Limited testing | +| MinGW | MinGW-w64 | | +| Other | N/A | Missing? Open a PR! | + +- `*`: Windows 7 is EOL and only supported in this project as long as it doesn't interfere with its progress. diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docusaurus.config.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docusaurus.config.js new file mode 100755 index 00000000..25524eda --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/docusaurus.config.js @@ -0,0 +1,114 @@ +// @ts-check +// `@type` JSDoc annotations allow editor autocompletion and type checking +// (when paired with `@ts-check`). +// There are various equivalent ways to declare your Docusaurus config. +// See: https://docusaurus.io/docs/api/docusaurus-config + +/** @type {import('@docusaurus/types').Config} */ +const config = { + title: 'QuickJS-NG', + tagline: 'QuickJS, the Next Generation: a mighty JavaScript engine', + favicon: 'img/favicon.ico', + + // Set the production url of your site here + url: 'https://quickjs-ng.github.io', + // Set the // pathname under which your site is served + // For GitHub pages deployment, it is often '//' + baseUrl: '/quickjs/', + + // GitHub pages deployment config. + // If you aren't using GitHub pages, you don't need these. + organizationName: 'quickjs-ng', // Usually your GitHub org/user name. + projectName: 'quickjs', // Usually your repo name. + + onBrokenLinks: 'throw', + onBrokenMarkdownLinks: 'throw', + + // Even if you don't use internationalization, you can use this field to set + // useful metadata like html lang. For example, if your site is Chinese, you + // may want to replace "en" with "zh-Hans". + i18n: { + defaultLocale: 'en', + locales: ['en'], + }, + + presets: [ + [ + 'classic', + /** @type {import('@docusaurus/preset-classic').Options} */ + ({ + docs: { + routeBasePath: '/', + sidebarPath: './sidebars.js', + // Please change this to your repo. + // Remove this to remove the "edit this page" links. + editUrl: 'https://github.com/quickjs-ng/quickjs/tree/master/docs/', + }, + blog: false, + theme: { + customCss: './src/css/custom.css', + }, + }), + ], + ], + + themeConfig: + /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ + ({ + // Replace with your project's social card + image: 'img/docusaurus-social-card.jpg', + navbar: { + title: 'QuickJS-NG', + items: [ + { + type: 'docSidebar', + sidebarId: 'docsSidebar', + position: 'left', + label: 'Documentation', + }, + { + href: 'https://github.com/quickjs-ng/quickjs', + label: 'GitHub', + position: 'right', + }, + ], + }, + footer: { + style: 'dark', + links: [ + { + title: 'Docs', + items: [ + ], + }, + { + title: 'Community', + items: [ + { + label: 'GitHub Discussions', + href: 'https://github.com/quickjs-ng/quickjs/discussions', + }, + { + label: 'Matrix', + href: 'https://matrix.to/#/%23quickjs-ng%3Amatrix.org?via=matrix.org', + }, + ], + }, + { + title: 'More', + items: [ + { + label: 'GitHub', + href: 'https://github.com/quickjs-ng/quickjs', + }, + ], + }, + ], + copyright: `Copyright © ${new Date().getFullYear()} QuickJS-NG project contributors.`, + }, + prism: { + }, + }), +}; + +export default config; diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/package-lock.json b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/package-lock.json new file mode 100755 index 00000000..f13c2d8c --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/package-lock.json @@ -0,0 +1,14656 @@ +{ + "name": "docs", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/preset-classic": "3.5.2", + "@mdx-js/react": "3.0.1", + "clsx": "2.1.1", + "prism-react-renderer": "2.4.0", + "react": "18.3.1", + "react-dom": "18.3.1" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "3.5.2", + "@docusaurus/types": "3.5.2" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", + "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", + "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", + "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", + "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/cache-browser-local-storage": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.24.0.tgz", + "integrity": "sha512-t63W9BnoXVrGy9iYHBgObNXqYXM3tYXCjDSHeNwnsc324r4o5UiVKUiAB4THQ5z9U5hTj6qUvwg/Ez43ZD85ww==", + "dependencies": { + "@algolia/cache-common": "4.24.0" + } + }, + "node_modules/@algolia/cache-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.24.0.tgz", + "integrity": "sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g==" + }, + "node_modules/@algolia/cache-in-memory": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.24.0.tgz", + "integrity": "sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w==", + "dependencies": { + "@algolia/cache-common": "4.24.0" + } + }, + "node_modules/@algolia/client-account": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.24.0.tgz", + "integrity": "sha512-adcvyJ3KjPZFDybxlqnf+5KgxJtBjwTPTeyG2aOyoJvx0Y8dUQAEOEVOJ/GBxX0WWNbmaSrhDURMhc+QeevDsA==", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-account/node_modules/@algolia/client-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", + "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "dependencies": { + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-account/node_modules/@algolia/client-search": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", + "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.24.0.tgz", + "integrity": "sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg==", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-analytics/node_modules/@algolia/client-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", + "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "dependencies": { + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-analytics/node_modules/@algolia/client-search": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", + "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.5.3.tgz", + "integrity": "sha512-3rdSdreBL2LGYu4DWmUGlMhaGy1vy36Xp42LdbTFsW/y3bhW5viptMHI5A3PKT0hPEMZUn+te1iM/EWvLUuVGQ==", + "peer": true, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.24.0.tgz", + "integrity": "sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w==", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-personalization/node_modules/@algolia/client-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", + "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "dependencies": { + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.5.3.tgz", + "integrity": "sha512-qrokD+uoNxchbiF9aP8niQd/9SZ6BgYg4WaesFaubHhr9DFvwGm4IePEMha8vQcc3fSsY6uL+gOtKB3J6RF0NQ==", + "peer": true, + "dependencies": { + "@algolia/client-common": "5.5.3", + "@algolia/requester-browser-xhr": "5.5.3", + "@algolia/requester-fetch": "5.5.3", + "@algolia/requester-node-http": "5.5.3" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/events": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", + "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" + }, + "node_modules/@algolia/logger-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.24.0.tgz", + "integrity": "sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA==" + }, + "node_modules/@algolia/logger-console": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.24.0.tgz", + "integrity": "sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg==", + "dependencies": { + "@algolia/logger-common": "4.24.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.24.0.tgz", + "integrity": "sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw==", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/recommend/node_modules/@algolia/client-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", + "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "dependencies": { + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/recommend/node_modules/@algolia/client-search": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", + "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/recommend/node_modules/@algolia/requester-browser-xhr": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz", + "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==", + "dependencies": { + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@algolia/recommend/node_modules/@algolia/requester-node-http": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz", + "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==", + "dependencies": { + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.5.3.tgz", + "integrity": "sha512-LsfUPokiXEpvlYF7SwNjyyjkUX7IoW7oIhH6WkDUD4PCfEZkFbVplGQA0UrCiWOAbpb25P7mmP6+ldwjwqW6Kg==", + "peer": true, + "dependencies": { + "@algolia/client-common": "5.5.3" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.24.0.tgz", + "integrity": "sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA==" + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.5.3.tgz", + "integrity": "sha512-RKaliEFHtVeD/fMxwrApkcI6ZxR+mU6pZna29r3NwVMpCXTJWWtlMpQmbr1RHzUsaAlpfv9pfGJN4nYPE8XWEg==", + "peer": true, + "dependencies": { + "@algolia/client-common": "5.5.3" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-node-http": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.5.3.tgz", + "integrity": "sha512-2wU+HlTVrVce7BMW2b3Gd62btk8B0jBbuKYYzu3OFeBD/aZa88eHABtjcjQCdw3x+wvkIPEc56UsZx9eHYLebg==", + "peer": true, + "dependencies": { + "@algolia/client-common": "5.5.3" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/transporter": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.24.0.tgz", + "integrity": "sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA==", + "dependencies": { + "@algolia/cache-common": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "dependencies": { + "@babel/types": "^7.25.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "dependencies": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", + "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/traverse": "^7.25.4", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", + "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "dependencies": { + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", + "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "dependencies": { + "@babel/types": "^7.25.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", + "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", + "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", + "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", + "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz", + "integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", + "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", + "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz", + "integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", + "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz", + "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz", + "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/traverse": "^7.25.4", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", + "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", + "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", + "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", + "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz", + "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.1.tgz", + "integrity": "sha512-SLV/giH/V4SmloZ6Dt40HjTGTAIkxn33TVIHxNGNvo8ezMhrxBkzisj4op1KZYPIOHFLqhv60OHvX+YRu4xbmQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz", + "integrity": "sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.25.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.4.tgz", + "integrity": "sha512-8hsyG+KUYGY0coX6KUCDancA0Vw225KJ2HJO0yCNr1vq5r+lJTleDaJf0K7iOhjw4SWhu03TMBzYTJ9krmzULQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", + "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz", + "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz", + "integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==", + "dependencies": { + "@babel/compat-data": "^7.25.4", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.25.0", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.25.4", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.4", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", + "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.25.6.tgz", + "integrity": "sha512-Gz0Nrobx8szge6kQQ5Z5MX9L3ObqNwCQY1PSwSNzreFL7aHGxv8Fp2j3ETV6/wWdbiV+mW6OSm8oQhg3Tcsniw==", + "dependencies": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.1.tgz", + "integrity": "sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg==" + }, + "node_modules/@docsearch/react": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.1.tgz", + "integrity": "sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw==", + "dependencies": { + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.6.1", + "algoliasearch": "^4.19.1" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@docusaurus/core": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.5.2.tgz", + "integrity": "sha512-4Z1WkhCSkX4KO0Fw5m/Vuc7Q3NxBG53NE5u59Rs96fWkMPZVSrzEPP16/Nk6cWb/shK7xXPndTmalJtw7twL/w==", + "dependencies": { + "@babel/core": "^7.23.3", + "@babel/generator": "^7.23.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.22.9", + "@babel/preset-env": "^7.22.9", + "@babel/preset-react": "^7.22.5", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@babel/runtime-corejs3": "^7.22.6", + "@babel/traverse": "^7.22.8", + "@docusaurus/cssnano-preset": "3.5.2", + "@docusaurus/logger": "3.5.2", + "@docusaurus/mdx-loader": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", + "autoprefixer": "^10.4.14", + "babel-loader": "^9.1.3", + "babel-plugin-dynamic-import-node": "^2.3.3", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "clean-css": "^5.3.2", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "copy-webpack-plugin": "^11.0.0", + "core-js": "^3.31.1", + "css-loader": "^6.8.1", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "del": "^6.1.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "html-minifier-terser": "^7.2.0", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.5.3", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "mini-css-extract-plugin": "^2.7.6", + "p-map": "^4.0.0", + "postcss": "^8.4.26", + "postcss-loader": "^7.3.3", + "prompts": "^2.4.2", + "react-dev-utils": "^12.0.1", + "react-helmet-async": "^1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.1", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "rtl-detect": "^1.0.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.5", + "shelljs": "^0.8.5", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "url-loader": "^4.1.1", + "webpack": "^5.88.1", + "webpack-bundle-analyzer": "^4.9.0", + "webpack-dev-server": "^4.15.1", + "webpack-merge": "^5.9.0", + "webpackbar": "^5.0.2" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@mdx-js/react": "^3.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/cssnano-preset": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.5.2.tgz", + "integrity": "sha512-D3KiQXOMA8+O0tqORBrTOEQyQxNIfPm9jEaJoALjjSjc2M/ZAWcUfPQEnwr2JB2TadHw2gqWgpZckQmrVWkytA==", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.4.38", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/logger": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.5.2.tgz", + "integrity": "sha512-LHC540SGkeLfyT3RHK3gAMK6aS5TRqOD4R72BEU/DE2M/TY8WwEUAMY576UUc/oNJXv8pGhBmQB6N9p3pt8LQw==", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/mdx-loader": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.5.2.tgz", + "integrity": "sha512-ku3xO9vZdwpiMIVd8BzWV0DCqGEbCP5zs1iHfKX50vw6jX8vQo0ylYo1YJMZyz6e+JFJ17HYHT5FzVidz2IflA==", + "dependencies": { + "@docusaurus/logger": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^1.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/module-type-aliases": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.5.2.tgz", + "integrity": "sha512-Z+Xu3+2rvKef/YKTMxZHsEXp1y92ac0ngjDiExRdqGTmEKtCUpkbNYH8v5eXo5Ls+dnW88n6WTa+Q54kLOkwPg==", + "dependencies": { + "@docusaurus/types": "3.5.2", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "@types/react-router-dom": "*", + "react-helmet-async": "*", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@docusaurus/plugin-content-blog": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.5.2.tgz", + "integrity": "sha512-R7ghWnMvjSf+aeNDH0K4fjyQnt5L0KzUEnUhmf1e3jZrv3wogeytZNN6n7X8yHcMsuZHPOrctQhXWnmxu+IRRg==", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/logger": "3.5.2", + "@docusaurus/mdx-loader": "3.5.2", + "@docusaurus/theme-common": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", + "cheerio": "1.0.0-rc.12", + "feed": "^4.2.2", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "reading-time": "^1.5.0", + "srcset": "^4.0.0", + "tslib": "^2.6.0", + "unist-util-visit": "^5.0.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/plugin-content-docs": "*", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.5.2.tgz", + "integrity": "sha512-Bt+OXn/CPtVqM3Di44vHjE7rPCEsRCB/DMo2qoOuozB9f7+lsdrHvD0QCHdBs0uhz6deYJDppAr2VgqybKPlVQ==", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/logger": "3.5.2", + "@docusaurus/mdx-loader": "3.5.2", + "@docusaurus/module-type-aliases": "3.5.2", + "@docusaurus/theme-common": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", + "@types/react-router-config": "^5.0.7", + "combine-promises": "^1.1.0", + "fs-extra": "^11.1.1", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.5.2.tgz", + "integrity": "sha512-WzhHjNpoQAUz/ueO10cnundRz+VUtkjFhhaQ9jApyv1a46FPURO4cef89pyNIOMny1fjDz/NUN2z6Yi+5WUrCw==", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/mdx-loader": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-debug": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.5.2.tgz", + "integrity": "sha512-kBK6GlN0itCkrmHuCS6aX1wmoWc5wpd5KJlqQ1FyrF0cLDnvsYSnh7+ftdwzt7G6lGBho8lrVwkkL9/iQvaSOA==", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils": "3.5.2", + "fs-extra": "^11.1.1", + "react-json-view-lite": "^1.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.5.2.tgz", + "integrity": "sha512-rjEkJH/tJ8OXRE9bwhV2mb/WP93V441rD6XnM6MIluu7rk8qg38iSxS43ga2V2Q/2ib53PcqbDEJDG/yWQRJhQ==", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.5.2.tgz", + "integrity": "sha512-lm8XL3xLkTPHFKKjLjEEAHUrW0SZBSHBE1I+i/tmYMBsjCcUB5UJ52geS5PSiOCFVR74tbPGcPHEV/gaaxFeSA==", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", + "@types/gtag.js": "^0.0.12", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.5.2.tgz", + "integrity": "sha512-QkpX68PMOMu10Mvgvr5CfZAzZQFx8WLlOiUQ/Qmmcl6mjGK6H21WLT5x7xDmcpCoKA/3CegsqIqBR+nA137lQg==", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.5.2.tgz", + "integrity": "sha512-DnlqYyRAdQ4NHY28TfHuVk414ft2uruP4QWCH//jzpHjqvKyXjj2fmDtI8RPUBh9K8iZKFMHRnLtzJKySPWvFA==", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/logger": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", + "fs-extra": "^11.1.1", + "sitemap": "^7.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/preset-classic": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.5.2.tgz", + "integrity": "sha512-3ihfXQ95aOHiLB5uCu+9PRy2gZCeSZoDcqpnDvf3B+sTrMvMTr8qRUzBvWkoIqc82yG5prCboRjk1SVILKx6sg==", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/plugin-content-blog": "3.5.2", + "@docusaurus/plugin-content-docs": "3.5.2", + "@docusaurus/plugin-content-pages": "3.5.2", + "@docusaurus/plugin-debug": "3.5.2", + "@docusaurus/plugin-google-analytics": "3.5.2", + "@docusaurus/plugin-google-gtag": "3.5.2", + "@docusaurus/plugin-google-tag-manager": "3.5.2", + "@docusaurus/plugin-sitemap": "3.5.2", + "@docusaurus/theme-classic": "3.5.2", + "@docusaurus/theme-common": "3.5.2", + "@docusaurus/theme-search-algolia": "3.5.2", + "@docusaurus/types": "3.5.2" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-classic": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.5.2.tgz", + "integrity": "sha512-XRpinSix3NBv95Rk7xeMF9k4safMkwnpSgThn0UNQNumKvmcIYjfkwfh2BhwYh/BxMXQHJ/PdmNh22TQFpIaYg==", + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/mdx-loader": "3.5.2", + "@docusaurus/module-type-aliases": "3.5.2", + "@docusaurus/plugin-content-blog": "3.5.2", + "@docusaurus/plugin-content-docs": "3.5.2", + "@docusaurus/plugin-content-pages": "3.5.2", + "@docusaurus/theme-common": "3.5.2", + "@docusaurus/theme-translations": "3.5.2", + "@docusaurus/types": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "copy-text-to-clipboard": "^3.2.0", + "infima": "0.2.0-alpha.44", + "lodash": "^4.17.21", + "nprogress": "^0.2.0", + "postcss": "^8.4.26", + "prism-react-renderer": "^2.3.0", + "prismjs": "^1.29.0", + "react-router-dom": "^5.3.4", + "rtlcss": "^4.1.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-common": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.5.2.tgz", + "integrity": "sha512-QXqlm9S6x9Ibwjs7I2yEDgsCocp708DrCrgHgKwg2n2AY0YQ6IjU0gAK35lHRLOvAoJUfCKpQAwUykB0R7+Eew==", + "dependencies": { + "@docusaurus/mdx-loader": "3.5.2", + "@docusaurus/module-type-aliases": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^2.0.0", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^2.3.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/plugin-content-docs": "*", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.5.2.tgz", + "integrity": "sha512-qW53kp3VzMnEqZGjakaV90sst3iN1o32PH+nawv1uepROO8aEGxptcq2R5rsv7aBShSRbZwIobdvSYKsZ5pqvA==", + "dependencies": { + "@docsearch/react": "^3.5.2", + "@docusaurus/core": "3.5.2", + "@docusaurus/logger": "3.5.2", + "@docusaurus/plugin-content-docs": "3.5.2", + "@docusaurus/theme-common": "3.5.2", + "@docusaurus/theme-translations": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-validation": "3.5.2", + "algoliasearch": "^4.18.0", + "algoliasearch-helper": "^3.13.3", + "clsx": "^2.0.0", + "eta": "^2.2.0", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-translations": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.5.2.tgz", + "integrity": "sha512-GPZLcu4aT1EmqSTmbdpVrDENGR2yObFEX8ssEFYTCiAIVc0EihNSdOIBTazUvgNqwvnoU1A8vIs1xyzc3LITTw==", + "dependencies": { + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/types": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.5.2.tgz", + "integrity": "sha512-N6GntLXoLVUwkZw7zCxwy9QiuEXIcTVzA9AkmNw16oc0AP3SXLrMmDMMBIfgqwuKWa6Ox6epHol9kMtJqekACw==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/utils": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.5.2.tgz", + "integrity": "sha512-33QvcNFh+Gv+C2dP9Y9xWEzMgf3JzrpL2nW9PopidiohS1nDcyknKRx2DWaFvyVTTYIkkABVSr073VTj/NITNA==", + "dependencies": { + "@docusaurus/logger": "3.5.2", + "@docusaurus/utils-common": "3.5.2", + "@svgr/webpack": "^8.1.0", + "escape-string-regexp": "^4.0.0", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "shelljs": "^0.8.5", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/types": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/types": { + "optional": true + } + } + }, + "node_modules/@docusaurus/utils-common": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.5.2.tgz", + "integrity": "sha512-i0AZjHiRgJU6d7faQngIhuHKNrszpL/SHQPgF1zH4H+Ij6E9NBYGy6pkcGWToIv7IVPbs+pQLh1P3whn0gWXVg==", + "dependencies": { + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/types": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/types": { + "optional": true + } + } + }, + "node_modules/@docusaurus/utils-validation": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.5.2.tgz", + "integrity": "sha512-m+Foq7augzXqB6HufdS139PFxDC5d5q2QKZy8q0qYYvGdI6nnlNsGH4cIGsgBnV7smz+mopl3g4asbSDvMV0jA==", + "dependencies": { + "@docusaurus/logger": "3.5.2", + "@docusaurus/utils": "3.5.2", + "@docusaurus/utils-common": "3.5.2", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" + }, + "node_modules/@mdx-js/mdx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", + "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-to-js": "^2.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-estree": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "periscopic": "^3.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", + "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.28", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", + "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==" + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@slorber/remark-comment": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", + "integrity": "sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA==", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.1.0", + "micromark-util-symbol": "^1.0.1" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/acorn": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", + "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/gtag.js": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", + "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.15", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz", + "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, + "node_modules/@types/node": { + "version": "22.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.6.0.tgz", + "integrity": "sha512-QyR8d5bmq+eR72TwQDfujwShHMcIrWIYsaQFtXRE58MHPTEKUNxjxvl0yS0qPMds5xbSDWtp7ZpvGFtd7dfMdQ==", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prismjs": { + "version": "1.26.4", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.4.tgz", + "integrity": "sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" + }, + "node_modules/@types/qs": { + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", + "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + }, + "node_modules/@types/react": { + "version": "18.3.8", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.8.tgz", + "integrity": "sha512-syBUrW3/XpnW4WJ41Pft+I+aPoDVbrBVQGEnbD7NijDGlVC+8gV/XKRY+7vMDlfPpbwYt0l1vd/Sj8bJGMbs9Q==", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "node_modules/@types/react-router-config": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.11.tgz", + "integrity": "sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "^5.1.0" + } + }, + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==" + }, + "node_modules/@types/ws": { + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/algoliasearch": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.24.0.tgz", + "integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-account": "4.24.0", + "@algolia/client-analytics": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-personalization": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/recommend": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/algoliasearch-helper": { + "version": "3.22.5", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.22.5.tgz", + "integrity": "sha512-lWvhdnc+aKOKx8jyA3bsdEgHzm/sglC4cYdMG4xSQyRiPLJVJtH/IVYZG3Hp6PkTEhQqhyVYkeP9z2IlcHJsWw==", + "dependencies": { + "@algolia/events": "^4.0.1" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 6" + } + }, + "node_modules/algoliasearch/node_modules/@algolia/client-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", + "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "dependencies": { + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/algoliasearch/node_modules/@algolia/client-search": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", + "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/algoliasearch/node_modules/@algolia/requester-browser-xhr": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz", + "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==", + "dependencies": { + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/algoliasearch/node_modules/@algolia/requester-node-http": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz", + "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==", + "dependencies": { + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/babel-loader": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/boxen": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", + "integrity": "sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^6.2.0", + "chalk": "^4.1.2", + "cli-boxes": "^3.0.0", + "string-width": "^5.0.1", + "type-fest": "^2.5.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/cacheable-request": { + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "dependencies": { + "@types/http-cache-semantics": "^4.0.2", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001663", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz", + "integrity": "sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "node_modules/combine-promises": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.2.0.tgz", + "integrity": "sha512-VcQB1ziGD0NXrhKxiwyNbCDmRzs/OShMs2GqW2DlU2A/Sd0nQxE1oWDAE5O0ygSx5mgQOn9eIFh7yKPgFRVkPQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compressible/node_modules/mime-db": { + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", + "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/configstore": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", + "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", + "dependencies": { + "dot-prop": "^6.0.1", + "graceful-fs": "^4.2.6", + "unique-string": "^3.0.0", + "write-file-atomic": "^3.0.3", + "xdg-basedir": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/yeoman/configstore?sponsor=1" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/copy-text-to-clipboard": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz", + "integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/core-js": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz", + "integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "dependencies": { + "browserslist": "^4.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.38.1.tgz", + "integrity": "sha512-BY8Etc1FZqdw1glX0XNOq2FDwfrg/VGqoZOZCdaL+UmdaqDwQwYXkMJT4t6In+zfEfOJDcM9T0KdbBeJg8KKCQ==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-declaration-sorter": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", + "integrity": "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz", + "integrity": "sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "cssnano": "^6.0.1", + "jest-worker": "^29.4.3", + "postcss": "^8.4.24", + "schema-utils": "^4.0.1", + "serialize-javascript": "^6.0.1" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "lightningcss": { + "optional": true + } + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.1.2.tgz", + "integrity": "sha512-rYk5UeX7VAM/u0lNqewCdasdtPK81CgX8wJFLEIXHbV2oldWRgJAsZrdhRXkV1NJzA2g850KiFm9mMU2HxNxMA==", + "dependencies": { + "cssnano-preset-default": "^6.1.2", + "lilconfig": "^3.1.1" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-advanced": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-6.1.2.tgz", + "integrity": "sha512-Nhao7eD8ph2DoHolEzQs5CfRpiEP0xa1HBdnFZ82kvqdmbwVBUr2r1QuQ4t1pi+D1ZpqpcO4T+wy/7RxzJ/WPQ==", + "dependencies": { + "autoprefixer": "^10.4.19", + "browserslist": "^4.23.0", + "cssnano-preset-default": "^6.1.2", + "postcss-discard-unused": "^6.0.5", + "postcss-merge-idents": "^6.0.3", + "postcss-reduce-idents": "^6.0.3", + "postcss-zindex": "^6.0.2" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-default": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", + "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", + "dependencies": { + "browserslist": "^4.23.0", + "css-declaration-sorter": "^7.2.0", + "cssnano-utils": "^4.0.2", + "postcss-calc": "^9.0.1", + "postcss-colormin": "^6.1.0", + "postcss-convert-values": "^6.1.0", + "postcss-discard-comments": "^6.0.2", + "postcss-discard-duplicates": "^6.0.3", + "postcss-discard-empty": "^6.0.3", + "postcss-discard-overridden": "^6.0.2", + "postcss-merge-longhand": "^6.0.5", + "postcss-merge-rules": "^6.1.1", + "postcss-minify-font-values": "^6.1.0", + "postcss-minify-gradients": "^6.0.3", + "postcss-minify-params": "^6.1.0", + "postcss-minify-selectors": "^6.0.4", + "postcss-normalize-charset": "^6.0.2", + "postcss-normalize-display-values": "^6.0.2", + "postcss-normalize-positions": "^6.0.2", + "postcss-normalize-repeat-style": "^6.0.2", + "postcss-normalize-string": "^6.0.2", + "postcss-normalize-timing-functions": "^6.0.2", + "postcss-normalize-unicode": "^6.1.0", + "postcss-normalize-url": "^6.0.2", + "postcss-normalize-whitespace": "^6.0.2", + "postcss-ordered-values": "^6.0.2", + "postcss-reduce-initial": "^6.1.0", + "postcss-reduce-transforms": "^6.0.2", + "postcss-svgo": "^6.0.3", + "postcss-unique-selectors": "^6.0.4" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-utils": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", + "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==" + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "node_modules/detect-port": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", + "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", + "dependencies": { + "address": "^1.0.1", + "debug": "4" + }, + "bin": { + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port-alt/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port-alt/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop/node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.27", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz", + "integrity": "sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/emoticon": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-4.1.0.tgz", + "integrity": "sha512-VWZfnxqwNcc51hIy/sbOdEem6D+cVtpPzEEtVAFdaas30+1dgkyaOQ4sQ6Bp0tOMqWO1v+HQfYaoodOkdhK6SQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", + "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-value-to-estree": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.1.2.tgz", + "integrity": "sha512-S0gW2+XZkmsx00tU2uJ4L9hUT7IFabbml9pHh2WQqFmAbxit++YGZne0sKJbNwkj9Wvg9E4uqWl4nCIFQMmfag==", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/remcohaszing" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eta": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eta/-/eta-2.2.0.tgz", + "integrity": "sha512-UVQ72Rqjy/ZKQalzV5dCCJP80GrmPrMxh6NlNf+erV6ObL0ZFkhCstWRawS85z3smdr3d2wXPsZEY7rDPfGd2g==", + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "url": "https://github.com/eta-dev/eta?sponsor=1" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eval": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", + "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==", + "dependencies": { + "@types/node": "*", + "require-like": ">= 0.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" + }, + "node_modules/express/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==" + }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "dependencies": { + "punycode": "^1.3.2" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", + "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/feed": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", + "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", + "dependencies": { + "xml-js": "^1.6.11" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/file-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/file-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dependencies": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-slugger": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", + "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/got/node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-yarn": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", + "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", + "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^8.0.0", + "property-information": "^6.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.4.tgz", + "integrity": "sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.0.tgz", + "integrity": "sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^0.4.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", + "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==" + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/style-to-object": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz", + "integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==", + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", + "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", + "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "dependencies": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "engines": { + "node": ">=14" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/html-webpack-plugin/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-plugin/node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", + "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/infima": { + "version": "0.2.0-alpha.44", + "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.44.tgz", + "integrity": "sha512-tuRkUSO/lB3rEhLJk25atwAjgLuzq070+pOW8XcvpHky/YbENnRRdPd85IBkyeTgttmOy5ah+yHYsK1HhUd4lQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-npm": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", + "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-reference": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", + "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-yarn-global": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz", + "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/latest-version": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", + "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", + "dependencies": { + "package-json": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/launch-editor": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", + "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", + "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-directive": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", + "integrity": "sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", + "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", + "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/mdast-util-frontmatter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz", + "integrity": "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "escape-string-regexp": "^5.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.3.tgz", + "integrity": "sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromark": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", + "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-directive": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", + "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-frontmatter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz", + "integrity": "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==", + "dependencies": { + "fault": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", + "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.0.tgz", + "integrity": "sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.1.tgz", + "integrity": "sha512-vNuFb9czP8QCtAQcEJn0UJQJZA8Dk6DXKBqx+bg/w0WGuSxDxNr7hErW89tHUY31dUW4NqEOWwmEUNhjTFmHkg==", + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-factory-label": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.2.tgz", + "integrity": "sha512-5E5I2pFzJyg2CtemqAbcyCktpHXuJbABnsb32wX2U8IQKhhVFBqkcZR5LRm1WVoFqa4kTueZK4abep7wdo9nrw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-factory-space": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-space/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-factory-title": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-character/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.2.tgz", + "integrity": "sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-events-to-acorn/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-normalize-identifier/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", + "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.1.tgz", + "integrity": "sha512-+Vyi+GCCOHnrJ2VPS+6aPoXN2k2jgUzDRhTFLjjTBn23qyXJXkjUWQgTL+mXpF5/A8ixLdCc6kWsoeOjKGejKQ==", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-emoji": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", + "integrity": "sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==", + "dependencies": { + "@sindresorhus/is": "^4.6.0", + "char-regex": "^1.0.2", + "emojilib": "^2.4.0", + "skin-tone": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", + "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", + "dependencies": { + "got": "^12.1.0", + "registry-auth-token": "^5.0.1", + "registry-url": "^6.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/periscopic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", + "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^3.0.0", + "is-reference": "^3.0.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-calc": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", + "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-colormin": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.1.0.tgz", + "integrity": "sha512-x9yX7DOxeMAR+BgGVnNSAxmAj98NX/YxEMNFP+SDCEeNLb2r3i6Hh1ksMsnW8Ub5SLCpbescQqn9YEbE9554Sw==", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "colord": "^2.9.3", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-convert-values": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz", + "integrity": "sha512-zx8IwP/ts9WvUM6NkVSkiU902QZL1bwPhaVaLynPtCsOTqp+ZKbNi+s6XJg3rfqpKGA/oc7Oxk5t8pOQJcwl/w==", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-comments": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.2.tgz", + "integrity": "sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw==", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.3.tgz", + "integrity": "sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw==", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-empty": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.3.tgz", + "integrity": "sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ==", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.2.tgz", + "integrity": "sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ==", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-unused": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-6.0.5.tgz", + "integrity": "sha512-wHalBlRHkaNnNwfC8z+ppX57VhvS+HWgjW508esjdaEYr3Mx7Gnn2xA4R/CKf5+Z9S5qsqC+Uzh4ueENWwCVUA==", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-loader": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", + "integrity": "sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A==", + "dependencies": { + "cosmiconfig": "^8.3.5", + "jiti": "^1.20.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-merge-idents": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-6.0.3.tgz", + "integrity": "sha512-1oIoAsODUs6IHQZkLQGO15uGEbK3EAl5wi9SS8hs45VgsxQfMnxvt+L+zIr7ifZFIH14cfAeVe2uCTa+SPRa3g==", + "dependencies": { + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.5.tgz", + "integrity": "sha512-5LOiordeTfi64QhICp07nzzuTDjNSO8g5Ksdibt44d+uvIIAE1oZdRn8y/W5ZtYgRH/lnLDlvi9F8btZcVzu3w==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^6.1.1" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-merge-rules": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.1.1.tgz", + "integrity": "sha512-KOdWF0gju31AQPZiD+2Ar9Qjowz1LTChSjFFbS+e2sFgc4uHOp3ZvVX4sNeTlk0w2O31ecFGgrFzhO0RSWbWwQ==", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^4.0.2", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.1.0.tgz", + "integrity": "sha512-gklfI/n+9rTh8nYaSJXlCo3nOKqMNkxuGpTn/Qm0gstL3ywTr9/WRKznE+oy6fvfolH6dF+QM4nCo8yPLdvGJg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.3.tgz", + "integrity": "sha512-4KXAHrYlzF0Rr7uc4VrfwDJ2ajrtNEpNEuLxFgwkhFZ56/7gaE4Nr49nLsQDZyUe+ds+kEhf+YAUolJiYXF8+Q==", + "dependencies": { + "colord": "^2.9.3", + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-params": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.1.0.tgz", + "integrity": "sha512-bmSKnDtyyE8ujHQK0RQJDIKhQ20Jq1LYiez54WiaOoBtcSuflfK3Nm596LvbtlFcpipMjgClQGyGr7GAs+H1uA==", + "dependencies": { + "browserslist": "^4.23.0", + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.4.tgz", + "integrity": "sha512-L8dZSwNLgK7pjTto9PzWRoMbnLq5vsZSTu8+j1P/2GB8qdtGQfn+K1uSvFgYvgh83cbyxT5m43ZZhUMTJDSClQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz", + "integrity": "sha512-a8N9czmdnrjPHa3DeFlwqst5eaL5W8jYu3EBbTTkI5FHkfMhFZh1EGbku6jhHhIzTA6tquI2P42NtZ59M/H/kQ==", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.2.tgz", + "integrity": "sha512-8H04Mxsb82ON/aAkPeq8kcBbAtI5Q2a64X/mnRRfPXBq7XeogoQvReqxEfc0B4WPq1KimjezNC8flUtC3Qz6jg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.2.tgz", + "integrity": "sha512-/JFzI441OAB9O7VnLA+RtSNZvQ0NCFZDOtp6QPFo1iIyawyXg0YI3CYM9HBy1WvwCRHnPep/BvI1+dGPKoXx/Q==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.2.tgz", + "integrity": "sha512-YdCgsfHkJ2jEXwR4RR3Tm/iOxSfdRt7jplS6XRh9Js9PyCR/aka/FCb6TuHT2U8gQubbm/mPmF6L7FY9d79VwQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-string": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.2.tgz", + "integrity": "sha512-vQZIivlxlfqqMp4L9PZsFE4YUkWniziKjQWUtsxUiVsSSPelQydwS8Wwcuw0+83ZjPWNTl02oxlIvXsmmG+CiQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.2.tgz", + "integrity": "sha512-a+YrtMox4TBtId/AEwbA03VcJgtyW4dGBizPl7e88cTFULYsprgHWTbfyjSLyHeBcK/Q9JhXkt2ZXiwaVHoMzA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.1.0.tgz", + "integrity": "sha512-QVC5TQHsVj33otj8/JD869Ndr5Xcc/+fwRh4HAsFsAeygQQXm+0PySrKbr/8tkDKzW+EVT3QkqZMfFrGiossDg==", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-url": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.2.tgz", + "integrity": "sha512-kVNcWhCeKAzZ8B4pv/DnrU1wNh458zBNp8dh4y5hhxih5RZQ12QWMuQrDgPRw3LRl8mN9vOVfHl7uhvHYMoXsQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.2.tgz", + "integrity": "sha512-sXZ2Nj1icbJOKmdjXVT9pnyHQKiSAyuNQHSgRCUgThn2388Y9cGVDR+E9J9iAYbSbLHI+UUwLVl1Wzco/zgv0Q==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-ordered-values": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.2.tgz", + "integrity": "sha512-VRZSOB+JU32RsEAQrO94QPkClGPKJEL/Z9PCBImXMhIeK5KAYo6slP/hBYlLgrCjFxyqvn5VC81tycFEDBLG1Q==", + "dependencies": { + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-idents": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-6.0.3.tgz", + "integrity": "sha512-G3yCqZDpsNPoQgbDUy3T0E6hqOQ5xigUtBQyrmq3tn2GxlyiL0yyl7H+T8ulQR6kOcHJ9t7/9H4/R2tv8tJbMA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.1.0.tgz", + "integrity": "sha512-RarLgBK/CrL1qZags04oKbVbrrVK2wcxhvta3GCxrZO4zveibqbRPmm2VI8sSgCXwoUHEliRSbOfpR0b/VIoiw==", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.2.tgz", + "integrity": "sha512-sB+Ya++3Xj1WaT9+5LOOdirAxP7dJZms3GRcYheSPi1PiTMigsxHAdkrbItHxwYHr4kt1zL7mmcHstgMYT+aiA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-sort-media-queries": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-5.2.0.tgz", + "integrity": "sha512-AZ5fDMLD8SldlAYlvi8NIqo0+Z8xnXU2ia0jxmuhxAU+Lqt9K+AlmLNJ/zWEnE9x+Zx3qL3+1K20ATgNOr3fAA==", + "dependencies": { + "sort-css-media-queries": "2.2.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.4.23" + } + }, + "node_modules/postcss-svgo": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.3.tgz", + "integrity": "sha512-dlrahRmxP22bX6iKEjOM+c8/1p+81asjKT+V5lrgOH944ryx/OHpclnIbGsKVd3uWOXFLYJwCVf0eEkJGvO96g==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^3.2.0" + }, + "engines": { + "node": "^14 || ^16 || >= 18" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.4.tgz", + "integrity": "sha512-K38OCaIrO8+PzpArzkLKB42dSARtC2tmG6PvD4b1o1Q2E9Os8jzfWFfSy/rixsHwohtsDdFtAWGjFVFUdwYaMg==", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/postcss-zindex": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-6.0.2.tgz", + "integrity": "sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg==", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/prism-react-renderer": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.4.0.tgz", + "integrity": "sha512-327BsVCD/unU4CNLZTWVHyUHKnsqcvj2qbPlQ8MiBE2eq2rgctjigPA1Gp9HLF83kZ20zNN6jgizHJeEsyFYOw==", + "dependencies": { + "@types/prismjs": "^1.26.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.0.0" + } + }, + "node_modules/prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, + "node_modules/pupa": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", + "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", + "dependencies": { + "escape-goat": "^4.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-dev-utils/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/react-dev-utils/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/react-dev-utils/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, + "node_modules/react-helmet-async": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", + "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.2.0", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-json-view-lite": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.5.0.tgz", + "integrity": "sha512-nWqA1E4jKPklL2jvHWs6s+7Na0qNgw9HCP6xehdQJeg6nPBTFZgGwyko9Q0oj+jQWKTTVRS30u0toM5wiuL3iw==", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-loadable": { + "name": "@docusaurus/react-loadable", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", + "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", + "dependencies": { + "@types/react": "*" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-loadable-ssr-addon-v5-slorber": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", + "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", + "dependencies": { + "@babel/runtime": "^7.10.3" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "react-loadable": "*", + "webpack": ">=4.41.1 || 5.x" + } + }, + "node_modules/react-router": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", + "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router-config": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", + "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", + "dependencies": { + "@babel/runtime": "^7.1.2" + }, + "peerDependencies": { + "react": ">=15", + "react-router": ">=5" + } + }, + "node_modules/react-router-dom": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", + "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.3.4", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reading-time": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", + "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/registry-url": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remark-directive": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.0.tgz", + "integrity": "sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-directive": "^3.0.0", + "micromark-extension-directive": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-emoji": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-4.0.1.tgz", + "integrity": "sha512-fHdvsTR1dHkWKev9eNyhTo4EFwbUvJ8ka9SgeWkMPYFX4WoI7ViVBms3PjlQYgw5TLvNQso3GUB/b/8t3yo+dg==", + "dependencies": { + "@types/mdast": "^4.0.2", + "emoticon": "^4.0.1", + "mdast-util-find-and-replace": "^3.0.1", + "node-emoji": "^2.1.0", + "unified": "^11.0.4" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/remark-frontmatter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz", + "integrity": "sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-frontmatter": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", + "integrity": "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.1.tgz", + "integrity": "sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/renderkid/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/renderkid/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-like": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", + "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==", + "engines": { + "node": "*" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rtl-detect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.1.2.tgz", + "integrity": "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==" + }, + "node_modules/rtlcss": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.3.0.tgz", + "integrity": "sha512-FI+pHEn7Wc4NqKXMXFM+VAYKEj/mRIcW4h24YVwVtyjI+EqGrLc2Hx/Ny0lrZ21cBWU2goLy36eqMcNj3AQJig==", + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0", + "postcss": "^8.4.21", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "rtlcss": "bin/rtlcss.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/search-insights": { + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.2.tgz", + "integrity": "sha512-zFNpOpUO+tY2D85KrxJ+aqwnIfdEGi06UH2+xEb+Bp9Mwznmauqc9djbnBibJO5mpfUPPa8st6Sx65+vbeO45g==", + "peer": true + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-handler": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.1.2", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/sitemap": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.2.tgz", + "integrity": "sha512-ARCqzHJ0p4gWt+j7NlU5eDlIO9+Rkr/JhPFZKKQ1l5GCus7rJH4UdrlVAh0xC/gDS/Qir2UMxqYNHtsKr2rpCw==", + "dependencies": { + "@types/node": "^17.0.5", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.2.4" + }, + "bin": { + "sitemap": "dist/cli.js" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=5.6.0" + } + }, + "node_modules/sitemap/node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" + }, + "node_modules/skin-tone": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", + "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", + "dependencies": { + "unicode-emoji-modifier-base": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sort-css-media-queries": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.2.0.tgz", + "integrity": "sha512-0xtkGhWCC9MGt/EzgnvbbbKhqWjl1+/rncmhTh5qCpbYguXh6S/qwePfv/JQ8jePXXmqingylxoC49pCkSPIbA==", + "engines": { + "node": ">= 6.3.0" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/srcset": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", + "integrity": "sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-to-object": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz", + "integrity": "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==", + "dependencies": { + "inline-style-parser": "0.1.1" + } + }, + "node_modules/stylehacks": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.1.1.tgz", + "integrity": "sha512-gSTTEQ670cJNoaeIp9KX6lZmm8LJ3jPB5yJmX8Zq/wQxOsAFXV3qjWzHas3YYk1qesuVIyYWWUpZ0vSE/dTSGg==", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.33.0.tgz", + "integrity": "sha512-JuPVaB7s1gdFKPKTelwUyRq5Sid2A3Gko2S0PncwdBq7kN9Ti9HPWDQ06MPsEDGsZeVESjKEnyGy68quBk1w6g==", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-emoji-modifier-base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", + "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/update-notifier": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", + "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", + "dependencies": { + "boxen": "^7.0.0", + "chalk": "^5.0.1", + "configstore": "^6.0.0", + "has-yarn": "^3.0.0", + "import-lazy": "^4.0.0", + "is-ci": "^3.0.1", + "is-installed-globally": "^0.4.0", + "is-npm": "^6.0.0", + "is-yarn-global": "^0.4.0", + "latest-version": "^7.0.0", + "pupa": "^3.1.0", + "semver": "^7.3.7", + "semver-diff": "^4.0.0", + "xdg-basedir": "^5.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/boxen": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", + "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^7.0.1", + "chalk": "^5.2.0", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "dependencies": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } + } + }, + "node_modules/url-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/url-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/url-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/url-loader/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/url-loader/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/url-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + }, + "node_modules/utility-types": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/watchpack": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webpack": { + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "dependencies": { + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", + "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", + "dependencies": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.4", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/webpack/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpackbar": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz", + "integrity": "sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==", + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.3", + "pretty-time": "^1.1.0", + "std-env": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "webpack": "3 || 4 || 5" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/package.json b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/package.json new file mode 100755 index 00000000..4acf04c4 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/package.json @@ -0,0 +1,42 @@ +{ + "private": true, + "scripts": { + "docusaurus": "docusaurus", + "start": "docusaurus start", + "build": "docusaurus build", + "swizzle": "docusaurus swizzle", + "deploy": "docusaurus deploy", + "clear": "docusaurus clear", + "serve": "docusaurus serve", + "write-translations": "docusaurus write-translations", + "write-heading-ids": "docusaurus write-heading-ids" + }, + "dependencies": { + "@docusaurus/core": "3.5.2", + "@docusaurus/preset-classic": "3.5.2", + "@mdx-js/react": "3.0.1", + "clsx": "2.1.1", + "prism-react-renderer": "2.4.0", + "react": "18.3.1", + "react-dom": "18.3.1" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "3.5.2", + "@docusaurus/types": "3.5.2" + }, + "browserslist": { + "production": [ + ">0.5%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 3 chrome version", + "last 3 firefox version", + "last 5 safari version" + ] + }, + "engines": { + "node": ">=18.0" + } +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/sidebars.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/sidebars.js new file mode 100755 index 00000000..3efb4ff4 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/sidebars.js @@ -0,0 +1,20 @@ +/** + * Creating a sidebar enables you to: + - create an ordered group of docs + - render a sidebar for each doc of that group + - provide next/previous navigation + + The sidebars can be generated from the filesystem, or explicitly defined here. + + Create as many sidebars as you want. + */ + +// @ts-check + +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const sidebars = { + // By default, Docusaurus generates a sidebar from the docs folder structure + docsSidebar: [{type: 'autogenerated', dirName: '.'}], +}; + +export default sidebars; diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/src/css/custom.css b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/src/css/custom.css new file mode 100755 index 00000000..2bc6a4cf --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/src/css/custom.css @@ -0,0 +1,30 @@ +/** + * Any CSS included here will be global. The classic template + * bundles Infima by default. Infima is a CSS framework designed to + * work well for content-centric websites. + */ + +/* You can override the default Infima variables here. */ +:root { + --ifm-color-primary: #2e8555; + --ifm-color-primary-dark: #29784c; + --ifm-color-primary-darker: #277148; + --ifm-color-primary-darkest: #205d3b; + --ifm-color-primary-light: #33925d; + --ifm-color-primary-lighter: #359962; + --ifm-color-primary-lightest: #3cad6e; + --ifm-code-font-size: 95%; + --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); +} + +/* For readability concerns, you should choose a lighter palette in dark mode. */ +[data-theme='dark'] { + --ifm-color-primary: #25c2a0; + --ifm-color-primary-dark: #21af90; + --ifm-color-primary-darker: #1fa588; + --ifm-color-primary-darkest: #1a8870; + --ifm-color-primary-light: #29d5b0; + --ifm-color-primary-lighter: #32d8b4; + --ifm-color-primary-lightest: #4fddbf; + --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/static/.nojekyll b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/static/.nojekyll new file mode 100755 index 00000000..e69de29b diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/static/img/favicon.ico b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/static/img/favicon.ico new file mode 100755 index 00000000..c01d54bc Binary files /dev/null and b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/docs/static/img/favicon.ico differ diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/fib.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/fib.c new file mode 100755 index 00000000..a9eb29d9 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/fib.c @@ -0,0 +1,67 @@ +/* + * QuickJS: Example of C module + * + * Copyright (c) 2017-2018 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#define countof(x) (sizeof(x) / sizeof((x)[0])) + +static int fib(int n) +{ + if (n <= 0) + return 0; + else if (n == 1) + return 1; + else + return fib(n - 1) + fib(n - 2); +} + +static JSValue js_fib(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + int n, res; + if (JS_ToInt32(ctx, &n, argv[0])) + return JS_EXCEPTION; + res = fib(n); + return JS_NewInt32(ctx, res); +} + +static const JSCFunctionListEntry js_fib_funcs[] = { + JS_CFUNC_DEF("fib", 1, js_fib ), +}; + +static int js_fib_init(JSContext *ctx, JSModuleDef *m) +{ + return JS_SetModuleExportList(ctx, m, js_fib_funcs, + countof(js_fib_funcs)); +} + +JS_MODULE_EXTERN JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) +{ + JSModuleDef *m; + m = JS_NewCModule(ctx, module_name, js_fib_init); + if (!m) + return NULL; + JS_AddModuleExportList(ctx, m, js_fib_funcs, countof(js_fib_funcs)); + return m; +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/fib_module.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/fib_module.js new file mode 100755 index 00000000..6a810716 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/fib_module.js @@ -0,0 +1,10 @@ +/* fib module */ +export function fib(n) +{ + if (n <= 0) + return 0; + else if (n == 1) + return 1; + else + return fib(n - 1) + fib(n - 2); +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/hello.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/hello.js new file mode 100755 index 00000000..accefceb --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/hello.js @@ -0,0 +1 @@ +console.log("Hello World"); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/hello_module.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/hello_module.js new file mode 100755 index 00000000..463660f6 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/hello_module.js @@ -0,0 +1,6 @@ +/* example of JS module */ + +import { fib } from "./fib_module.js"; + +console.log("Hello World"); +console.log("fib(10)=", fib(10)); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/meson.build b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/meson.build new file mode 100755 index 00000000..08f0329f --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/meson.build @@ -0,0 +1,17 @@ +shared_module( + 'fib', + 'fib.c', + + name_prefix: '', + gnu_symbol_visibility: 'hidden', + dependencies: qjs_module_dep, +) + +shared_module( + 'point', + 'point.c', + + name_prefix: '', + gnu_symbol_visibility: 'hidden', + dependencies: qjs_module_dep, +) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/pi_bigint.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/pi_bigint.js new file mode 100755 index 00000000..e15abd17 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/pi_bigint.js @@ -0,0 +1,118 @@ +/* + * PI computation in Javascript using the BigInt type + */ +"use strict"; + +/* return floor(log2(a)) for a > 0 and 0 for a = 0 */ +function floor_log2(a) +{ + var k_max, a1, k, i; + k_max = 0n; + while ((a >> (2n ** k_max)) != 0n) { + k_max++; + } + k = 0n; + a1 = a; + for(i = k_max - 1n; i >= 0n; i--) { + a1 = a >> (2n ** i); + if (a1 != 0n) { + a = a1; + k |= (1n << i); + } + } + return k; +} + +/* return ceil(log2(a)) for a > 0 */ +function ceil_log2(a) +{ + return floor_log2(a - 1n) + 1n; +} + +/* return floor(sqrt(a)) (not efficient but simple) */ +function int_sqrt(a) +{ + var l, u, s; + if (a == 0n) + return a; + l = ceil_log2(a); + u = 1n << ((l + 1n) / 2n); + /* u >= floor(sqrt(a)) */ + for(;;) { + s = u; + u = ((a / s) + s) / 2n; + if (u >= s) + break; + } + return s; +} + +/* return pi * 2**prec */ +function calc_pi(prec) { + const CHUD_A = 13591409n; + const CHUD_B = 545140134n; + const CHUD_C = 640320n; + const CHUD_C3 = 10939058860032000n; /* C^3/24 */ + const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */ + + /* return [P, Q, G] */ + function chud_bs(a, b, need_G) { + var c, P, Q, G, P1, Q1, G1, P2, Q2, G2; + if (a == (b - 1n)) { + G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n); + P = G * (CHUD_B * b + CHUD_A); + if (b & 1n) + P = -P; + Q = b * b * b * CHUD_C3; + } else { + c = (a + b) >> 1n; + [P1, Q1, G1] = chud_bs(a, c, true); + [P2, Q2, G2] = chud_bs(c, b, need_G); + P = P1 * Q2 + P2 * G1; + Q = Q1 * Q2; + if (need_G) + G = G1 * G2; + else + G = 0n; + } + return [P, Q, G]; + } + + var n, P, Q, G; + /* number of serie terms */ + n = BigInt(Math.ceil(Number(prec) / CHUD_BITS_PER_TERM)) + 10n; + [P, Q, G] = chud_bs(0n, n, false); + Q = (CHUD_C / 12n) * (Q << prec) / (P + Q * CHUD_A); + G = int_sqrt(CHUD_C << (2n * prec)); + return (Q * G) >> prec; +} + +function main(args) { + var r, n_digits, n_bits, out; + if (args.length < 1) { + print("usage: pi n_digits"); + return; + } + n_digits = args[0] | 0; + + /* we add more bits to reduce the probability of bad rounding for + the last digits */ + n_bits = BigInt(Math.ceil(n_digits * Math.log2(10))) + 32n; + r = calc_pi(n_bits); + r = ((10n ** BigInt(n_digits)) * r) >> n_bits; + out = r.toString(); + print(out[0] + "." + out.slice(1)); +} + +var args; +if (typeof scriptArgs != "undefined") { + args = scriptArgs; + args.shift(); +} else if (typeof arguments != "undefined") { + args = arguments; +} else { + /* default: 1000 digits */ + args=[1000]; +} + +main(args); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/point.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/point.c new file mode 100755 index 00000000..baa06388 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/point.c @@ -0,0 +1,154 @@ +/* + * QuickJS: Example of C module with a class + * + * Copyright (c) 2019 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include + +#define countof(x) (sizeof(x) / sizeof((x)[0])) + +/* Point Class */ + +typedef struct { + int x; + int y; +} JSPointData; + +static JSClassID js_point_class_id; + +static void js_point_finalizer(JSRuntime *rt, JSValue val) +{ + JSPointData *s = JS_GetOpaque(val, js_point_class_id); + /* Note: 's' can be NULL in case JS_SetOpaque() was not called */ + js_free_rt(rt, s); +} + +static JSValue js_point_ctor(JSContext *ctx, + JSValue new_target, + int argc, JSValue *argv) +{ + JSPointData *s; + JSValue obj = JS_UNDEFINED; + JSValue proto; + + s = js_mallocz(ctx, sizeof(*s)); + if (!s) + return JS_EXCEPTION; + if (JS_ToInt32(ctx, &s->x, argv[0])) + goto fail; + if (JS_ToInt32(ctx, &s->y, argv[1])) + goto fail; + /* using new_target to get the prototype is necessary when the + class is extended. */ + proto = JS_GetPropertyStr(ctx, new_target, "prototype"); + if (JS_IsException(proto)) + goto fail; + obj = JS_NewObjectProtoClass(ctx, proto, js_point_class_id); + JS_FreeValue(ctx, proto); + if (JS_IsException(obj)) + goto fail; + JS_SetOpaque(obj, s); + return obj; + fail: + js_free(ctx, s); + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; +} + +static JSValue js_point_get_xy(JSContext *ctx, JSValue this_val, int magic) +{ + JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); + if (!s) + return JS_EXCEPTION; + if (magic == 0) + return JS_NewInt32(ctx, s->x); + else + return JS_NewInt32(ctx, s->y); +} + +static JSValue js_point_set_xy(JSContext *ctx, JSValue this_val, JSValue val, int magic) +{ + JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); + int v; + if (!s) + return JS_EXCEPTION; + if (JS_ToInt32(ctx, &v, val)) + return JS_EXCEPTION; + if (magic == 0) + s->x = v; + else + s->y = v; + return JS_UNDEFINED; +} + +static JSValue js_point_norm(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv) +{ + JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); + if (!s) + return JS_EXCEPTION; + return JS_NewFloat64(ctx, sqrt((double)s->x * s->x + (double)s->y * s->y)); +} + +static JSClassDef js_point_class = { + "Point", + .finalizer = js_point_finalizer, +}; + +static const JSCFunctionListEntry js_point_proto_funcs[] = { + JS_CGETSET_MAGIC_DEF("x", js_point_get_xy, js_point_set_xy, 0), + JS_CGETSET_MAGIC_DEF("y", js_point_get_xy, js_point_set_xy, 1), + JS_CFUNC_DEF("norm", 0, js_point_norm), +}; + +static int js_point_init(JSContext *ctx, JSModuleDef *m) +{ + JSValue point_proto, point_class; + JSRuntime *rt = JS_GetRuntime(ctx); + + /* create the Point class */ + JS_NewClassID(rt, &js_point_class_id); + JS_NewClass(rt, js_point_class_id, &js_point_class); + + point_proto = JS_NewObject(ctx); + JS_SetPropertyFunctionList(ctx, point_proto, js_point_proto_funcs, countof(js_point_proto_funcs)); + + point_class = JS_NewCFunction2(ctx, js_point_ctor, "Point", 2, JS_CFUNC_constructor, 0); + /* set proto.constructor and ctor.prototype */ + JS_SetConstructor(ctx, point_class, point_proto); + JS_SetClassProto(ctx, js_point_class_id, point_proto); + + JS_SetModuleExport(ctx, m, "Point", point_class); + return 0; +} + +JS_MODULE_EXTERN JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) +{ + JSModuleDef *m; + m = JS_NewCModule(ctx, module_name, js_point_init); + if (!m) + return NULL; + JS_AddModuleExport(ctx, m, "Point"); + return m; +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/test_fib.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/test_fib.js new file mode 100755 index 00000000..f22c5764 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/test_fib.js @@ -0,0 +1,8 @@ +/* example of JS module importing a C module */ +import * as os from "qjs:os"; + +const isWin = os.platform === 'win32'; +const { fib } = await import(`./fib.${isWin ? 'dll' : 'so'}`); + +console.log("Hello World"); +console.log("fib(10)=", fib(10)); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/test_point.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/test_point.js new file mode 100755 index 00000000..1e0fafa0 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/examples/test_point.js @@ -0,0 +1,43 @@ +/* example of JS module importing a C module */ +import * as os from "qjs:os"; + +const isWin = os.platform === 'win32'; +const { Point } = await import(`./point.${isWin ? 'dll' : 'so'}`); + +function assert(b, str) +{ + if (b) { + return; + } else { + throw Error("assertion failed: " + str); + } +} + +class ColorPoint extends Point { + constructor(x, y, color) { + super(x, y); + this.color = color; + } + get_color() { + return this.color; + } +}; + +function main() +{ + var pt, pt2; + + pt = new Point(2, 3); + assert(pt.x === 2); + assert(pt.y === 3); + pt.x = 4; + assert(pt.x === 4); + assert(pt.norm() == 5); + + pt2 = new ColorPoint(2, 3, 0xffffff); + assert(pt2.x === 2); + assert(pt2.color === 0xffffff); + assert(pt2.get_color() === 0xffffff); +} + +main(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/fuzz.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/fuzz.c index fca8fa41..5794e7b4 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/fuzz.c +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/fuzz.c @@ -1,20 +1,49 @@ // clang -g -O1 -fsanitize=fuzzer -o fuzz fuzz.c #include "quickjs.h" #include "quickjs.c" -#include "cutils.c" +#include "cutils.h" #include "libregexp.c" #include "libunicode.c" +#include "dtoa.c" + +#include #include +#include +// note: LLVM output does not contain checksum, needs to be added +// manually (4 byte field at position 1) when adding to the corpus +// +// fill in UINT32_MAX to disable checksumming int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { + if (!len) + return 0; JSRuntime *rt = JS_NewRuntime(); if (!rt) exit(1); JSContext *ctx = JS_NewContext(rt); if (!ctx) exit(1); - JSValue val = JS_ReadObject(ctx, buf, len, /*flags*/0); + size_t newlen = len + 4; + uint8_t *newbuf = malloc(newlen); + if (!newbuf) + exit(1); + uint32_t csum = bc_csum(&buf[1], len-1); // skip version field + newbuf[0] = buf[0]; // copy version field + put_u32(&newbuf[1], csum); // insert checksum + memcpy(&newbuf[5], &buf[1], len-1); // copy rest of payload + JSValue val = JS_ReadObject(ctx, newbuf, newlen, /*flags*/0); + free(newbuf); + if (JS_IsException(val)) { + JSValue exc = JS_GetException(ctx); + const char *str = JS_ToCString(ctx, exc); + JS_FreeValue(ctx, exc); + if (!str) + exit(1); + if (strstr(str, "checksum error")) + exit(1); + JS_FreeCString(ctx, str); + } JS_FreeValue(ctx, val); JS_FreeContext(ctx); JS_FreeRuntime(rt); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/function_source.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/function_source.c new file mode 100755 index 00000000..03a01282 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/function_source.c @@ -0,0 +1,81 @@ +/* File generated automatically by the QuickJS-ng compiler. */ + +#include "quickjs-libc.h" + +const uint32_t qjsc_function_source_size = 332; + +const uint8_t qjsc_function_source[332] = { + 0x1a, 0x42, 0x81, 0xa1, 0x89, 0x05, 0x01, 0x30, + 0x74, 0x65, 0x73, 0x74, 0x73, 0x2f, 0x66, 0x75, + 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x6a, 0x73, + 0x01, 0x0c, 0x61, 0x63, 0x74, 0x75, 0x61, 0x6c, + 0x01, 0x02, 0x66, 0x01, 0x0c, 0x65, 0x78, 0x70, + 0x65, 0x63, 0x74, 0x01, 0x34, 0x66, 0x75, 0x6e, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x28, + 0x29, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x34, 0x32, 0x20, 0x7d, 0x0d, + 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x20, 0x0a, 0x01, 0xa8, 0x01, 0x00, 0x05, 0x00, + 0x03, 0x02, 0x02, 0x01, 0x74, 0x05, 0xe6, 0x03, + 0x02, 0x00, 0x30, 0xe8, 0x03, 0x04, 0x00, 0x70, + 0x01, 0xe6, 0x03, 0x04, 0x02, 0x70, 0x00, 0x10, + 0x00, 0x01, 0x00, 0xf4, 0x01, 0x00, 0x01, 0x00, + 0xea, 0x03, 0x00, 0x1e, 0xe8, 0x03, 0x01, 0x06, + 0x0c, 0x43, 0x0a, 0x01, 0xe8, 0x03, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc2, + 0x2a, 0x28, 0xe4, 0x03, 0x03, 0x01, 0x00, 0x1a, + 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x66, 0x28, 0x29, 0x20, 0x7b, 0x20, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x34, 0x32, + 0x20, 0x7d, 0x0c, 0x03, 0xc8, 0x04, 0x08, 0xd2, + 0x08, 0xf0, 0x05, 0xc5, 0x00, 0xe8, 0x29, 0x04, + 0xf6, 0x00, 0x00, 0x00, 0xe7, 0x60, 0x00, 0x00, + 0xe4, 0x41, 0x3b, 0x00, 0x00, 0x00, 0x24, 0x00, + 0x00, 0xcf, 0x61, 0x00, 0x00, 0x64, 0x00, 0x00, + 0xae, 0xf0, 0x0b, 0x38, 0xa0, 0x00, 0x00, 0x00, + 0x61, 0x00, 0x00, 0xf5, 0x30, 0x60, 0x02, 0x00, + 0x60, 0x01, 0x00, 0x38, 0x3e, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x04, 0xf4, 0x00, 0x00, 0x00, + 0x9c, 0x32, 0x01, 0x00, 0x03, 0x00, 0xd0, 0x61, + 0x01, 0x00, 0x41, 0x3b, 0x00, 0x00, 0x00, 0x24, + 0x00, 0x00, 0xd1, 0x61, 0x02, 0x00, 0x64, 0x00, + 0x00, 0xae, 0xf0, 0x0b, 0x38, 0xa0, 0x00, 0x00, + 0x00, 0x61, 0x02, 0x00, 0xf5, 0x30, 0x67, 0x02, + 0x00, 0x67, 0x01, 0x00, 0x06, 0x2f, 0xe4, 0x03, + 0x01, 0x01, 0x18, 0x00, 0x1c, 0x0a, 0x2a, 0x26, + 0x03, 0x20, 0x1c, 0x1b, 0x0c, 0x00, 0x10, 0x08, + 0x27, 0x11, 0x12, 0x67, 0x0d, 0x26, 0x03, 0x20, + 0x1c, 0x1b, 0x0c, 0x00, +}; + +static JSContext *JS_NewCustomContext(JSRuntime *rt) +{ + JSContext *ctx = JS_NewContext(rt); + if (!ctx) + return NULL; + return ctx; +} + +int main(int argc, char **argv) +{ + int r; + JSRuntime *rt; + JSContext *ctx; + r = 0; + rt = JS_NewRuntime(); + js_std_set_worker_new_context_func(JS_NewCustomContext); + js_std_init_handlers(rt); + JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL); + ctx = JS_NewCustomContext(rt); + js_std_add_helpers(ctx, argc, argv); + js_std_eval_binary(ctx, qjsc_function_source, qjsc_function_source_size, 0); + r = js_std_loop(ctx); + if (r) { + js_std_dump_error(ctx); + } + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return r; +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/hello.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/hello.c new file mode 100755 index 00000000..8f35f7da --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/hello.c @@ -0,0 +1,53 @@ +/* File generated automatically by the QuickJS-ng compiler. */ + +#include "quickjs-libc.h" + +const uint32_t qjsc_hello_size = 108; + +const uint8_t qjsc_hello[108] = { + 0x1a, 0x9f, 0x9e, 0xb6, 0xf5, 0x04, 0x01, 0x22, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, + 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e, 0x6a, + 0x73, 0x01, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x6f, + 0x6c, 0x65, 0x01, 0x06, 0x6c, 0x6f, 0x67, 0x01, + 0x16, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, + 0x6f, 0x72, 0x6c, 0x64, 0x0d, 0xe4, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x20, 0x0a, 0x01, + 0xa8, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x19, 0x00, 0x08, 0xf0, 0x02, 0x29, 0x38, + 0xf3, 0x00, 0x00, 0x00, 0x41, 0xf4, 0x00, 0x00, + 0x00, 0x04, 0xf5, 0x00, 0x00, 0x00, 0x24, 0x01, + 0x00, 0x0e, 0x06, 0x2f, 0xe4, 0x03, 0x01, 0x01, + 0x02, 0x48, 0x0e, 0x00, +}; + +static JSContext *JS_NewCustomContext(JSRuntime *rt) +{ + JSContext *ctx = JS_NewContext(rt); + if (!ctx) + return NULL; + return ctx; +} + +int main(int argc, char **argv) +{ + int r; + JSRuntime *rt; + JSContext *ctx; + r = 0; + rt = JS_NewRuntime(); + js_std_set_worker_new_context_func(JS_NewCustomContext); + js_std_init_handlers(rt); + JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL); + ctx = JS_NewCustomContext(rt); + js_std_add_helpers(ctx, argc, argv); + js_std_eval_binary(ctx, qjsc_hello, qjsc_hello_size, 0); + r = js_std_loop(ctx); + if (r) { + js_std_dump_error(ctx); + } + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return r; +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/hello_module.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/hello_module.c new file mode 100755 index 00000000..55268e0e --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/hello_module.c @@ -0,0 +1,106 @@ +/* File generated automatically by the QuickJS-ng compiler. */ + +#include "quickjs-libc.h" + +const uint32_t qjsc_fib_module_size = 296; + +const uint8_t qjsc_fib_module[296] = { + 0x1a, 0x0b, 0xdb, 0x78, 0x32, 0x03, 0x01, 0x2c, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, + 0x2f, 0x66, 0x69, 0x62, 0x5f, 0x6d, 0x6f, 0x64, + 0x75, 0x6c, 0x65, 0x2e, 0x6a, 0x73, 0x01, 0x06, + 0x66, 0x69, 0x62, 0x01, 0x02, 0x6e, 0x0d, 0xe4, + 0x03, 0x00, 0x01, 0x00, 0x00, 0xe6, 0x03, 0x00, + 0x00, 0x00, 0x0c, 0x20, 0x0a, 0x01, 0xa8, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x09, + 0x00, 0xe6, 0x03, 0x00, 0x06, 0x0c, 0x43, 0x0a, + 0x01, 0xe6, 0x03, 0x01, 0x00, 0x01, 0x04, 0x00, + 0x01, 0x00, 0x1a, 0x01, 0xe8, 0x03, 0x00, 0x01, + 0x00, 0xe6, 0x03, 0x00, 0x02, 0xd7, 0xba, 0xa6, + 0xf0, 0x03, 0xba, 0x28, 0xd7, 0xbb, 0xab, 0xf0, + 0x03, 0xbb, 0x28, 0xe3, 0xd7, 0xbb, 0x9d, 0xf5, + 0xe3, 0xd7, 0xbc, 0x9d, 0xf5, 0x9c, 0x28, 0xe4, + 0x03, 0x02, 0x08, 0x0e, 0x09, 0x0c, 0x27, 0x0a, + 0x28, 0x02, 0x07, 0x08, 0x11, 0x0a, 0x07, 0x08, + 0x07, 0x08, 0x8d, 0x01, 0x66, 0x75, 0x6e, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x69, 0x62, + 0x28, 0x6e, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x20, + 0x3c, 0x3d, 0x20, 0x30, 0x29, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x30, 0x3b, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, + 0x20, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x20, 0x3d, + 0x3d, 0x20, 0x31, 0x29, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x20, 0x31, 0x3b, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, + 0x69, 0x62, 0x28, 0x6e, 0x20, 0x2d, 0x20, 0x31, + 0x29, 0x20, 0x2b, 0x20, 0x66, 0x69, 0x62, 0x28, + 0x6e, 0x20, 0x2d, 0x20, 0x32, 0x29, 0x3b, 0x0a, + 0x7d, 0x08, 0xf0, 0x05, 0xc5, 0x00, 0xe7, 0x29, + 0x06, 0x2f, 0xe4, 0x03, 0x01, 0x01, 0x00, 0x00, +}; + +const uint32_t qjsc_hello_module_size = 192; + +const uint8_t qjsc_hello_module[192] = { + 0x1a, 0xee, 0x6a, 0xd3, 0x27, 0x07, 0x01, 0x30, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, + 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x5f, 0x6d, + 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x6a, 0x73, + 0x01, 0x1e, 0x2e, 0x2f, 0x66, 0x69, 0x62, 0x5f, + 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x6a, + 0x73, 0x01, 0x06, 0x66, 0x69, 0x62, 0x01, 0x0e, + 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x01, + 0x06, 0x6c, 0x6f, 0x67, 0x01, 0x16, 0x48, 0x65, + 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, + 0x64, 0x01, 0x10, 0x66, 0x69, 0x62, 0x28, 0x31, + 0x30, 0x29, 0x3d, 0x0d, 0xe4, 0x03, 0x01, 0xe6, + 0x03, 0x00, 0x00, 0x01, 0x00, 0xe8, 0x03, 0x00, + 0x00, 0x0c, 0x20, 0x0a, 0x01, 0xa8, 0x01, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x32, 0x00, + 0xe8, 0x03, 0x00, 0x1f, 0x08, 0xf0, 0x02, 0x29, + 0x38, 0xf5, 0x00, 0x00, 0x00, 0x41, 0xf6, 0x00, + 0x00, 0x00, 0x04, 0xf7, 0x00, 0x00, 0x00, 0x24, + 0x01, 0x00, 0x0e, 0x38, 0xf5, 0x00, 0x00, 0x00, + 0x41, 0xf6, 0x00, 0x00, 0x00, 0x04, 0xf8, 0x00, + 0x00, 0x00, 0x64, 0x00, 0x00, 0xc2, 0x0a, 0xf5, + 0x24, 0x02, 0x00, 0x0e, 0x06, 0x2f, 0xe4, 0x03, + 0x01, 0x01, 0x0c, 0x00, 0x04, 0x08, 0x00, 0x34, + 0x10, 0x30, 0x0f, 0x34, 0x10, 0x2a, 0x20, 0x00, +}; + +static JSContext *JS_NewCustomContext(JSRuntime *rt) +{ + JSContext *ctx = JS_NewContext(rt); + if (!ctx) + return NULL; + js_std_eval_binary(ctx, qjsc_fib_module, qjsc_fib_module_size, 1); + return ctx; +} + +int main(int argc, char **argv) +{ + int r; + JSRuntime *rt; + JSContext *ctx; + r = 0; + rt = JS_NewRuntime(); + js_std_set_worker_new_context_func(JS_NewCustomContext); + js_std_init_handlers(rt); + JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL); + ctx = JS_NewCustomContext(rt); + js_std_add_helpers(ctx, argc, argv); + js_std_eval_binary(ctx, qjsc_hello_module, qjsc_hello_module_size, 0); + r = js_std_loop(ctx); + if (r) { + js_std_dump_error(ctx); + } + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return r; +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/repl.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/repl.c new file mode 100755 index 00000000..854540f8 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/repl.c @@ -0,0 +1,3052 @@ +/* File generated automatically by the QuickJS-ng compiler. */ + +#include + +const uint32_t qjsc_repl_size = 24338; + +const uint8_t qjsc_repl[24338] = { + 0x1a, 0x8e, 0x10, 0xe1, 0xf4, 0xb5, 0x04, 0x01, + 0x0e, 0x72, 0x65, 0x70, 0x6c, 0x2e, 0x6a, 0x73, + 0x01, 0x0e, 0x71, 0x6a, 0x73, 0x3a, 0x73, 0x74, + 0x64, 0x01, 0x0c, 0x71, 0x6a, 0x73, 0x3a, 0x6f, + 0x73, 0x01, 0x12, 0x71, 0x6a, 0x73, 0x3a, 0x62, + 0x6a, 0x73, 0x6f, 0x6e, 0x01, 0x06, 0x73, 0x74, + 0x64, 0x01, 0x04, 0x6f, 0x73, 0x01, 0x0a, 0x62, + 0x6a, 0x73, 0x6f, 0x6e, 0x01, 0x02, 0x67, 0x01, + 0x10, 0x69, 0x73, 0x46, 0x69, 0x6e, 0x69, 0x74, + 0x65, 0x01, 0x0a, 0x69, 0x73, 0x4e, 0x61, 0x4e, + 0x01, 0x10, 0x49, 0x6e, 0x66, 0x69, 0x6e, 0x69, + 0x74, 0x79, 0x01, 0x0e, 0x63, 0x6f, 0x6e, 0x73, + 0x6f, 0x6c, 0x65, 0x01, 0x10, 0x6b, 0x65, 0x79, + 0x77, 0x6f, 0x72, 0x64, 0x73, 0x01, 0x0c, 0x63, + 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x01, 0x0c, 0x74, + 0x68, 0x65, 0x6d, 0x65, 0x73, 0x01, 0x0c, 0x73, + 0x74, 0x79, 0x6c, 0x65, 0x73, 0x01, 0x08, 0x75, + 0x74, 0x66, 0x38, 0x01, 0x12, 0x73, 0x68, 0x6f, + 0x77, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x01, 0x16, + 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x63, 0x6f, 0x6c, + 0x6f, 0x72, 0x73, 0x01, 0x16, 0x73, 0x68, 0x6f, + 0x77, 0x5f, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, + 0x01, 0x14, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x64, + 0x65, 0x70, 0x74, 0x68, 0x01, 0x10, 0x68, 0x65, + 0x78, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x01, 0x14, + 0x75, 0x73, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x69, + 0x63, 0x74, 0x01, 0x0e, 0x68, 0x69, 0x73, 0x74, + 0x6f, 0x72, 0x79, 0x01, 0x1a, 0x68, 0x69, 0x73, + 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x01, 0x14, 0x63, 0x6c, 0x69, 0x70, + 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x01, 0x0c, + 0x70, 0x73, 0x74, 0x61, 0x74, 0x65, 0x01, 0x0c, + 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x01, 0x08, + 0x70, 0x6c, 0x65, 0x6e, 0x01, 0x06, 0x70, 0x73, + 0x31, 0x01, 0x06, 0x70, 0x73, 0x32, 0x01, 0x1e, + 0x65, 0x76, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x01, + 0x12, 0x65, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x01, 0x0a, 0x6d, 0x65, 0x78, 0x70, + 0x72, 0x01, 0x0a, 0x6c, 0x65, 0x76, 0x65, 0x6c, + 0x01, 0x06, 0x63, 0x6d, 0x64, 0x01, 0x14, 0x63, + 0x75, 0x72, 0x73, 0x6f, 0x72, 0x5f, 0x70, 0x6f, + 0x73, 0x01, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x5f, + 0x63, 0x6d, 0x64, 0x01, 0x1e, 0x6c, 0x61, 0x73, + 0x74, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, + 0x5f, 0x70, 0x6f, 0x73, 0x01, 0x10, 0x74, 0x68, + 0x69, 0x73, 0x5f, 0x66, 0x75, 0x6e, 0x01, 0x10, + 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x75, 0x6e, + 0x01, 0x14, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x5f, + 0x66, 0x6c, 0x61, 0x67, 0x01, 0x14, 0x75, 0x74, + 0x66, 0x38, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x01, 0x10, 0x75, 0x74, 0x66, 0x38, 0x5f, 0x76, + 0x61, 0x6c, 0x01, 0x0e, 0x74, 0x65, 0x72, 0x6d, + 0x5f, 0x66, 0x64, 0x01, 0x1a, 0x74, 0x65, 0x72, + 0x6d, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x62, + 0x75, 0x66, 0x01, 0x14, 0x74, 0x65, 0x72, 0x6d, + 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x01, 0x1a, + 0x74, 0x65, 0x72, 0x6d, 0x5f, 0x63, 0x75, 0x72, + 0x73, 0x6f, 0x72, 0x5f, 0x78, 0x01, 0x10, 0x74, + 0x65, 0x72, 0x6d, 0x49, 0x6e, 0x69, 0x74, 0x01, + 0x1c, 0x73, 0x69, 0x67, 0x69, 0x6e, 0x74, 0x5f, + 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x01, + 0x22, 0x74, 0x65, 0x72, 0x6d, 0x5f, 0x72, 0x65, + 0x61, 0x64, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, + 0x65, 0x72, 0x01, 0x16, 0x68, 0x61, 0x6e, 0x64, + 0x6c, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x01, + 0x10, 0x69, 0x73, 0x5f, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x01, 0x10, 0x69, 0x73, 0x5f, 0x64, 0x69, + 0x67, 0x69, 0x74, 0x01, 0x0e, 0x69, 0x73, 0x5f, + 0x77, 0x6f, 0x72, 0x64, 0x01, 0x10, 0x69, 0x73, + 0x5f, 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x01, 0x14, + 0x75, 0x63, 0x73, 0x5f, 0x6c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x01, 0x2a, 0x69, 0x73, 0x5f, 0x74, + 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, + 0x73, 0x75, 0x72, 0x72, 0x6f, 0x67, 0x61, 0x74, + 0x65, 0x01, 0x16, 0x69, 0x73, 0x5f, 0x62, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x01, 0x20, + 0x70, 0x72, 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x6f, + 0x6c, 0x6f, 0x72, 0x5f, 0x74, 0x65, 0x78, 0x74, + 0x01, 0x12, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x5f, + 0x63, 0x73, 0x69, 0x01, 0x16, 0x6d, 0x6f, 0x76, + 0x65, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, + 0x01, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x01, 0x0c, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, + 0x01, 0x1a, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x64, + 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x01, + 0x0a, 0x61, 0x62, 0x6f, 0x72, 0x74, 0x01, 0x0a, + 0x61, 0x6c, 0x65, 0x72, 0x74, 0x01, 0x22, 0x62, + 0x65, 0x67, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, + 0x5f, 0x6f, 0x66, 0x5f, 0x6c, 0x69, 0x6e, 0x65, + 0x01, 0x16, 0x65, 0x6e, 0x64, 0x5f, 0x6f, 0x66, + 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x01, 0x18, 0x66, + 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x63, + 0x68, 0x61, 0x72, 0x01, 0x1a, 0x62, 0x61, 0x63, + 0x6b, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x68, + 0x61, 0x72, 0x01, 0x22, 0x73, 0x6b, 0x69, 0x70, + 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x66, 0x6f, + 0x72, 0x77, 0x61, 0x72, 0x64, 0x01, 0x24, 0x73, + 0x6b, 0x69, 0x70, 0x5f, 0x77, 0x6f, 0x72, 0x64, + 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, + 0x64, 0x01, 0x18, 0x66, 0x6f, 0x72, 0x77, 0x61, + 0x72, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x01, + 0x1a, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, + 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x01, 0x18, + 0x63, 0x6c, 0x65, 0x61, 0x72, 0x5f, 0x73, 0x63, + 0x72, 0x65, 0x65, 0x6e, 0x01, 0x16, 0x61, 0x63, + 0x63, 0x65, 0x70, 0x74, 0x5f, 0x6c, 0x69, 0x6e, + 0x65, 0x01, 0x16, 0x68, 0x69, 0x73, 0x74, 0x6f, + 0x72, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x01, 0x20, + 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, + 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, + 0x01, 0x18, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x68, + 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x01, 0x1c, + 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x5f, + 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x01, 0x2e, + 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x5f, + 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x62, + 0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, 0x64, 0x01, + 0x2c, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, + 0x5f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, + 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x01, + 0x1e, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x5f, + 0x63, 0x68, 0x61, 0x72, 0x5f, 0x64, 0x69, 0x72, + 0x01, 0x16, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x5f, 0x63, 0x68, 0x61, 0x72, 0x01, 0x12, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x64, + 0x01, 0x28, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61, + 0x72, 0x64, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x01, 0x1e, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x73, + 0x65, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x73, 0x01, + 0x1e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, + 0x73, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x73, + 0x01, 0x16, 0x75, 0x70, 0x63, 0x61, 0x73, 0x65, + 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x01, 0x1a, 0x64, + 0x6f, 0x77, 0x6e, 0x63, 0x61, 0x73, 0x65, 0x5f, + 0x77, 0x6f, 0x72, 0x64, 0x01, 0x16, 0x6b, 0x69, + 0x6c, 0x6c, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, + 0x6e, 0x01, 0x12, 0x6b, 0x69, 0x6c, 0x6c, 0x5f, + 0x6c, 0x69, 0x6e, 0x65, 0x01, 0x24, 0x62, 0x61, + 0x63, 0x6b, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x6b, + 0x69, 0x6c, 0x6c, 0x5f, 0x6c, 0x69, 0x6e, 0x65, + 0x01, 0x12, 0x6b, 0x69, 0x6c, 0x6c, 0x5f, 0x77, + 0x6f, 0x72, 0x64, 0x01, 0x24, 0x62, 0x61, 0x63, + 0x6b, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x6b, 0x69, + 0x6c, 0x6c, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x01, + 0x08, 0x79, 0x61, 0x6e, 0x6b, 0x01, 0x12, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x63, + 0x01, 0x0a, 0x72, 0x65, 0x73, 0x65, 0x74, 0x01, + 0x22, 0x69, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, + 0x74, 0x79, 0x01, 0x20, 0x67, 0x65, 0x74, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, + 0x77, 0x6f, 0x72, 0x64, 0x01, 0x24, 0x67, 0x65, + 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x01, 0x1e, 0x67, 0x65, 0x74, 0x5f, 0x63, 0x6f, + 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x01, 0x14, 0x63, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x01, 0x10, 0x63, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x01, + 0x0c, 0x64, 0x75, 0x70, 0x73, 0x74, 0x72, 0x01, + 0x1a, 0x72, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, + 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x01, 0x1c, + 0x72, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x01, 0x16, + 0x72, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, + 0x5f, 0x63, 0x62, 0x01, 0x2a, 0x72, 0x65, 0x61, + 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x70, 0x72, + 0x69, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x6d, + 0x70, 0x74, 0x01, 0x1c, 0x72, 0x65, 0x61, 0x64, + 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x01, 0x16, 0x68, 0x61, 0x6e, 0x64, + 0x6c, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x01, + 0x14, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, + 0x6b, 0x65, 0x79, 0x01, 0x20, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x5f, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x01, 0x20, 0x62, + 0x69, 0x67, 0x69, 0x6e, 0x74, 0x5f, 0x74, 0x6f, + 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x01, + 0x08, 0x75, 0x74, 0x69, 0x6c, 0x01, 0x0a, 0x70, + 0x72, 0x69, 0x6e, 0x74, 0x01, 0x20, 0x68, 0x61, + 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x64, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x01, 0x08, + 0x68, 0x65, 0x6c, 0x70, 0x01, 0x08, 0x6c, 0x6f, + 0x61, 0x64, 0x01, 0x08, 0x65, 0x78, 0x69, 0x74, + 0x01, 0x0e, 0x74, 0x6f, 0x5f, 0x62, 0x6f, 0x6f, + 0x6c, 0x01, 0x14, 0x64, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x73, 0x01, 0x12, 0x63, + 0x6d, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x01, 0x24, 0x63, 0x6d, 0x64, 0x5f, 0x72, 0x65, + 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x01, 0x26, 0x72, 0x65, + 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x68, + 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x63, 0x6d, + 0x64, 0x01, 0x14, 0x68, 0x61, 0x6e, 0x64, 0x6c, + 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x01, 0x1c, 0x65, + 0x76, 0x61, 0x6c, 0x5f, 0x61, 0x6e, 0x64, 0x5f, + 0x70, 0x72, 0x69, 0x6e, 0x74, 0x01, 0x22, 0x70, + 0x72, 0x69, 0x6e, 0x74, 0x5f, 0x65, 0x76, 0x61, + 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x01, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x5f, + 0x65, 0x76, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x01, 0x1c, 0x68, 0x61, 0x6e, 0x64, + 0x6c, 0x65, 0x5f, 0x63, 0x6d, 0x64, 0x5f, 0x65, + 0x6e, 0x64, 0x01, 0x16, 0x63, 0x6f, 0x6c, 0x6f, + 0x72, 0x69, 0x7a, 0x65, 0x5f, 0x6a, 0x73, 0x01, + 0x16, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, + 0x66, 0x69, 0x6c, 0x65, 0x01, 0x18, 0x73, 0x61, + 0x76, 0x65, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, + 0x72, 0x79, 0x01, 0x18, 0x6c, 0x6f, 0x61, 0x64, + 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, + 0x01, 0x16, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x01, 0x06, 0x74, + 0x61, 0x62, 0x01, 0x0c, 0x66, 0x69, 0x6c, 0x65, + 0x6e, 0x6f, 0x01, 0x0c, 0x69, 0x73, 0x61, 0x74, + 0x74, 0x79, 0x01, 0x1a, 0x74, 0x74, 0x79, 0x47, + 0x65, 0x74, 0x57, 0x69, 0x6e, 0x53, 0x69, 0x7a, + 0x65, 0x01, 0x12, 0x74, 0x74, 0x79, 0x53, 0x65, + 0x74, 0x52, 0x61, 0x77, 0x01, 0x0c, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x6c, 0x01, 0x0c, 0x53, 0x49, + 0x47, 0x49, 0x4e, 0x54, 0x01, 0x1c, 0x73, 0x65, + 0x74, 0x52, 0x65, 0x61, 0x64, 0x48, 0x61, 0x6e, + 0x64, 0x6c, 0x65, 0x72, 0x01, 0x02, 0x6c, 0x01, + 0x02, 0x69, 0x01, 0x08, 0x72, 0x65, 0x61, 0x64, + 0x01, 0x0c, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, + 0x01, 0x02, 0x63, 0x01, 0x02, 0x41, 0x01, 0x02, + 0x5a, 0x01, 0x02, 0x61, 0x01, 0x02, 0x7a, 0x01, + 0x02, 0x5f, 0x01, 0x02, 0x24, 0x01, 0x0a, 0x09, + 0x0d, 0x0a, 0x0c, 0x0b, 0x01, 0x10, 0x69, 0x6e, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x01, 0x06, + 0x73, 0x74, 0x72, 0x01, 0x06, 0x6c, 0x65, 0x6e, + 0x01, 0x0e, 0x73, 0x74, 0x72, 0x5f, 0x6c, 0x65, + 0x6e, 0x01, 0x14, 0x63, 0x68, 0x61, 0x72, 0x43, + 0x6f, 0x64, 0x65, 0x41, 0x74, 0x01, 0x02, 0x64, + 0x01, 0x16, 0x63, 0x6f, 0x64, 0x65, 0x50, 0x6f, + 0x69, 0x6e, 0x74, 0x41, 0x74, 0x01, 0x02, 0x62, + 0x01, 0x04, 0x28, 0x29, 0x01, 0x04, 0x5b, 0x5d, + 0x01, 0x04, 0x7b, 0x7d, 0x01, 0x0a, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x01, 0x16, 0x73, 0x74, 0x79, + 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x01, 0x02, 0x6a, 0x01, 0x0a, 0x73, 0x74, 0x79, + 0x6c, 0x65, 0x01, 0x08, 0x70, 0x75, 0x74, 0x73, + 0x01, 0x08, 0x6e, 0x6f, 0x6e, 0x65, 0x01, 0x12, + 0x73, 0x75, 0x62, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x01, 0x02, 0x6e, 0x01, 0x08, 0x63, 0x6f, + 0x64, 0x65, 0x01, 0x04, 0x1b, 0x5b, 0x01, 0x0a, + 0x64, 0x65, 0x6c, 0x74, 0x61, 0x01, 0x02, 0x0a, + 0x01, 0x06, 0x6d, 0x69, 0x6e, 0x01, 0x02, 0x43, + 0x01, 0x02, 0x44, 0x01, 0x0e, 0x63, 0x6d, 0x64, + 0x5f, 0x6c, 0x65, 0x6e, 0x01, 0x14, 0x63, 0x6f, + 0x6c, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x01, 0x04, 0x20, 0x08, 0x01, 0x06, 0x1b, 0x5b, + 0x4a, 0x01, 0x06, 0x6f, 0x75, 0x74, 0x01, 0x0a, + 0x66, 0x6c, 0x75, 0x73, 0x68, 0x01, 0x0c, 0x63, + 0x68, 0x61, 0x72, 0x41, 0x74, 0x01, 0x06, 0x70, + 0x6f, 0x73, 0x01, 0x0a, 0x63, 0x6c, 0x65, 0x61, + 0x72, 0x01, 0x12, 0x74, 0x72, 0x69, 0x6d, 0x52, + 0x69, 0x67, 0x68, 0x74, 0x01, 0x08, 0x70, 0x75, + 0x73, 0x68, 0x01, 0x06, 0x64, 0x69, 0x72, 0x01, + 0x06, 0x65, 0x6e, 0x64, 0x01, 0x04, 0x70, 0x31, + 0x01, 0x04, 0x70, 0x32, 0x01, 0x04, 0x70, 0x34, + 0x01, 0x04, 0x70, 0x33, 0x01, 0x16, 0x74, 0x6f, + 0x55, 0x70, 0x70, 0x65, 0x72, 0x43, 0x61, 0x73, + 0x65, 0x01, 0x16, 0x74, 0x6f, 0x4c, 0x6f, 0x77, + 0x65, 0x72, 0x43, 0x61, 0x73, 0x65, 0x01, 0x02, + 0x73, 0x01, 0x3c, 0x0a, 0x28, 0x50, 0x72, 0x65, + 0x73, 0x73, 0x20, 0x43, 0x74, 0x72, 0x6c, 0x2d, + 0x43, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, + 0x74, 0x6f, 0x20, 0x71, 0x75, 0x69, 0x74, 0x29, + 0x0a, 0x01, 0x08, 0x6c, 0x69, 0x6e, 0x65, 0x01, + 0x02, 0x2e, 0x01, 0x0a, 0x73, 0x6c, 0x69, 0x63, + 0x65, 0x01, 0x08, 0x62, 0x61, 0x73, 0x65, 0x01, + 0x10, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x6f, + 0x73, 0x01, 0x06, 0x6f, 0x62, 0x6a, 0x01, 0x02, + 0x5c, 0x01, 0x12, 0x27, 0x22, 0x60, 0x40, 0x23, + 0x29, 0x5d, 0x7d, 0x5c, 0x01, 0x0e, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x4f, 0x66, 0x01, 0x02, 0x27, + 0x01, 0x02, 0x22, 0x01, 0x02, 0x60, 0x01, 0x02, + 0x5d, 0x01, 0x02, 0x2f, 0x01, 0x0a, 0x6d, 0x61, + 0x74, 0x63, 0x68, 0x01, 0x0e, 0x63, 0x74, 0x78, + 0x5f, 0x6f, 0x62, 0x6a, 0x01, 0x02, 0x72, 0x01, + 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x01, 0x04, + 0x6b, 0x77, 0x01, 0x0a, 0x70, 0x72, 0x6f, 0x70, + 0x73, 0x01, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x01, + 0x0c, 0x73, 0x79, 0x6d, 0x63, 0x6d, 0x70, 0x01, + 0x14, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x57, + 0x69, 0x74, 0x68, 0x01, 0x26, 0x67, 0x65, 0x74, + 0x4f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, + 0x72, 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x01, 0x08, 0x73, 0x6f, 0x72, 0x74, 0x01, 0x06, + 0x63, 0x74, 0x78, 0x01, 0x06, 0x72, 0x65, 0x73, + 0x01, 0x02, 0x74, 0x01, 0x12, 0x6d, 0x61, 0x78, + 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x01, 0x06, + 0x63, 0x6f, 0x6c, 0x01, 0x0c, 0x6e, 0x5f, 0x63, + 0x6f, 0x6c, 0x73, 0x01, 0x06, 0x72, 0x6f, 0x77, + 0x01, 0x0c, 0x6e, 0x5f, 0x72, 0x6f, 0x77, 0x73, + 0x01, 0x02, 0x6d, 0x01, 0x02, 0x28, 0x01, 0x02, + 0x29, 0x01, 0x06, 0x6d, 0x61, 0x78, 0x01, 0x0a, + 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x01, 0x08, 0x63, + 0x65, 0x69, 0x6c, 0x01, 0x0c, 0x70, 0x61, 0x64, + 0x45, 0x6e, 0x64, 0x01, 0x0a, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x01, 0x0c, 0x64, 0x65, 0x66, 0x73, + 0x74, 0x72, 0x01, 0x04, 0x63, 0x62, 0x01, 0x02, + 0x20, 0x01, 0x0e, 0x74, 0x6f, 0x46, 0x69, 0x78, + 0x65, 0x64, 0x01, 0x04, 0x63, 0x31, 0x01, 0x1a, + 0x66, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x64, 0x65, + 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x01, 0x02, 0x1b, + 0x01, 0x02, 0x5b, 0x01, 0x02, 0x4f, 0x01, 0x02, + 0x3b, 0x01, 0x06, 0x66, 0x75, 0x6e, 0x01, 0x0a, + 0x72, 0x61, 0x64, 0x69, 0x78, 0x01, 0x04, 0x2d, + 0x30, 0x01, 0x02, 0x2d, 0x01, 0x04, 0x30, 0x78, + 0x01, 0x06, 0x76, 0x61, 0x6c, 0x01, 0x12, 0x6d, + 0x61, 0x78, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, + 0x01, 0x14, 0x75, 0x73, 0x65, 0x5f, 0x63, 0x6f, + 0x6c, 0x6f, 0x72, 0x73, 0x01, 0x0e, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x01, 0x16, 0x62, + 0x72, 0x65, 0x61, 0x6b, 0x4c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x01, 0x1c, 0x6d, 0x61, 0x78, 0x41, + 0x72, 0x72, 0x61, 0x79, 0x4c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x01, 0x1e, 0x6d, 0x61, 0x78, 0x4f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x01, 0x1e, 0x6d, 0x61, 0x78, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x01, 0x08, 0x72, 0x65, + 0x66, 0x73, 0x01, 0x0c, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x73, 0x01, 0x0c, 0x6f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x01, 0x14, 0x6c, 0x61, 0x73, 0x74, + 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x01, 0x12, + 0x71, 0x75, 0x6f, 0x74, 0x65, 0x5f, 0x73, 0x74, + 0x72, 0x01, 0x14, 0x70, 0x75, 0x73, 0x68, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x01, 0x18, 0x61, + 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x01, 0x12, 0x63, 0x6c, 0x61, + 0x73, 0x73, 0x5f, 0x74, 0x61, 0x67, 0x01, 0x12, + 0x70, 0x72, 0x69, 0x6e, 0x74, 0x5f, 0x72, 0x65, + 0x63, 0x01, 0x14, 0x6f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x5f, 0x73, 0x74, 0x72, 0x01, 0x1e, 0x6f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x70, 0x72, + 0x6f, 0x70, 0x6e, 0x61, 0x6d, 0x65, 0x01, 0x1a, + 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x70, + 0x72, 0x65, 0x74, 0x74, 0x79, 0x01, 0x10, 0x69, + 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x01, + 0x16, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x77, + 0x69, 0x64, 0x74, 0x68, 0x01, 0x1a, 0x6f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x69, 0x6e, + 0x67, 0x6c, 0x65, 0x01, 0x1a, 0x6f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x5f, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x73, 0x01, 0x1a, 0x6f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x6e, + 0x74, 0x01, 0x06, 0x6f, 0x70, 0x74, 0x01, 0x06, + 0x64, 0x65, 0x66, 0x01, 0x12, 0x73, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x01, 0x14, + 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, + 0x6c, 0x6c, 0x01, 0x04, 0x5c, 0x22, 0x01, 0x02, + 0x6f, 0x01, 0x08, 0x63, 0x61, 0x6c, 0x6c, 0x01, + 0x04, 0x6e, 0x30, 0x01, 0x02, 0x6b, 0x01, 0x06, + 0x6b, 0x65, 0x79, 0x01, 0x08, 0x74, 0x79, 0x70, + 0x65, 0x01, 0x0e, 0x69, 0x73, 0x61, 0x72, 0x72, + 0x61, 0x79, 0x01, 0x0e, 0x6e, 0x6f, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x01, 0x0c, 0x6e, 0x6f, 0x6b, + 0x65, 0x79, 0x73, 0x01, 0x0a, 0x62, 0x72, 0x61, + 0x63, 0x65, 0x01, 0x06, 0x73, 0x65, 0x70, 0x01, + 0x12, 0x6f, 0x62, 0x6a, 0x5f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x01, 0x06, 0x74, 0x61, 0x67, 0x01, + 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x01, 0x08, 0x64, + 0x65, 0x73, 0x63, 0x01, 0x0c, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x73, 0x01, 0x06, 0x2e, 0x2e, 0x2e, + 0x01, 0x16, 0x5b, 0x43, 0x69, 0x72, 0x63, 0x75, + 0x6c, 0x61, 0x72, 0x20, 0x2a, 0x01, 0x0a, 0x44, + 0x61, 0x74, 0x65, 0x20, 0x01, 0x16, 0x74, 0x6f, + 0x47, 0x4d, 0x54, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x01, 0x04, 0x3a, 0x20, 0x01, 0x0e, 0x69, + 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x01, 0x06, + 0x29, 0x20, 0x5b, 0x01, 0x16, 0x5b, 0x46, 0x75, + 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, + 0x01, 0x2c, 0x5b, 0x46, 0x75, 0x6e, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x61, 0x6e, 0x6f, + 0x6e, 0x79, 0x6d, 0x6f, 0x75, 0x73, 0x29, 0x5d, + 0x01, 0x04, 0x20, 0x5b, 0x01, 0x06, 0x5d, 0x20, + 0x7b, 0x01, 0x26, 0x3a, 0x20, 0x6e, 0x75, 0x6c, + 0x6c, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, + 0x79, 0x70, 0x65, 0x5d, 0x20, 0x7b, 0x01, 0x04, + 0x20, 0x7b, 0x01, 0x02, 0x7b, 0x01, 0x02, 0x7d, + 0x01, 0x02, 0x3c, 0x01, 0x1a, 0x20, 0x65, 0x6d, + 0x70, 0x74, 0x79, 0x20, 0x69, 0x74, 0x65, 0x6d, + 0x73, 0x3e, 0x01, 0x0e, 0x3c, 0x65, 0x6d, 0x70, + 0x74, 0x79, 0x3e, 0x01, 0x08, 0x2e, 0x2e, 0x2e, + 0x20, 0x01, 0x16, 0x20, 0x6d, 0x6f, 0x72, 0x65, + 0x20, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x01, 0x02, + 0x3a, 0x01, 0x0c, 0x47, 0x65, 0x74, 0x74, 0x65, + 0x72, 0x01, 0x0c, 0x53, 0x65, 0x74, 0x74, 0x65, + 0x72, 0x01, 0x20, 0x20, 0x6d, 0x6f, 0x72, 0x65, + 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x65, 0x73, 0x01, 0x06, 0x70, 0x6f, 0x70, + 0x01, 0x0c, 0x3c, 0x72, 0x65, 0x66, 0x20, 0x2a, + 0x01, 0x04, 0x3e, 0x20, 0x01, 0x0a, 0x63, 0x6f, + 0x6c, 0x6f, 0x72, 0x01, 0x10, 0x70, 0x72, 0x6f, + 0x70, 0x6e, 0x61, 0x6d, 0x65, 0x01, 0x0a, 0x63, + 0x68, 0x75, 0x6e, 0x6b, 0x01, 0x0c, 0x72, 0x65, + 0x67, 0x65, 0x78, 0x70, 0x01, 0x14, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x01, 0x02, 0x2c, 0x01, 0x0a, 0x6f, 0x74, 0x68, + 0x65, 0x72, 0x01, 0x08, 0x64, 0x61, 0x74, 0x65, + 0x01, 0x06, 0x4e, 0x61, 0x4e, 0x01, 0x0e, 0x6b, + 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x01, 0x02, + 0x77, 0x01, 0x0a, 0x77, 0x69, 0x64, 0x74, 0x68, + 0x01, 0x0c, 0x73, 0x65, 0x70, 0x6c, 0x65, 0x6e, + 0x01, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x01, 0x04, + 0x2c, 0x20, 0x01, 0x0c, 0x72, 0x65, 0x70, 0x65, + 0x61, 0x74, 0x01, 0x0c, 0x69, 0x6e, 0x64, 0x65, + 0x6e, 0x74, 0x01, 0x16, 0x61, 0x76, 0x61, 0x69, + 0x6c, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x01, + 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x01, 0x08, + 0x63, 0x6f, 0x6c, 0x73, 0x01, 0x10, 0x63, 0x6f, + 0x6c, 0x77, 0x69, 0x64, 0x74, 0x68, 0x01, 0x10, + 0x65, 0x6e, 0x64, 0x73, 0x57, 0x69, 0x74, 0x68, + 0x01, 0x14, 0x73, 0x68, 0x6f, 0x77, 0x48, 0x69, + 0x64, 0x64, 0x65, 0x6e, 0x01, 0x0a, 0x64, 0x65, + 0x70, 0x74, 0x68, 0x01, 0x0e, 0x69, 0x6e, 0x73, + 0x70, 0x65, 0x63, 0x74, 0x01, 0x0e, 0x70, 0x61, + 0x72, 0x74, 0x69, 0x61, 0x6c, 0x01, 0x02, 0x70, + 0x01, 0x02, 0x3f, 0x01, 0x08, 0x74, 0x72, 0x69, + 0x6d, 0x01, 0x26, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, + 0x77, 0x6e, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x3a, 0x20, 0x01, 0x06, + 0x73, 0x65, 0x6c, 0x01, 0x32, 0x2e, 0x68, 0x65, + 0x6c, 0x70, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, + 0x69, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, + 0x20, 0x68, 0x65, 0x6c, 0x70, 0x0a, 0x01, 0x10, + 0x2e, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x01, 0x36, 0x68, 0x65, 0x78, 0x61, 0x64, 0x65, + 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x20, 0x64, 0x69, 0x73, + 0x70, 0x6c, 0x61, 0x79, 0x0a, 0x01, 0x10, 0x2e, + 0x64, 0x65, 0x63, 0x20, 0x20, 0x20, 0x20, 0x01, + 0x2e, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, + 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, + 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x0a, + 0x01, 0x10, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x20, + 0x20, 0x20, 0x01, 0x2c, 0x74, 0x6f, 0x67, 0x67, + 0x6c, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x69, 0x6e, + 0x67, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, + 0x79, 0x0a, 0x01, 0x10, 0x2e, 0x73, 0x74, 0x72, + 0x69, 0x63, 0x74, 0x20, 0x01, 0x3c, 0x74, 0x6f, + 0x67, 0x67, 0x6c, 0x65, 0x20, 0x73, 0x74, 0x72, + 0x69, 0x63, 0x74, 0x20, 0x6d, 0x6f, 0x64, 0x65, + 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x0a, 0x01, 0x48, 0x2e, 0x64, + 0x65, 0x70, 0x74, 0x68, 0x20, 0x20, 0x20, 0x73, + 0x65, 0x74, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x20, 0x64, 0x65, 0x70, 0x74, 0x68, 0x20, + 0x28, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x3a, 0x20, 0x01, 0x04, 0x29, 0x0a, 0x01, 0x10, + 0x2e, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x20, + 0x01, 0x42, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, + 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x20, + 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, + 0x65, 0x73, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, + 0x61, 0x79, 0x0a, 0x01, 0x10, 0x2e, 0x63, 0x6f, + 0x6c, 0x6f, 0x72, 0x20, 0x20, 0x01, 0x2c, 0x74, + 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x20, 0x63, 0x6f, + 0x6c, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x6f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x0a, 0x01, 0x10, 0x2e, + 0x64, 0x61, 0x72, 0x6b, 0x20, 0x20, 0x20, 0x01, + 0x08, 0x64, 0x61, 0x72, 0x6b, 0x01, 0x30, 0x73, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x64, 0x61, + 0x72, 0x6b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, + 0x20, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x0a, 0x01, + 0x10, 0x2e, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, + 0x20, 0x01, 0x0a, 0x6c, 0x69, 0x67, 0x68, 0x74, + 0x01, 0x32, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x63, + 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x6d, 0x65, 0x0a, 0x01, 0x38, 0x2e, 0x63, 0x6c, + 0x65, 0x61, 0x72, 0x20, 0x20, 0x20, 0x63, 0x6c, + 0x65, 0x61, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, + 0x0a, 0x01, 0x4c, 0x2e, 0x6c, 0x6f, 0x61, 0x64, + 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x61, 0x64, + 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, + 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x72, 0x6f, + 0x6d, 0x20, 0x61, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x0a, 0x01, 0x1c, 0x2e, 0x71, 0x75, 0x69, 0x74, + 0x20, 0x20, 0x20, 0x20, 0x65, 0x78, 0x69, 0x74, + 0x0a, 0x01, 0x02, 0x65, 0x01, 0x16, 0x6c, 0x61, + 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4f, + 0x66, 0x01, 0x06, 0x2e, 0x6a, 0x73, 0x01, 0x14, + 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x01, 0x1c, 0x31, 0x20, 0x74, 0x72, + 0x75, 0x65, 0x20, 0x79, 0x65, 0x73, 0x20, 0x59, + 0x65, 0x73, 0x01, 0x0c, 0x1b, 0x5b, 0x48, 0x1b, + 0x5b, 0x4a, 0x01, 0x46, 0x51, 0x75, 0x69, 0x63, + 0x6b, 0x4a, 0x53, 0x2d, 0x6e, 0x67, 0x20, 0x2d, + 0x20, 0x54, 0x79, 0x70, 0x65, 0x20, 0x22, 0x2e, + 0x68, 0x65, 0x6c, 0x70, 0x22, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x68, 0x65, 0x6c, 0x70, 0x0a, 0x01, + 0x08, 0x20, 0x20, 0x20, 0x20, 0x01, 0x08, 0x65, + 0x78, 0x70, 0x72, 0x01, 0x0c, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x01, 0x2a, 0x22, 0x75, 0x73, + 0x65, 0x20, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, + 0x22, 0x3b, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, + 0x30, 0x3b, 0x01, 0x06, 0x6e, 0x6f, 0x77, 0x01, + 0x14, 0x65, 0x76, 0x61, 0x6c, 0x53, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x01, 0x22, 0x62, 0x61, 0x63, + 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x62, + 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x01, 0x0e, + 0x54, 0x68, 0x72, 0x6f, 0x77, 0x3a, 0x20, 0x01, + 0x04, 0x67, 0x63, 0x01, 0x0a, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x01, 0x0e, 0x70, 0x72, 0x69, 0x6d, + 0x61, 0x72, 0x79, 0x01, 0x12, 0x63, 0x61, 0x6e, + 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x01, 0x14, + 0x70, 0x75, 0x73, 0x68, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x01, 0x14, 0x6c, 0x61, 0x73, 0x74, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x01, 0x12, + 0x70, 0x6f, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x01, 0x26, 0x70, 0x61, 0x72, 0x73, 0x65, + 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, + 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x01, 0x24, + 0x70, 0x61, 0x72, 0x73, 0x65, 0x5f, 0x6c, 0x69, + 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, + 0x6e, 0x74, 0x01, 0x18, 0x70, 0x61, 0x72, 0x73, + 0x65, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x01, 0x16, 0x70, 0x61, 0x72, 0x73, 0x65, 0x5f, + 0x72, 0x65, 0x67, 0x65, 0x78, 0x01, 0x18, 0x70, + 0x61, 0x72, 0x73, 0x65, 0x5f, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x01, 0x16, 0x6a, 0x73, 0x5f, + 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, + 0x01, 0x16, 0x6a, 0x73, 0x5f, 0x6e, 0x6f, 0x5f, + 0x72, 0x65, 0x67, 0x65, 0x78, 0x01, 0x10, 0x6a, + 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x01, + 0x20, 0x70, 0x61, 0x72, 0x73, 0x65, 0x5f, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x01, 0x12, 0x73, 0x65, 0x74, 0x5f, 0x73, + 0x74, 0x79, 0x6c, 0x65, 0x01, 0x0e, 0x63, 0x6f, + 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x01, 0x0a, 0x64, + 0x65, 0x6c, 0x69, 0x6d, 0x01, 0x04, 0x69, 0x31, + 0x01, 0x02, 0x7c, 0x01, 0x14, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x01, + 0x04, 0x74, 0x6f, 0x01, 0x6a, 0x62, 0x72, 0x65, + 0x61, 0x6b, 0x7c, 0x63, 0x61, 0x73, 0x65, 0x7c, + 0x63, 0x61, 0x74, 0x63, 0x68, 0x7c, 0x63, 0x6f, + 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x7c, 0x64, + 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x7c, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x7c, + 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x7c, 0x64, + 0x6f, 0x7c, 0x01, 0x5e, 0x65, 0x6c, 0x73, 0x65, + 0x7c, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x6c, 0x79, + 0x7c, 0x66, 0x6f, 0x72, 0x7c, 0x66, 0x75, 0x6e, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x7c, 0x69, 0x66, + 0x7c, 0x69, 0x6e, 0x7c, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x6f, 0x66, 0x7c, 0x6e, + 0x65, 0x77, 0x7c, 0x01, 0x5e, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x7c, 0x73, 0x77, 0x69, 0x74, + 0x63, 0x68, 0x7c, 0x74, 0x68, 0x69, 0x73, 0x7c, + 0x74, 0x68, 0x72, 0x6f, 0x77, 0x7c, 0x74, 0x72, + 0x79, 0x7c, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, + 0x7c, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x7c, 0x77, + 0x69, 0x74, 0x68, 0x7c, 0x01, 0x5a, 0x63, 0x6c, + 0x61, 0x73, 0x73, 0x7c, 0x63, 0x6f, 0x6e, 0x73, + 0x74, 0x7c, 0x65, 0x6e, 0x75, 0x6d, 0x7c, 0x69, + 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x7c, 0x65, 0x78, + 0x70, 0x6f, 0x72, 0x74, 0x7c, 0x65, 0x78, 0x74, + 0x65, 0x6e, 0x64, 0x73, 0x7c, 0x73, 0x75, 0x70, + 0x65, 0x72, 0x7c, 0x01, 0x66, 0x69, 0x6d, 0x70, + 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x7c, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, + 0x65, 0x7c, 0x6c, 0x65, 0x74, 0x7c, 0x70, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x7c, 0x70, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x7c, 0x70, 0x72, + 0x6f, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x7c, + 0x01, 0x28, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x7c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x7c, + 0x79, 0x69, 0x65, 0x6c, 0x64, 0x7c, 0x01, 0x4e, + 0x75, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, + 0x64, 0x7c, 0x6e, 0x75, 0x6c, 0x6c, 0x7c, 0x74, + 0x72, 0x75, 0x65, 0x7c, 0x66, 0x61, 0x6c, 0x73, + 0x65, 0x7c, 0x49, 0x6e, 0x66, 0x69, 0x6e, 0x69, + 0x74, 0x79, 0x7c, 0x4e, 0x61, 0x4e, 0x7c, 0x01, + 0x1e, 0x65, 0x76, 0x61, 0x6c, 0x7c, 0x61, 0x72, + 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x7c, + 0x01, 0x0c, 0x61, 0x77, 0x61, 0x69, 0x74, 0x7c, + 0x01, 0x7a, 0x7c, 0x74, 0x68, 0x69, 0x73, 0x7c, + 0x73, 0x75, 0x70, 0x65, 0x72, 0x7c, 0x75, 0x6e, + 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x7c, + 0x6e, 0x75, 0x6c, 0x6c, 0x7c, 0x74, 0x72, 0x75, + 0x65, 0x7c, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7c, + 0x49, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, + 0x7c, 0x4e, 0x61, 0x4e, 0x7c, 0x61, 0x72, 0x67, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x7c, 0x01, + 0x14, 0x7c, 0x76, 0x6f, 0x69, 0x64, 0x7c, 0x76, + 0x61, 0x72, 0x7c, 0x01, 0x02, 0x09, 0x01, 0x02, + 0x0d, 0x01, 0x02, 0x2b, 0x01, 0x1c, 0x78, 0x64, + 0x67, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, + 0x68, 0x6f, 0x6d, 0x65, 0x01, 0x08, 0x68, 0x6f, + 0x6d, 0x65, 0x01, 0x0c, 0x67, 0x65, 0x74, 0x65, + 0x6e, 0x76, 0x01, 0x1c, 0x58, 0x44, 0x47, 0x5f, + 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x48, 0x4f, + 0x4d, 0x45, 0x01, 0x08, 0x48, 0x4f, 0x4d, 0x45, + 0x01, 0x10, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, + 0x72, 0x6d, 0x01, 0x0a, 0x6c, 0x69, 0x6e, 0x75, + 0x78, 0x01, 0x1a, 0x2f, 0x2e, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x01, 0x08, 0x73, 0x74, 0x61, 0x74, 0x01, 0x16, + 0x55, 0x53, 0x45, 0x52, 0x50, 0x52, 0x4f, 0x46, + 0x49, 0x4c, 0x45, 0x01, 0x04, 0x2f, 0x2e, 0x01, + 0x02, 0x66, 0x01, 0x08, 0x6f, 0x70, 0x65, 0x6e, + 0x01, 0x16, 0x71, 0x6a, 0x73, 0x5f, 0x68, 0x69, + 0x73, 0x74, 0x6f, 0x72, 0x79, 0x01, 0x0a, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x01, 0x10, 0x6c, 0x6f, + 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x01, 0x12, + 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x46, 0x47, 0x42, + 0x47, 0x01, 0x10, 0x4e, 0x4f, 0x5f, 0x43, 0x4f, + 0x4c, 0x4f, 0x52, 0x01, 0x0c, 0x61, 0x77, 0x61, + 0x69, 0x74, 0x20, 0x01, 0x0e, 0x63, 0x61, 0x74, + 0x63, 0x68, 0x20, 0x28, 0x01, 0x0c, 0x63, 0x6c, + 0x61, 0x73, 0x73, 0x20, 0x01, 0x0c, 0x63, 0x6f, + 0x6e, 0x73, 0x74, 0x20, 0x01, 0x0a, 0x65, 0x6c, + 0x73, 0x65, 0x20, 0x01, 0x0e, 0x65, 0x78, 0x70, + 0x6f, 0x72, 0x74, 0x20, 0x01, 0x08, 0x66, 0x6f, + 0x72, 0x20, 0x01, 0x12, 0x66, 0x75, 0x6e, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x01, 0x08, 0x69, + 0x66, 0x20, 0x28, 0x01, 0x0e, 0x69, 0x6d, 0x70, + 0x6f, 0x72, 0x74, 0x20, 0x01, 0x16, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x6f, 0x66, + 0x20, 0x01, 0x08, 0x6c, 0x65, 0x74, 0x20, 0x01, + 0x08, 0x6e, 0x65, 0x77, 0x20, 0x01, 0x0c, 0x73, + 0x75, 0x70, 0x65, 0x72, 0x20, 0x01, 0x0a, 0x74, + 0x72, 0x79, 0x20, 0x7b, 0x01, 0x0e, 0x74, 0x79, + 0x70, 0x65, 0x6f, 0x66, 0x20, 0x01, 0x08, 0x76, + 0x61, 0x72, 0x20, 0x01, 0x0e, 0x77, 0x68, 0x69, + 0x6c, 0x65, 0x20, 0x28, 0x01, 0x0c, 0x79, 0x69, + 0x65, 0x6c, 0x64, 0x20, 0x01, 0x08, 0x1b, 0x5b, + 0x30, 0x6d, 0x01, 0x0a, 0x1b, 0x5b, 0x33, 0x30, + 0x6d, 0x01, 0x0a, 0x62, 0x6c, 0x61, 0x63, 0x6b, + 0x01, 0x0a, 0x1b, 0x5b, 0x33, 0x31, 0x6d, 0x01, + 0x06, 0x72, 0x65, 0x64, 0x01, 0x0a, 0x1b, 0x5b, + 0x33, 0x32, 0x6d, 0x01, 0x0a, 0x67, 0x72, 0x65, + 0x65, 0x6e, 0x01, 0x0a, 0x1b, 0x5b, 0x33, 0x33, + 0x6d, 0x01, 0x0c, 0x79, 0x65, 0x6c, 0x6c, 0x6f, + 0x77, 0x01, 0x0a, 0x1b, 0x5b, 0x33, 0x34, 0x6d, + 0x01, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x01, 0x0a, + 0x1b, 0x5b, 0x33, 0x35, 0x6d, 0x01, 0x0e, 0x6d, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x61, 0x01, 0x0a, + 0x1b, 0x5b, 0x33, 0x36, 0x6d, 0x01, 0x08, 0x63, + 0x79, 0x61, 0x6e, 0x01, 0x0a, 0x1b, 0x5b, 0x33, + 0x37, 0x6d, 0x01, 0x0a, 0x77, 0x68, 0x69, 0x74, + 0x65, 0x01, 0x0e, 0x1b, 0x5b, 0x33, 0x30, 0x3b, + 0x31, 0x6d, 0x01, 0x08, 0x67, 0x72, 0x61, 0x79, + 0x01, 0x08, 0x67, 0x72, 0x65, 0x79, 0x01, 0x0e, + 0x1b, 0x5b, 0x33, 0x31, 0x3b, 0x31, 0x6d, 0x01, + 0x14, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5f, + 0x72, 0x65, 0x64, 0x01, 0x0e, 0x1b, 0x5b, 0x33, + 0x32, 0x3b, 0x31, 0x6d, 0x01, 0x18, 0x62, 0x72, + 0x69, 0x67, 0x68, 0x74, 0x5f, 0x67, 0x72, 0x65, + 0x65, 0x6e, 0x01, 0x0e, 0x1b, 0x5b, 0x33, 0x33, + 0x3b, 0x31, 0x6d, 0x01, 0x1a, 0x62, 0x72, 0x69, + 0x67, 0x68, 0x74, 0x5f, 0x79, 0x65, 0x6c, 0x6c, + 0x6f, 0x77, 0x01, 0x0e, 0x1b, 0x5b, 0x33, 0x34, + 0x3b, 0x31, 0x6d, 0x01, 0x16, 0x62, 0x72, 0x69, + 0x67, 0x68, 0x74, 0x5f, 0x62, 0x6c, 0x75, 0x65, + 0x01, 0x0e, 0x1b, 0x5b, 0x33, 0x35, 0x3b, 0x31, + 0x6d, 0x01, 0x1c, 0x62, 0x72, 0x69, 0x67, 0x68, + 0x74, 0x5f, 0x6d, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x61, 0x01, 0x0e, 0x1b, 0x5b, 0x33, 0x36, 0x3b, + 0x31, 0x6d, 0x01, 0x16, 0x62, 0x72, 0x69, 0x67, + 0x68, 0x74, 0x5f, 0x63, 0x79, 0x61, 0x6e, 0x01, + 0x0e, 0x1b, 0x5b, 0x33, 0x37, 0x3b, 0x31, 0x6d, + 0x01, 0x18, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, + 0x5f, 0x77, 0x68, 0x69, 0x74, 0x65, 0x01, 0x0c, + 0x71, 0x6a, 0x73, 0x20, 0x3e, 0x20, 0x01, 0x0c, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x01, 0x02, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x03, 0x01, + 0x02, 0x04, 0x01, 0x02, 0x05, 0x01, 0x02, 0x06, + 0x01, 0x02, 0x07, 0x01, 0x02, 0x08, 0x01, 0x02, + 0x0b, 0x01, 0x02, 0x0c, 0x01, 0x02, 0x0e, 0x01, + 0x02, 0x10, 0x01, 0x02, 0x11, 0x01, 0x02, 0x12, + 0x01, 0x02, 0x13, 0x01, 0x02, 0x14, 0x01, 0x02, + 0x17, 0x01, 0x02, 0x18, 0x01, 0x02, 0x19, 0x01, + 0x06, 0x1b, 0x4f, 0x41, 0x01, 0x06, 0x1b, 0x4f, + 0x42, 0x01, 0x06, 0x1b, 0x4f, 0x43, 0x01, 0x06, + 0x1b, 0x4f, 0x44, 0x01, 0x06, 0x1b, 0x4f, 0x46, + 0x01, 0x06, 0x1b, 0x4f, 0x48, 0x01, 0x0c, 0x1b, + 0x5b, 0x31, 0x3b, 0x35, 0x43, 0x01, 0x0c, 0x1b, + 0x5b, 0x31, 0x3b, 0x35, 0x44, 0x01, 0x08, 0x1b, + 0x5b, 0x31, 0x7e, 0x01, 0x08, 0x1b, 0x5b, 0x33, + 0x7e, 0x01, 0x08, 0x1b, 0x5b, 0x34, 0x7e, 0x01, + 0x08, 0x1b, 0x5b, 0x35, 0x7e, 0x01, 0x08, 0x1b, + 0x5b, 0x36, 0x7e, 0x01, 0x06, 0x1b, 0x5b, 0x41, + 0x01, 0x06, 0x1b, 0x5b, 0x42, 0x01, 0x06, 0x1b, + 0x5b, 0x43, 0x01, 0x06, 0x1b, 0x5b, 0x44, 0x01, + 0x06, 0x1b, 0x5b, 0x46, 0x01, 0x06, 0x1b, 0x5b, + 0x48, 0x01, 0x04, 0x1b, 0x7f, 0x01, 0x04, 0x1b, + 0x62, 0x01, 0x04, 0x1b, 0x64, 0x01, 0x04, 0x1b, + 0x66, 0x01, 0x04, 0x1b, 0x6b, 0x01, 0x04, 0x1b, + 0x6c, 0x01, 0x04, 0x1b, 0x74, 0x01, 0x04, 0x1b, + 0x75, 0x01, 0x02, 0x7f, 0x01, 0x02, 0x78, 0x01, + 0x06, 0x64, 0x65, 0x63, 0x01, 0x08, 0x74, 0x69, + 0x6d, 0x65, 0x01, 0x0c, 0x73, 0x74, 0x72, 0x69, + 0x63, 0x74, 0x01, 0x0c, 0x68, 0x69, 0x64, 0x64, + 0x65, 0x6e, 0x01, 0x08, 0x71, 0x75, 0x69, 0x74, + 0x0d, 0xe4, 0x03, 0x03, 0xe6, 0x03, 0xe8, 0x03, + 0xea, 0x03, 0x00, 0x00, 0x03, 0x00, 0x8e, 0x02, + 0x00, 0x01, 0x8e, 0x02, 0x01, 0x02, 0x8e, 0x02, + 0x02, 0x00, 0x0c, 0x20, 0x02, 0x01, 0xa8, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x01, 0x0f, + 0x00, 0xec, 0x03, 0x00, 0x1e, 0xee, 0x03, 0x01, + 0x1e, 0xf0, 0x03, 0x02, 0x1e, 0x0c, 0x43, 0x02, + 0x01, 0x00, 0x01, 0x8d, 0x01, 0x01, 0x15, 0x6c, + 0x03, 0x5e, 0xf9, 0x0d, 0x8e, 0x01, 0xf2, 0x03, + 0x00, 0x01, 0x40, 0x30, 0xbc, 0x02, 0x00, 0x00, + 0x40, 0x37, 0xc4, 0x02, 0x00, 0x01, 0x40, 0x45, + 0xc2, 0x02, 0x00, 0x02, 0x40, 0x53, 0xc6, 0x02, + 0x00, 0x03, 0x40, 0x52, 0xf8, 0x02, 0x00, 0x04, + 0x40, 0x54, 0xe2, 0x02, 0x00, 0x05, 0x40, 0x03, + 0xbe, 0x02, 0x00, 0x06, 0x40, 0x55, 0xd0, 0x02, + 0x00, 0x07, 0x40, 0x51, 0xd8, 0x02, 0x00, 0x08, + 0x40, 0x34, 0xc0, 0x02, 0x00, 0x09, 0x40, 0x69, + 0xc8, 0x02, 0x00, 0x0a, 0x00, 0xcc, 0x02, 0x00, + 0x0b, 0x40, 0x10, 0xce, 0x02, 0x00, 0x0c, 0x40, + 0x4d, 0xf4, 0x03, 0x00, 0x0d, 0x40, 0x4b, 0xf6, + 0x03, 0x00, 0x0e, 0x40, 0x32, 0xf8, 0x03, 0x00, + 0x0f, 0x40, 0x4c, 0xfa, 0x03, 0x00, 0x10, 0x00, + 0xfc, 0x03, 0x00, 0x11, 0x40, 0x36, 0xfe, 0x03, + 0x00, 0x12, 0x40, 0x0d, 0x80, 0x04, 0x00, 0x13, + 0x40, 0x5b, 0x82, 0x04, 0x00, 0x14, 0x40, 0x0e, + 0x84, 0x04, 0x00, 0x15, 0x40, 0x07, 0x86, 0x04, + 0x00, 0x16, 0x40, 0x40, 0x88, 0x04, 0x00, 0x17, + 0x40, 0x14, 0x8a, 0x04, 0x00, 0x18, 0x40, 0x58, + 0x8c, 0x04, 0x00, 0x19, 0x40, 0x57, 0x8e, 0x04, + 0x00, 0x1a, 0x40, 0x4f, 0x90, 0x04, 0x00, 0x1b, + 0x40, 0x5a, 0x92, 0x04, 0x00, 0x1c, 0x40, 0x23, + 0x94, 0x04, 0x00, 0x1d, 0x40, 0x24, 0x96, 0x04, + 0x00, 0x1e, 0x40, 0x29, 0x98, 0x04, 0x00, 0x1f, + 0x40, 0x3c, 0x9a, 0x04, 0x00, 0x20, 0x40, 0x3a, + 0x9c, 0x04, 0x00, 0x21, 0x40, 0x3e, 0x9e, 0x04, + 0x00, 0x22, 0x40, 0x42, 0xa0, 0x04, 0x00, 0x23, + 0x40, 0x3f, 0xa2, 0x04, 0x00, 0x24, 0x40, 0x64, + 0xa4, 0x04, 0x00, 0x25, 0x40, 0x41, 0xa6, 0x04, + 0x00, 0x26, 0x40, 0x18, 0xa8, 0x04, 0x00, 0x27, + 0x40, 0x5f, 0xaa, 0x04, 0x00, 0x28, 0x40, 0x12, + 0xac, 0x04, 0x00, 0x29, 0x40, 0x1b, 0xae, 0x04, + 0x00, 0x2a, 0x40, 0x13, 0xb0, 0x04, 0x00, 0x2b, + 0x40, 0x15, 0xb2, 0x04, 0x00, 0x2c, 0x40, 0x2a, + 0xb4, 0x04, 0x00, 0x2d, 0x40, 0x26, 0xb6, 0x04, + 0x00, 0x2e, 0x40, 0x1c, 0xb8, 0x04, 0x00, 0x2f, + 0x40, 0x09, 0xba, 0x04, 0x00, 0x30, 0x40, 0x0a, + 0xbc, 0x04, 0x00, 0x31, 0x40, 0x00, 0xbe, 0x04, + 0x00, 0x32, 0x40, 0x04, 0xc0, 0x04, 0x00, 0x33, + 0x40, 0x01, 0xc2, 0x04, 0x00, 0x34, 0x40, 0x0f, + 0xc4, 0x04, 0x00, 0x35, 0x00, 0xc6, 0x04, 0x00, + 0x36, 0x40, 0x02, 0xc8, 0x04, 0x00, 0x37, 0x40, + 0x05, 0xca, 0x04, 0x00, 0x38, 0x40, 0x06, 0xcc, + 0x04, 0x00, 0x39, 0x40, 0x0b, 0xce, 0x04, 0x00, + 0x3a, 0x40, 0x0c, 0xd0, 0x04, 0x00, 0x3b, 0x40, + 0x1e, 0xd2, 0x04, 0x00, 0x3c, 0x40, 0x2f, 0xd4, + 0x04, 0x00, 0x3d, 0x40, 0x17, 0xd6, 0x04, 0x00, + 0x3e, 0x40, 0x1d, 0xd8, 0x04, 0x00, 0x3f, 0x40, + 0x6a, 0xda, 0x04, 0x00, 0x40, 0x40, 0x1a, 0xdc, + 0x04, 0x00, 0x41, 0x40, 0x11, 0xde, 0x04, 0x00, + 0x42, 0x40, 0x16, 0xe0, 0x04, 0x00, 0x43, 0x40, + 0x43, 0xe2, 0x04, 0x00, 0x44, 0x40, 0x2b, 0xe4, + 0x04, 0x00, 0x45, 0x00, 0xe6, 0x04, 0x00, 0x46, + 0x00, 0xe8, 0x04, 0x00, 0x47, 0x40, 0x4a, 0xea, + 0x04, 0x00, 0x48, 0x00, 0xec, 0x04, 0x00, 0x49, + 0x00, 0xee, 0x04, 0x00, 0x4a, 0x00, 0xf0, 0x04, + 0x00, 0x4b, 0x00, 0xf2, 0x04, 0x00, 0x4c, 0x40, + 0x1f, 0xf4, 0x04, 0x00, 0x4d, 0x40, 0x20, 0xf6, + 0x04, 0x00, 0x4e, 0x00, 0xf8, 0x04, 0x00, 0x4f, + 0x00, 0xfa, 0x04, 0x00, 0x50, 0x00, 0xfc, 0x04, + 0x00, 0x51, 0x00, 0xfe, 0x04, 0x00, 0x52, 0x40, + 0x22, 0x80, 0x05, 0x00, 0x53, 0x00, 0x82, 0x05, + 0x00, 0x54, 0x00, 0x84, 0x05, 0x00, 0x55, 0x40, + 0x25, 0x86, 0x05, 0x00, 0x56, 0x00, 0x88, 0x05, + 0x00, 0x57, 0x00, 0x8a, 0x05, 0x00, 0x58, 0x40, + 0x28, 0x8c, 0x05, 0x00, 0x59, 0x00, 0x8e, 0x05, + 0x00, 0x5a, 0x00, 0x90, 0x05, 0x00, 0x5b, 0x00, + 0x92, 0x05, 0x00, 0x5c, 0x00, 0x94, 0x05, 0x00, + 0x5d, 0x00, 0x96, 0x05, 0x00, 0x5e, 0x00, 0x98, + 0x05, 0x00, 0x5f, 0x00, 0x9a, 0x05, 0x00, 0x60, + 0x40, 0x27, 0x9c, 0x05, 0x00, 0x61, 0x00, 0x9e, + 0x05, 0x00, 0x62, 0x00, 0xa0, 0x05, 0x00, 0x63, + 0x00, 0xa2, 0x05, 0x00, 0x64, 0x00, 0xa4, 0x05, + 0x00, 0x65, 0x00, 0xa6, 0x05, 0x00, 0x66, 0x40, + 0x2c, 0xa8, 0x05, 0x00, 0x67, 0x00, 0xaa, 0x05, + 0x00, 0x68, 0x40, 0x35, 0xac, 0x05, 0x00, 0x69, + 0x40, 0x31, 0xae, 0x05, 0x00, 0x6a, 0x40, 0x33, + 0xb0, 0x05, 0x00, 0x6b, 0x40, 0x38, 0xb2, 0x05, + 0x00, 0x6c, 0x40, 0x39, 0xb4, 0x05, 0x00, 0x6d, + 0x40, 0x48, 0xb6, 0x05, 0x00, 0x6e, 0x40, 0x3d, + 0xb8, 0x05, 0x00, 0x6f, 0x40, 0x46, 0xba, 0x05, + 0x00, 0x70, 0x40, 0x44, 0xbc, 0x05, 0x00, 0x71, + 0x40, 0x3b, 0xbe, 0x05, 0x00, 0x72, 0x40, 0x2e, + 0xc0, 0x05, 0x00, 0x73, 0x40, 0x5e, 0xc2, 0x05, + 0x00, 0x74, 0x40, 0x08, 0xc4, 0x05, 0x00, 0x75, + 0x40, 0x47, 0xc6, 0x05, 0x00, 0x76, 0x40, 0x4e, + 0xc8, 0x05, 0x00, 0x77, 0x40, 0x50, 0xca, 0x05, + 0x00, 0x78, 0x40, 0x56, 0xcc, 0x05, 0x00, 0x79, + 0x40, 0x67, 0xce, 0x05, 0x00, 0x7a, 0x40, 0x62, + 0xd0, 0x05, 0x00, 0x7b, 0x40, 0x59, 0xd2, 0x05, + 0x00, 0x7c, 0x00, 0xd4, 0x05, 0x00, 0x7d, 0x40, + 0x2d, 0xd6, 0x05, 0x00, 0x7e, 0x40, 0x5c, 0xd8, + 0x05, 0x00, 0x7f, 0x40, 0x21, 0xda, 0x05, 0x00, + 0x80, 0x01, 0x00, 0xdc, 0x05, 0x00, 0x81, 0x01, + 0x40, 0x5d, 0xde, 0x05, 0x00, 0x82, 0x01, 0x40, + 0x60, 0xe0, 0x05, 0x00, 0x83, 0x01, 0x40, 0x61, + 0xe2, 0x05, 0x00, 0x84, 0x01, 0x40, 0x63, 0xe4, + 0x05, 0x00, 0x85, 0x01, 0x40, 0x65, 0xe6, 0x05, + 0x00, 0x86, 0x01, 0x40, 0x66, 0xe8, 0x05, 0x00, + 0x87, 0x01, 0x40, 0x68, 0xea, 0x05, 0x00, 0x88, + 0x01, 0x40, 0x19, 0xec, 0x05, 0x00, 0x89, 0x01, + 0x40, 0x6b, 0xee, 0x05, 0x00, 0x8a, 0x01, 0x40, + 0x49, 0xf0, 0x05, 0x00, 0x8b, 0x01, 0x00, 0xf2, + 0x05, 0x00, 0x8c, 0x01, 0x00, 0xec, 0x03, 0x00, + 0x1a, 0xee, 0x03, 0x01, 0x1a, 0xf0, 0x03, 0x02, + 0x1a, 0x0c, 0x43, 0x02, 0x01, 0xc4, 0x04, 0x00, + 0x01, 0x00, 0x04, 0x00, 0x08, 0x00, 0x89, 0x01, + 0x01, 0xf4, 0x05, 0x00, 0x00, 0x00, 0xec, 0x03, + 0x00, 0x1a, 0xbc, 0x04, 0x31, 0x00, 0xc0, 0x04, + 0x33, 0x00, 0xee, 0x03, 0x01, 0x1a, 0xc6, 0x04, + 0x36, 0x00, 0xe2, 0x02, 0x05, 0x00, 0xbe, 0x04, + 0x32, 0x00, 0xc8, 0x04, 0x37, 0x00, 0x64, 0x00, + 0x00, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x41, 0x7b, + 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, 0xe8, 0xc2, + 0x50, 0xe9, 0x64, 0x03, 0x00, 0x41, 0x7c, 0x01, + 0x00, 0x00, 0xe4, 0x24, 0x01, 0x00, 0xf0, 0x35, + 0x64, 0x03, 0x00, 0x40, 0x7d, 0x01, 0x00, 0x00, + 0xf0, 0x14, 0x64, 0x03, 0x00, 0x41, 0x7d, 0x01, + 0x00, 0x00, 0xe4, 0x24, 0x01, 0x00, 0xd3, 0xf0, + 0x05, 0xcb, 0xba, 0x46, 0xe9, 0x64, 0x03, 0x00, + 0x40, 0x7e, 0x01, 0x00, 0x00, 0xf0, 0x0e, 0x64, + 0x03, 0x00, 0x41, 0x7e, 0x01, 0x00, 0x00, 0xe4, + 0x24, 0x01, 0x00, 0x0e, 0x64, 0x03, 0x00, 0x41, + 0x7f, 0x01, 0x00, 0x00, 0x64, 0x03, 0x00, 0x40, + 0x80, 0x01, 0x00, 0x00, 0x5d, 0x04, 0x00, 0x24, + 0x02, 0x00, 0x0e, 0x5d, 0x05, 0x00, 0x11, 0xc2, + 0x40, 0x21, 0x01, 0x00, 0x5e, 0x06, 0x00, 0x64, + 0x03, 0x00, 0x41, 0x81, 0x01, 0x00, 0x00, 0xe4, + 0x5d, 0x07, 0x00, 0x24, 0x02, 0x00, 0x29, 0x0c, + 0x43, 0x02, 0x01, 0xc6, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0xca, 0x04, + 0x38, 0x00, 0xe3, 0xbd, 0xf5, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0xc8, 0x04, 0x00, 0x02, 0x00, 0x06, + 0x00, 0x04, 0x00, 0x28, 0x02, 0x84, 0x06, 0x00, + 0x00, 0x00, 0x86, 0x06, 0x00, 0x01, 0x00, 0xee, + 0x03, 0x01, 0x1a, 0xbc, 0x04, 0x31, 0x00, 0xbe, + 0x04, 0x32, 0x00, 0xca, 0x04, 0x38, 0x00, 0x64, + 0x00, 0x00, 0x41, 0x84, 0x01, 0x00, 0x00, 0xe4, + 0xe5, 0x40, 0x85, 0x01, 0x00, 0x00, 0xba, 0xe5, + 0xef, 0x24, 0x04, 0x00, 0xcf, 0xba, 0xd0, 0xcc, + 0xcb, 0xa5, 0xf0, 0x0b, 0xe6, 0xe5, 0xcc, 0x46, + 0xf5, 0x0e, 0x92, 0x01, 0xf2, 0xf2, 0x29, 0x0c, + 0x43, 0x02, 0x01, 0xca, 0x04, 0x01, 0x00, 0x01, + 0x04, 0x00, 0x04, 0x00, 0x5f, 0x01, 0x8c, 0x06, + 0x00, 0x01, 0x00, 0x84, 0x04, 0x15, 0x00, 0xc2, + 0x05, 0x74, 0x00, 0xb8, 0x04, 0x2f, 0x00, 0xba, + 0x04, 0x30, 0x00, 0xe3, 0x95, 0xf0, 0x06, 0xe4, + 0xd7, 0xf5, 0x0e, 0x29, 0xe5, 0xba, 0xae, 0xf0, + 0x24, 0xd7, 0xc3, 0x80, 0x00, 0xa8, 0xf0, 0x1d, + 0xd7, 0xc3, 0xc0, 0x00, 0xa5, 0xf0, 0x16, 0xe6, + 0xc0, 0x9e, 0xd7, 0xc2, 0x3f, 0xa1, 0xa3, 0xea, + 0xe5, 0x8d, 0xed, 0xba, 0xad, 0xf0, 0x33, 0xe4, + 0xe6, 0xf5, 0x0e, 0x29, 0xd7, 0xc3, 0xc0, 0x00, + 0xa8, 0xf0, 0x21, 0xd7, 0xc3, 0xf8, 0x00, 0xa5, + 0xf0, 0x1a, 0xbb, 0xd7, 0xc3, 0xe0, 0x00, 0xa8, + 0x9c, 0xd7, 0xc3, 0xf0, 0x00, 0xa8, 0x9c, 0xe9, + 0xd7, 0xbb, 0xc0, 0xe5, 0x9d, 0x9e, 0xbb, 0x9d, + 0xa1, 0xea, 0x29, 0xba, 0xe9, 0xe4, 0xd7, 0xf5, + 0x0e, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xcc, 0x04, + 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x35, + 0x01, 0x8c, 0x06, 0x00, 0x01, 0x00, 0xd7, 0x96, + 0x04, 0x4c, 0x00, 0x00, 0x00, 0xad, 0x11, 0xf0, + 0x2a, 0x0e, 0xd7, 0x04, 0x87, 0x01, 0x00, 0x00, + 0xa8, 0x11, 0xf0, 0x09, 0x0e, 0xd7, 0x04, 0x88, + 0x01, 0x00, 0x00, 0xa6, 0x11, 0xf1, 0x14, 0x0e, + 0xd7, 0x04, 0x89, 0x01, 0x00, 0x00, 0xa8, 0x11, + 0xf0, 0x09, 0x0e, 0xd7, 0x04, 0x8a, 0x01, 0x00, + 0x00, 0xa6, 0x28, 0x0c, 0x43, 0x02, 0x01, 0xce, + 0x04, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x02, + 0x19, 0x01, 0x8c, 0x06, 0x00, 0x01, 0x00, 0x07, + 0x02, 0x30, 0x07, 0x02, 0x39, 0xd7, 0x96, 0x04, + 0x4c, 0x00, 0x00, 0x00, 0xad, 0x11, 0xf0, 0x0e, + 0x0e, 0xd7, 0xc4, 0x00, 0xa8, 0x11, 0xf0, 0x06, + 0x0e, 0xd7, 0xc4, 0x01, 0xa6, 0x28, 0x0c, 0x43, + 0x02, 0x01, 0xd0, 0x04, 0x01, 0x00, 0x01, 0x02, + 0x00, 0x02, 0x00, 0x2d, 0x01, 0x8c, 0x06, 0x00, + 0x01, 0x00, 0xcc, 0x04, 0x39, 0x00, 0xce, 0x04, + 0x3a, 0x00, 0xd7, 0x96, 0x04, 0x4c, 0x00, 0x00, + 0x00, 0xad, 0x11, 0xf0, 0x22, 0x0e, 0xe3, 0xd7, + 0xf5, 0x11, 0xf1, 0x1b, 0x0e, 0xe4, 0xd7, 0xf5, + 0x11, 0xf1, 0x14, 0x0e, 0xd7, 0x04, 0x8b, 0x01, + 0x00, 0x00, 0xab, 0x11, 0xf1, 0x09, 0x0e, 0xd7, + 0x04, 0x8c, 0x01, 0x00, 0x00, 0xab, 0x28, 0x0c, + 0x43, 0x02, 0x01, 0xd2, 0x04, 0x01, 0x00, 0x01, + 0x04, 0x00, 0x00, 0x00, 0x1d, 0x01, 0x8c, 0x06, + 0x00, 0x01, 0x00, 0xd7, 0x96, 0x04, 0x4c, 0x00, + 0x00, 0x00, 0xad, 0x11, 0xf0, 0x12, 0x0e, 0x04, + 0x8d, 0x01, 0x00, 0x00, 0x41, 0x8e, 0x01, 0x00, + 0x00, 0xd7, 0xba, 0x46, 0x24, 0x01, 0x00, 0x28, + 0x0c, 0x43, 0x02, 0x01, 0xd4, 0x04, 0x01, 0x04, + 0x01, 0x03, 0x00, 0x00, 0x00, 0x32, 0x05, 0x9e, + 0x06, 0x00, 0x01, 0x00, 0xa0, 0x06, 0x00, 0x00, + 0x00, 0x8c, 0x06, 0x00, 0x01, 0x00, 0x86, 0x06, + 0x00, 0x02, 0x00, 0xa2, 0x06, 0x00, 0x03, 0x00, + 0xd7, 0xef, 0xd2, 0xba, 0xcf, 0xba, 0xd1, 0xcd, + 0xce, 0xa5, 0xf0, 0x25, 0xd7, 0x41, 0x92, 0x01, + 0x00, 0x00, 0xcd, 0x24, 0x01, 0x00, 0xd4, 0x01, + 0x00, 0xdc, 0x00, 0x00, 0xa5, 0x11, 0xf1, 0x09, + 0x0e, 0xcc, 0x01, 0x00, 0xe0, 0x00, 0x00, 0xa8, + 0xf0, 0x03, 0x92, 0x00, 0x92, 0x02, 0xf2, 0xd8, + 0xcb, 0x28, 0x0c, 0x43, 0x02, 0x01, 0xd6, 0x04, + 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x29, + 0x02, 0x8c, 0x06, 0x00, 0x01, 0x00, 0xa6, 0x06, + 0x00, 0x00, 0x00, 0xd7, 0x96, 0x04, 0x4c, 0x00, + 0x00, 0x00, 0xae, 0xf0, 0x03, 0x09, 0x28, 0xd7, + 0x41, 0x94, 0x01, 0x00, 0x00, 0xba, 0x24, 0x01, + 0x00, 0xd3, 0x01, 0x00, 0xdc, 0x00, 0x00, 0xa8, + 0x11, 0xf0, 0x09, 0x0e, 0xcb, 0x01, 0x00, 0xe0, + 0x00, 0x00, 0xa5, 0x28, 0x0c, 0x43, 0x02, 0x01, + 0xd8, 0x04, 0x02, 0x00, 0x02, 0x03, 0x00, 0x00, + 0x00, 0x23, 0x02, 0x92, 0x06, 0x00, 0x01, 0x00, + 0xaa, 0x06, 0x00, 0x01, 0x00, 0xd7, 0xd8, 0x9c, + 0x11, 0x04, 0x96, 0x01, 0x00, 0x00, 0xad, 0xf1, + 0x13, 0x11, 0x04, 0x97, 0x01, 0x00, 0x00, 0xad, + 0xf1, 0x0a, 0x11, 0x04, 0x98, 0x01, 0x00, 0x00, + 0xad, 0xf0, 0x03, 0x0a, 0x28, 0x0e, 0x09, 0x28, + 0x0c, 0x43, 0x02, 0x01, 0xda, 0x04, 0x03, 0x03, + 0x03, 0x06, 0x00, 0x03, 0x00, 0x62, 0x06, 0x9e, + 0x06, 0x00, 0x01, 0x00, 0xb2, 0x06, 0x00, 0x01, + 0x00, 0xb4, 0x06, 0x00, 0x01, 0x00, 0x86, 0x06, + 0x00, 0x00, 0x00, 0xb6, 0x06, 0x00, 0x01, 0x00, + 0xb8, 0x06, 0x00, 0x02, 0x00, 0xec, 0x03, 0x00, + 0x1a, 0xfe, 0x03, 0x12, 0x00, 0x82, 0x04, 0x14, + 0x00, 0xd8, 0xd0, 0xcc, 0xd7, 0xef, 0xa5, 0xf0, + 0x5a, 0xd9, 0xcc, 0xd3, 0x46, 0xd1, 0xcc, 0x8e, + 0xd4, 0xd7, 0xef, 0xa5, 0xf0, 0x08, 0xd9, 0xcc, + 0x46, 0xcd, 0xab, 0xf1, 0xf2, 0x64, 0x00, 0x00, + 0x41, 0x9d, 0x01, 0x00, 0x00, 0xe4, 0xe5, 0xcd, + 0x46, 0x11, 0xf1, 0x07, 0x0e, 0x04, 0x9e, 0x01, + 0x00, 0x00, 0x46, 0x24, 0x01, 0x00, 0x0e, 0x64, + 0x00, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, 0xd7, + 0x41, 0x9f, 0x01, 0x00, 0x00, 0xca, 0x24, 0x02, + 0x00, 0x24, 0x01, 0x00, 0x0e, 0x64, 0x00, 0x00, + 0x41, 0x9d, 0x01, 0x00, 0x00, 0xe4, 0x04, 0x9e, + 0x01, 0x00, 0x00, 0x46, 0x24, 0x01, 0x00, 0x0e, + 0xf2, 0xa2, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xdc, + 0x04, 0x02, 0x00, 0x02, 0x05, 0x00, 0x01, 0x00, + 0x1d, 0x02, 0xc0, 0x06, 0x00, 0x01, 0x00, 0xc2, + 0x06, 0x00, 0x01, 0x00, 0xec, 0x03, 0x00, 0x1a, + 0x64, 0x00, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, + 0x04, 0xa2, 0x01, 0x00, 0x00, 0xd7, 0xbb, 0xac, + 0xf0, 0x04, 0xd7, 0xf2, 0x02, 0xc6, 0x9c, 0xd8, + 0x9c, 0x24, 0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0xde, 0x04, 0x01, 0x02, 0x01, 0x04, 0x00, + 0x05, 0x00, 0xa1, 0x01, 0x03, 0xc6, 0x06, 0x00, + 0x01, 0x00, 0x86, 0x06, 0x00, 0x00, 0x00, 0x84, + 0x06, 0x00, 0x01, 0x00, 0xc2, 0x04, 0x34, 0x00, + 0xc0, 0x04, 0x33, 0x00, 0xec, 0x03, 0x00, 0x1a, + 0xcc, 0x02, 0x0b, 0x00, 0xdc, 0x04, 0x41, 0x00, + 0xd7, 0xba, 0xa7, 0xf0, 0x4d, 0xd7, 0xba, 0xac, + 0x68, 0x97, 0x00, 0x00, 0x00, 0xe3, 0xe4, 0xbb, + 0x9d, 0xab, 0xf0, 0x19, 0x64, 0x02, 0x00, 0x41, + 0x9d, 0x01, 0x00, 0x00, 0x04, 0xa4, 0x01, 0x00, + 0x00, 0x24, 0x01, 0x00, 0x0e, 0xba, 0xe7, 0xd7, + 0x8d, 0xdb, 0xf2, 0xda, 0xe6, 0x41, 0xa5, 0x01, + 0x00, 0x00, 0xe4, 0xbb, 0x9d, 0xe3, 0x9d, 0xd7, + 0x24, 0x02, 0x00, 0xd0, 0x5d, 0x04, 0x00, 0xcc, + 0x04, 0xa6, 0x01, 0x00, 0x00, 0xf6, 0x0e, 0xd7, + 0xcc, 0x9d, 0xdb, 0xe3, 0xcc, 0x9c, 0xe7, 0xf2, + 0xb5, 0xd7, 0x8b, 0xdb, 0xd7, 0xba, 0xac, 0xf0, + 0x48, 0xe3, 0xba, 0xab, 0xf0, 0x22, 0x5d, 0x04, + 0x00, 0xbb, 0x04, 0x87, 0x01, 0x00, 0x00, 0xf6, + 0x0e, 0x5d, 0x04, 0x00, 0xe4, 0xbb, 0x9d, 0x04, + 0xa6, 0x01, 0x00, 0x00, 0xf6, 0x0e, 0xd7, 0x8d, + 0xdb, 0xe4, 0xbb, 0x9d, 0xe7, 0xf2, 0xd6, 0xe6, + 0x41, 0xa5, 0x01, 0x00, 0x00, 0xd7, 0xe3, 0x24, + 0x02, 0x00, 0xd0, 0x5d, 0x04, 0x00, 0xcc, 0x04, + 0xa7, 0x01, 0x00, 0x00, 0xf6, 0x0e, 0xd7, 0xcc, + 0x9d, 0xdb, 0xe3, 0xcc, 0x9d, 0xe7, 0xf2, 0xb5, + 0x29, 0x0c, 0x43, 0x02, 0x01, 0xe0, 0x04, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x9c, 0x02, + 0x05, 0x86, 0x06, 0x00, 0x00, 0x00, 0xd0, 0x06, + 0x00, 0x01, 0x00, 0x9e, 0x06, 0x00, 0x02, 0x00, + 0xb2, 0x06, 0x00, 0x03, 0x00, 0xd2, 0x06, 0x00, + 0x04, 0x00, 0xaa, 0x04, 0x28, 0x00, 0xae, 0x04, + 0x2a, 0x00, 0x88, 0x04, 0x17, 0x00, 0xb0, 0x04, + 0x2b, 0x00, 0xec, 0x03, 0x00, 0x1a, 0xde, 0x04, + 0x42, 0x00, 0xd4, 0x04, 0x3d, 0x00, 0xa6, 0x04, + 0x26, 0x00, 0xea, 0x05, 0x88, 0x01, 0x00, 0xda, + 0x04, 0x40, 0x00, 0xc2, 0x04, 0x34, 0x00, 0xc0, + 0x04, 0x33, 0x00, 0xac, 0x04, 0x29, 0x00, 0xe3, + 0xe4, 0xac, 0x68, 0xc6, 0x00, 0x00, 0x00, 0xe5, + 0x95, 0xf0, 0x32, 0xe4, 0x41, 0x9f, 0x01, 0x00, + 0x00, 0xba, 0xe6, 0x24, 0x02, 0x00, 0xe3, 0x41, + 0x9f, 0x01, 0x00, 0x00, 0xba, 0xe6, 0x24, 0x02, + 0x00, 0xab, 0xf0, 0x19, 0x64, 0x04, 0x00, 0x41, + 0x9d, 0x01, 0x00, 0x00, 0xe3, 0x41, 0x9f, 0x01, + 0x00, 0x00, 0xe6, 0x24, 0x01, 0x00, 0x24, 0x01, + 0x00, 0x0e, 0xf2, 0x53, 0x5d, 0x05, 0x00, 0x5d, + 0x06, 0x00, 0xe4, 0x41, 0x9f, 0x01, 0x00, 0x00, + 0xba, 0xe6, 0x24, 0x02, 0x00, 0xf5, 0x8b, 0xf5, + 0x0e, 0xe5, 0xf0, 0x2e, 0x5d, 0x07, 0x00, 0xf0, + 0x0e, 0x5d, 0x07, 0x00, 0x04, 0xa4, 0x01, 0x00, + 0x00, 0x9c, 0xe3, 0x9c, 0xf2, 0x02, 0xe3, 0xd5, + 0xef, 0xe3, 0xef, 0x9d, 0xd2, 0x5d, 0x08, 0x00, + 0xcd, 0xf5, 0xc8, 0x04, 0x5d, 0x09, 0x00, 0xcd, + 0xce, 0xc7, 0x04, 0xbc, 0x46, 0xf7, 0x0e, 0xf2, + 0x0e, 0x64, 0x04, 0x00, 0x41, 0x9d, 0x01, 0x00, + 0x00, 0xe3, 0x24, 0x01, 0x00, 0x0e, 0x5d, 0x0a, + 0x00, 0x5d, 0x06, 0x00, 0xe3, 0xf5, 0x9c, 0x5d, + 0x0b, 0x00, 0x9b, 0x5f, 0x0a, 0x00, 0xba, 0xab, + 0xf0, 0x12, 0x64, 0x04, 0x00, 0x41, 0x9d, 0x01, + 0x00, 0x00, 0x04, 0xaa, 0x01, 0x00, 0x00, 0x24, + 0x01, 0x00, 0x0e, 0x64, 0x04, 0x00, 0x41, 0x9d, + 0x01, 0x00, 0x00, 0x04, 0xab, 0x01, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x0e, 0xe3, 0xe8, 0xe3, 0xef, + 0xea, 0x5d, 0x0c, 0x00, 0xe6, 0xa7, 0xf0, 0x19, + 0x5d, 0x05, 0x00, 0x5d, 0x06, 0x00, 0xe3, 0x41, + 0x9f, 0x01, 0x00, 0x00, 0xe6, 0x5d, 0x0c, 0x00, + 0x24, 0x02, 0x00, 0xf5, 0xf5, 0x0e, 0xf2, 0x1f, + 0x5d, 0x0c, 0x00, 0xe6, 0xa5, 0xf0, 0x18, 0x5d, + 0x05, 0x00, 0x5d, 0x06, 0x00, 0xe3, 0x41, 0x9f, + 0x01, 0x00, 0x00, 0x5d, 0x0c, 0x00, 0xe6, 0x24, + 0x02, 0x00, 0xf5, 0x8b, 0xf5, 0x0e, 0x5d, 0x0c, + 0x00, 0xea, 0x64, 0x04, 0x00, 0x40, 0xac, 0x01, + 0x00, 0x00, 0x41, 0xad, 0x01, 0x00, 0x00, 0x24, + 0x00, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xe2, + 0x04, 0x01, 0x00, 0x01, 0x04, 0x00, 0x02, 0x00, + 0x22, 0x01, 0x9e, 0x06, 0x00, 0x01, 0x00, 0xaa, + 0x04, 0x28, 0x00, 0xac, 0x04, 0x29, 0x00, 0xd7, + 0xf0, 0x1f, 0xe3, 0x41, 0x9f, 0x01, 0x00, 0x00, + 0xba, 0xe4, 0x24, 0x02, 0x00, 0xd7, 0x9c, 0xe3, + 0x41, 0x9f, 0x01, 0x00, 0x00, 0xe4, 0x24, 0x01, + 0x00, 0x9c, 0xe7, 0xe4, 0xd7, 0xef, 0x9c, 0xe8, + 0x29, 0x0c, 0x43, 0x02, 0x01, 0xe4, 0x04, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, + 0xb6, 0x04, 0x2e, 0x00, 0x0a, 0xe7, 0x29, 0x0c, + 0x43, 0x02, 0x01, 0xe6, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x07, 0x00, 0xaa, 0x04, + 0x28, 0x00, 0xac, 0x04, 0x29, 0x00, 0xc6, 0xe7, + 0xba, 0xe8, 0xc2, 0xfe, 0x28, 0x0c, 0x43, 0x02, + 0x01, 0xe8, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0xea, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x03, 0x00, 0xac, 0x04, 0x29, 0x00, + 0xba, 0xe7, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xec, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x04, 0x00, 0xaa, 0x04, 0x28, 0x00, 0xac, 0x04, + 0x29, 0x00, 0xe3, 0xef, 0xe8, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0xee, 0x04, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x03, 0x00, 0x1d, 0x00, 0xac, 0x04, 0x29, + 0x00, 0xaa, 0x04, 0x28, 0x00, 0xd6, 0x04, 0x3e, + 0x00, 0xe3, 0xe4, 0xef, 0xa5, 0xf0, 0x17, 0xe3, + 0x8e, 0xe7, 0xe5, 0xe4, 0x41, 0xae, 0x01, 0x00, + 0x00, 0xe3, 0x24, 0x01, 0x00, 0xf5, 0xf0, 0x06, + 0xe3, 0x8e, 0xe7, 0xf2, 0xee, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x03, 0x00, 0x1c, 0x00, 0xac, 0x04, 0x29, + 0x00, 0xd6, 0x04, 0x3e, 0x00, 0xaa, 0x04, 0x28, + 0x00, 0xe3, 0xba, 0xa7, 0xf0, 0x17, 0xe3, 0x8d, + 0xe7, 0xe4, 0xe5, 0x41, 0xae, 0x01, 0x00, 0x00, + 0xe3, 0x24, 0x01, 0x00, 0xf5, 0xf0, 0x06, 0xe3, + 0x8d, 0xe7, 0xf2, 0xee, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0xf2, 0x04, 0x01, 0x00, 0x01, 0x04, 0x00, + 0x02, 0x00, 0x35, 0x01, 0xde, 0x06, 0x00, 0x01, + 0x00, 0xaa, 0x04, 0x28, 0x00, 0xd0, 0x04, 0x3b, + 0x00, 0xd7, 0xe3, 0xef, 0xa5, 0xf0, 0x15, 0xe4, + 0xe3, 0x41, 0xae, 0x01, 0x00, 0x00, 0xd7, 0x24, + 0x01, 0x00, 0xf5, 0x95, 0xf0, 0x06, 0xd7, 0x8e, + 0xdb, 0xf2, 0xe7, 0xd7, 0xe3, 0xef, 0xa5, 0xf0, + 0x14, 0xe4, 0xe3, 0x41, 0xae, 0x01, 0x00, 0x00, + 0xd7, 0x24, 0x01, 0x00, 0xf5, 0xf0, 0x06, 0xd7, + 0x8e, 0xdb, 0xf2, 0xe8, 0xd7, 0x28, 0x0c, 0x43, + 0x02, 0x01, 0xf4, 0x04, 0x01, 0x00, 0x01, 0x05, + 0x00, 0x02, 0x00, 0x37, 0x01, 0xde, 0x06, 0x00, + 0x01, 0x00, 0xd0, 0x04, 0x3b, 0x00, 0xaa, 0x04, + 0x28, 0x00, 0xd7, 0xba, 0xa7, 0xf0, 0x17, 0xe3, + 0xe4, 0x41, 0xae, 0x01, 0x00, 0x00, 0xd7, 0xbb, + 0x9d, 0x24, 0x01, 0x00, 0xf5, 0x95, 0xf0, 0x06, + 0xd7, 0x8d, 0xdb, 0xf2, 0xe6, 0xd7, 0xba, 0xa7, + 0xf0, 0x16, 0xe3, 0xe4, 0x41, 0xae, 0x01, 0x00, + 0x00, 0xd7, 0xbb, 0x9d, 0x24, 0x01, 0x00, 0xf5, + 0xf0, 0x06, 0xd7, 0x8d, 0xdb, 0xf2, 0xe7, 0xd7, + 0x28, 0x0c, 0x43, 0x02, 0x01, 0xf6, 0x04, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00, + 0xf2, 0x04, 0x4c, 0x00, 0xac, 0x04, 0x29, 0x00, + 0xe3, 0xe4, 0xf5, 0xe8, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0xf8, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x05, 0x00, 0xf4, 0x04, 0x4d, 0x00, + 0xac, 0x04, 0x29, 0x00, 0xe3, 0xe4, 0xf5, 0xe8, + 0x29, 0x0c, 0x43, 0x02, 0x01, 0xfa, 0x04, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x0e, 0x00, + 0xd8, 0x05, 0x7f, 0x00, 0xe3, 0x04, 0xb0, 0x01, + 0x00, 0x00, 0x47, 0x24, 0x00, 0x00, 0x0e, 0xc2, + 0xfe, 0x28, 0x0c, 0x43, 0x02, 0x01, 0xfc, 0x04, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x17, + 0x00, 0xec, 0x03, 0x00, 0x1a, 0xfe, 0x04, 0x52, + 0x00, 0xaa, 0x04, 0x28, 0x00, 0x64, 0x00, 0x00, + 0x41, 0x9d, 0x01, 0x00, 0x00, 0x04, 0xa4, 0x01, + 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0xe4, 0xe5, + 0xf5, 0x0e, 0xb9, 0x28, 0x0c, 0x43, 0x02, 0x01, + 0xfe, 0x04, 0x01, 0x00, 0x01, 0x03, 0x00, 0x02, + 0x00, 0x36, 0x01, 0x9e, 0x06, 0x00, 0x01, 0x00, + 0x92, 0x04, 0x1c, 0x00, 0x94, 0x04, 0x1d, 0x00, + 0xd7, 0x41, 0xb1, 0x01, 0x00, 0x00, 0x24, 0x00, + 0x00, 0xdf, 0xf0, 0x27, 0xe3, 0xef, 0xf0, 0x18, + 0xe3, 0xe3, 0xef, 0xbb, 0x9d, 0x46, 0x95, 0xf0, + 0x0f, 0xe3, 0x41, 0x33, 0x00, 0x00, 0x00, 0x8d, + 0x42, 0x33, 0x00, 0x00, 0x00, 0xf2, 0xe6, 0xe3, + 0x41, 0xb2, 0x01, 0x00, 0x00, 0xd7, 0x24, 0x01, + 0x00, 0x0e, 0xe3, 0xef, 0xe8, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0x80, 0x05, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x04, 0x00, 0x20, 0x00, 0x94, 0x04, 0x1d, + 0x00, 0x92, 0x04, 0x1c, 0x00, 0xaa, 0x04, 0x28, + 0x00, 0xac, 0x04, 0x29, 0x00, 0xe3, 0xba, 0xa7, + 0xf0, 0x1b, 0xe3, 0xe4, 0xef, 0xab, 0xf0, 0x0c, + 0xe4, 0x41, 0xb2, 0x01, 0x00, 0x00, 0xe5, 0x24, + 0x01, 0x00, 0x0e, 0xe3, 0x8d, 0xe7, 0xe4, 0xe3, + 0x46, 0xed, 0xef, 0xea, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0x82, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x12, 0x00, 0x94, 0x04, 0x1d, 0x00, + 0x92, 0x04, 0x1c, 0x00, 0xaa, 0x04, 0x28, 0x00, + 0xac, 0x04, 0x29, 0x00, 0xe3, 0xe4, 0xef, 0xbb, + 0x9d, 0xa5, 0xf0, 0x0a, 0xe3, 0x8e, 0xe7, 0xe4, + 0xe3, 0x46, 0xed, 0xef, 0xea, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0x84, 0x05, 0x01, 0x03, 0x01, 0x05, + 0x00, 0x04, 0x00, 0x3d, 0x04, 0xe6, 0x06, 0x00, + 0x01, 0x00, 0xde, 0x06, 0x00, 0x00, 0x00, 0x86, + 0x06, 0x00, 0x01, 0x00, 0xbe, 0x01, 0x00, 0x02, + 0x00, 0xac, 0x04, 0x29, 0x00, 0x92, 0x04, 0x1c, + 0x00, 0x94, 0x04, 0x1d, 0x00, 0xaa, 0x04, 0x28, + 0x00, 0xe3, 0xcf, 0xbb, 0xd0, 0xcc, 0xe4, 0xef, + 0xa6, 0xf0, 0x33, 0xe4, 0xef, 0xcc, 0xd7, 0x99, + 0x9c, 0xe5, 0x9c, 0xe4, 0xef, 0x9b, 0xd1, 0xe4, + 0xcd, 0x46, 0x41, 0x9f, 0x01, 0x00, 0x00, 0xba, + 0xcb, 0x24, 0x02, 0x00, 0xe6, 0x41, 0x9f, 0x01, + 0x00, 0x00, 0xba, 0xcb, 0x24, 0x02, 0x00, 0xab, + 0xf0, 0x08, 0xcd, 0xe9, 0xe4, 0xcd, 0x46, 0xea, + 0x29, 0x92, 0x01, 0xf2, 0xc9, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0x86, 0x05, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x01, 0x00, 0x05, 0x00, 0x84, 0x05, 0x55, + 0x00, 0xe3, 0xb9, 0x23, 0x01, 0x00, 0x0c, 0x43, + 0x02, 0x01, 0x88, 0x05, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x01, 0x00, 0x05, 0x00, 0x84, 0x05, 0x55, + 0x00, 0xe3, 0xbb, 0x23, 0x01, 0x00, 0x0c, 0x43, + 0x02, 0x01, 0x8a, 0x05, 0x01, 0x02, 0x01, 0x04, + 0x00, 0x05, 0x00, 0x65, 0x03, 0xe6, 0x06, 0x00, + 0x01, 0x00, 0xb2, 0x06, 0x00, 0x00, 0x00, 0xe8, + 0x06, 0x00, 0x01, 0x00, 0xac, 0x04, 0x29, 0x00, + 0xd6, 0x04, 0x3e, 0x00, 0xaa, 0x04, 0x28, 0x00, + 0xb4, 0x04, 0x2d, 0x00, 0x9a, 0x05, 0x60, 0x00, + 0xe3, 0xcf, 0xd7, 0xba, 0xa5, 0xf0, 0x15, 0x91, + 0x00, 0xe4, 0xe5, 0x41, 0xae, 0x01, 0x00, 0x00, + 0xcb, 0x24, 0x01, 0x00, 0xf5, 0xf0, 0x05, 0x91, + 0x00, 0xf2, 0xef, 0xcb, 0xbb, 0x9c, 0xd0, 0xe4, + 0xe5, 0x41, 0xae, 0x01, 0x00, 0x00, 0xcc, 0x24, + 0x01, 0x00, 0xf5, 0xf0, 0x05, 0x92, 0x01, 0xf2, + 0xef, 0xcb, 0xba, 0xa8, 0xf0, 0x2f, 0xcb, 0xe5, + 0xef, 0xa5, 0xf0, 0x29, 0xe6, 0x5d, 0x04, 0x00, + 0xad, 0xf0, 0x09, 0x5d, 0x04, 0x00, 0xca, 0xd7, + 0xf7, 0x0e, 0x29, 0xe5, 0x41, 0x9f, 0x01, 0x00, + 0x00, 0xba, 0xcb, 0x24, 0x02, 0x00, 0xe5, 0x41, + 0x9f, 0x01, 0x00, 0x00, 0xcc, 0x24, 0x01, 0x00, + 0x9c, 0xe9, 0xcb, 0xe7, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0x8c, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x04, 0x00, 0x8a, 0x05, 0x58, 0x00, + 0xe3, 0xbb, 0xf5, 0x29, 0x0c, 0x43, 0x02, 0x01, + 0x8e, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, + 0x00, 0x1f, 0x00, 0xaa, 0x04, 0x28, 0x00, 0xec, + 0x03, 0x00, 0x1a, 0x8a, 0x05, 0x58, 0x00, 0xe3, + 0xef, 0xba, 0xab, 0xf0, 0x15, 0x64, 0x01, 0x00, + 0x41, 0x9d, 0x01, 0x00, 0x00, 0x04, 0xa4, 0x01, + 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0xc2, 0xfd, + 0x28, 0xe5, 0xbb, 0xf5, 0x0e, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0x90, 0x05, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x01, 0x00, 0x04, 0x00, 0x8a, 0x05, 0x58, + 0x00, 0xe3, 0xb9, 0xf5, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0x92, 0x05, 0x00, 0x01, 0x00, 0x06, 0x00, + 0x02, 0x00, 0x51, 0x01, 0xde, 0x06, 0x00, 0x00, + 0x00, 0xac, 0x04, 0x29, 0x00, 0xaa, 0x04, 0x28, + 0x00, 0xe3, 0xcf, 0xe4, 0xef, 0xbb, 0xa7, 0xf0, + 0x49, 0xcb, 0xba, 0xa7, 0xf0, 0x44, 0xcb, 0xe4, + 0xef, 0xab, 0xf0, 0x03, 0x91, 0x00, 0xe4, 0x41, + 0x9f, 0x01, 0x00, 0x00, 0xba, 0xcb, 0xbb, 0x9d, + 0x24, 0x02, 0x00, 0xe4, 0x41, 0x9f, 0x01, 0x00, + 0x00, 0xcb, 0xcb, 0xbb, 0x9c, 0x24, 0x02, 0x00, + 0x9c, 0xe4, 0x41, 0x9f, 0x01, 0x00, 0x00, 0xcb, + 0xbb, 0x9d, 0xcb, 0x24, 0x02, 0x00, 0x9c, 0xe4, + 0x41, 0x9f, 0x01, 0x00, 0x00, 0xcb, 0xbb, 0x9c, + 0x24, 0x01, 0x00, 0x9c, 0xe8, 0xcb, 0xbb, 0x9c, + 0xe7, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x94, 0x05, + 0x00, 0x04, 0x00, 0x05, 0x00, 0x04, 0x00, 0x55, + 0x04, 0xea, 0x06, 0x00, 0x00, 0x00, 0xec, 0x06, + 0x00, 0x01, 0x00, 0xee, 0x06, 0x00, 0x02, 0x00, + 0xf0, 0x06, 0x00, 0x03, 0x00, 0xf4, 0x04, 0x4d, + 0x00, 0xac, 0x04, 0x29, 0x00, 0xf2, 0x04, 0x4c, + 0x00, 0xaa, 0x04, 0x28, 0x00, 0xe3, 0xe4, 0xf5, + 0xcf, 0xe5, 0xcb, 0xf5, 0xd0, 0xe5, 0xe4, 0xf5, + 0xd1, 0xe3, 0xcd, 0xf5, 0xd2, 0xca, 0xa5, 0xf0, + 0x41, 0xcc, 0xe4, 0xa6, 0xf0, 0x3c, 0xe4, 0xce, + 0xa6, 0xf0, 0x37, 0xce, 0xcd, 0xa5, 0xf0, 0x32, + 0xe6, 0x41, 0x9f, 0x01, 0x00, 0x00, 0xba, 0xcb, + 0x24, 0x02, 0x00, 0xe6, 0x41, 0x9f, 0x01, 0x00, + 0x00, 0xce, 0xcd, 0x24, 0x02, 0x00, 0x9c, 0xe6, + 0x41, 0x9f, 0x01, 0x00, 0x00, 0xcc, 0xce, 0x24, + 0x02, 0x00, 0x9c, 0xe6, 0x41, 0x9f, 0x01, 0x00, + 0x00, 0xca, 0x24, 0x02, 0x00, 0x9c, 0xea, 0xcd, + 0xe8, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x96, 0x05, + 0x00, 0x01, 0x00, 0x05, 0x00, 0x03, 0x00, 0x30, + 0x01, 0xe8, 0x06, 0x00, 0x00, 0x00, 0xf2, 0x04, + 0x4c, 0x00, 0xac, 0x04, 0x29, 0x00, 0xaa, 0x04, + 0x28, 0x00, 0xe3, 0xe4, 0xf5, 0xcf, 0xe5, 0x41, + 0x9f, 0x01, 0x00, 0x00, 0xba, 0xe4, 0x24, 0x02, + 0x00, 0xe5, 0x41, 0x9f, 0x01, 0x00, 0x00, 0xe4, + 0xcb, 0x24, 0x02, 0x00, 0x41, 0xb9, 0x01, 0x00, + 0x00, 0x24, 0x00, 0x00, 0x9c, 0xe5, 0x41, 0x9f, + 0x01, 0x00, 0x00, 0xcb, 0x24, 0x01, 0x00, 0x9c, + 0xe9, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x98, 0x05, + 0x00, 0x01, 0x00, 0x05, 0x00, 0x03, 0x00, 0x30, + 0x01, 0xe8, 0x06, 0x00, 0x00, 0x00, 0xf2, 0x04, + 0x4c, 0x00, 0xac, 0x04, 0x29, 0x00, 0xaa, 0x04, + 0x28, 0x00, 0xe3, 0xe4, 0xf5, 0xcf, 0xe5, 0x41, + 0x9f, 0x01, 0x00, 0x00, 0xba, 0xe4, 0x24, 0x02, + 0x00, 0xe5, 0x41, 0x9f, 0x01, 0x00, 0x00, 0xe4, + 0xcb, 0x24, 0x02, 0x00, 0x41, 0xba, 0x01, 0x00, + 0x00, 0x24, 0x00, 0x00, 0x9c, 0xe5, 0x41, 0x9f, + 0x01, 0x00, 0x00, 0xcb, 0x24, 0x01, 0x00, 0x9c, + 0xe9, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x9a, 0x05, + 0x03, 0x01, 0x03, 0x04, 0x00, 0x06, 0x00, 0x5e, + 0x04, 0xb2, 0x06, 0x00, 0x01, 0x00, 0xe8, 0x06, + 0x00, 0x01, 0x00, 0xe6, 0x06, 0x00, 0x01, 0x00, + 0xf6, 0x06, 0x00, 0x00, 0x00, 0xaa, 0x04, 0x28, + 0x00, 0xb4, 0x04, 0x2d, 0x00, 0x9a, 0x05, 0x60, + 0x00, 0x96, 0x04, 0x1e, 0x00, 0xac, 0x04, 0x29, + 0x00, 0xb2, 0x04, 0x2c, 0x00, 0xe3, 0x41, 0x9f, + 0x01, 0x00, 0x00, 0xd7, 0xd8, 0x24, 0x02, 0x00, + 0xcf, 0xe4, 0xe5, 0xae, 0xf0, 0x05, 0xcb, 0xea, + 0xf2, 0x10, 0xd9, 0xba, 0xa5, 0xf0, 0x07, 0xcb, + 0xe6, 0x9c, 0xea, 0xf2, 0x05, 0xe6, 0xcb, 0x9c, + 0xea, 0xe3, 0x41, 0x9f, 0x01, 0x00, 0x00, 0xba, + 0xd7, 0x24, 0x02, 0x00, 0xe3, 0x41, 0x9f, 0x01, + 0x00, 0x00, 0xd8, 0x24, 0x01, 0x00, 0x9c, 0xe7, + 0x5d, 0x04, 0x00, 0xd8, 0xa7, 0xf0, 0x0d, 0x5d, + 0x04, 0x00, 0xd8, 0xd7, 0x9d, 0x9d, 0x5e, 0x04, + 0x00, 0xf2, 0x0c, 0x5d, 0x04, 0x00, 0xd7, 0xa7, + 0xf0, 0x05, 0xd7, 0x5e, 0x04, 0x00, 0xe5, 0x5e, + 0x05, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x9c, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, + 0x07, 0x00, 0x9a, 0x05, 0x60, 0x00, 0xac, 0x04, + 0x29, 0x00, 0xaa, 0x04, 0x28, 0x00, 0xe3, 0xe4, + 0xe5, 0xef, 0xbb, 0xf7, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0x9e, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x02, 0x00, 0x06, 0x00, 0x9a, 0x05, 0x60, 0x00, + 0xac, 0x04, 0x29, 0x00, 0xe3, 0xba, 0xe4, 0xb9, + 0xf7, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xa0, 0x05, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x08, + 0x00, 0x9a, 0x05, 0x60, 0x00, 0xac, 0x04, 0x29, + 0x00, 0xf2, 0x04, 0x4c, 0x00, 0xe3, 0xe4, 0xe5, + 0xe4, 0xf5, 0xbb, 0xf7, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0xa2, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x03, 0x00, 0x08, 0x00, 0x9a, 0x05, 0x60, 0x00, + 0xf4, 0x04, 0x4d, 0x00, 0xac, 0x04, 0x29, 0x00, + 0xe3, 0xe4, 0xe5, 0xf5, 0xe5, 0xb9, 0xf7, 0x29, + 0x0c, 0x43, 0x02, 0x01, 0xa4, 0x05, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0xe2, + 0x04, 0x44, 0x00, 0x96, 0x04, 0x1e, 0x00, 0xe3, + 0xe4, 0xf5, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xa6, + 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x00, + 0x32, 0x00, 0xb4, 0x04, 0x2d, 0x00, 0xa6, 0x05, + 0x66, 0x00, 0xec, 0x03, 0x00, 0x1a, 0xd4, 0x05, + 0x7d, 0x00, 0xbe, 0x05, 0x72, 0x00, 0xe3, 0xe4, + 0xad, 0xf0, 0x17, 0x64, 0x02, 0x00, 0x41, 0x9d, + 0x01, 0x00, 0x00, 0x04, 0xa4, 0x01, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x0e, 0xe6, 0xba, 0xf5, 0x0e, + 0x29, 0x64, 0x02, 0x00, 0x41, 0x9d, 0x01, 0x00, + 0x00, 0x04, 0xbc, 0x01, 0x00, 0x00, 0x24, 0x01, + 0x00, 0x0e, 0x5d, 0x04, 0x00, 0xf4, 0x0e, 0x29, + 0x0c, 0x43, 0x02, 0x01, 0xa8, 0x05, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x05, 0x00, 0xaa, + 0x04, 0x28, 0x00, 0xac, 0x04, 0x29, 0x00, 0xc6, + 0xe7, 0xba, 0xe8, 0x29, 0x0c, 0x43, 0x02, 0x01, + 0xaa, 0x05, 0x02, 0x01, 0x02, 0x04, 0x00, 0x02, + 0x00, 0x39, 0x03, 0xfa, 0x06, 0x00, 0x01, 0x00, + 0xe8, 0x06, 0x00, 0x01, 0x00, 0xde, 0x06, 0x00, + 0x00, 0x00, 0xd0, 0x04, 0x3b, 0x00, 0xd2, 0x04, + 0x3c, 0x00, 0xd8, 0xcf, 0xcb, 0xba, 0xa7, 0xf0, + 0x0e, 0xe3, 0xd7, 0xcb, 0xbb, 0x9d, 0x46, 0xf5, + 0xf0, 0x05, 0x91, 0x00, 0xf2, 0xef, 0xcb, 0xba, + 0xa7, 0xf0, 0x0e, 0xe4, 0xd7, 0xcb, 0xbb, 0x9d, + 0x46, 0xf5, 0xf0, 0x05, 0x91, 0x00, 0xf2, 0xef, + 0xcb, 0xba, 0xa7, 0x11, 0xf0, 0x0d, 0x0e, 0xd7, + 0xcb, 0xbb, 0x9d, 0x46, 0x04, 0xbe, 0x01, 0x00, + 0x00, 0xad, 0x28, 0x0c, 0x43, 0x02, 0x01, 0xac, + 0x05, 0x02, 0x01, 0x02, 0x04, 0x00, 0x01, 0x00, + 0x1f, 0x03, 0xfa, 0x06, 0x00, 0x01, 0x00, 0xe8, + 0x06, 0x00, 0x01, 0x00, 0xde, 0x06, 0x00, 0x00, + 0x00, 0xd0, 0x04, 0x3b, 0x00, 0xd8, 0xcf, 0xcb, + 0xba, 0xa7, 0xf0, 0x0e, 0xe3, 0xd7, 0xcb, 0xbb, + 0x9d, 0x46, 0xf5, 0xf0, 0x05, 0x91, 0x00, 0xf2, + 0xef, 0xd7, 0x41, 0xbf, 0x01, 0x00, 0x00, 0xcb, + 0xd8, 0x25, 0x02, 0x00, 0x0c, 0x43, 0x02, 0x01, + 0xae, 0x05, 0x02, 0x04, 0x02, 0x05, 0x00, 0x07, + 0x04, 0x9f, 0x02, 0x06, 0xfa, 0x06, 0x00, 0x01, + 0x00, 0xde, 0x06, 0x00, 0x01, 0x00, 0x8c, 0x06, + 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x01, 0x00, + 0x82, 0x07, 0x00, 0x02, 0x00, 0x84, 0x07, 0x00, + 0x03, 0x00, 0xf2, 0x03, 0x00, 0x01, 0xd8, 0x05, + 0x7f, 0x00, 0xd0, 0x04, 0x3b, 0x00, 0xac, 0x05, + 0x69, 0x00, 0xf6, 0x03, 0x0e, 0x00, 0xae, 0x05, + 0x6a, 0x00, 0xd8, 0x02, 0x08, 0x00, 0x07, 0x02, + 0x20, 0x07, 0x34, 0x00, 0x00, 0x01, 0x00, 0x12, + 0x00, 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, 0x00, + 0x05, 0x08, 0xf5, 0xff, 0xff, 0xff, 0x0c, 0x00, + 0x01, 0x20, 0x0d, 0x00, 0x0b, 0x07, 0x1a, 0x5e, + 0x5b, 0x64, 0x67, 0x69, 0x6d, 0x73, 0x75, 0x76, + 0x79, 0x5d, 0x2b, 0x24, 0x07, 0x96, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x43, 0x00, 0x00, 0x00, 0x09, + 0x06, 0x00, 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, + 0xff, 0xff, 0x0c, 0x00, 0x06, 0x1d, 0x20, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, 0x16, 0x07, + 0x00, 0x64, 0x00, 0x64, 0x00, 0x67, 0x00, 0x67, + 0x00, 0x69, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x6d, + 0x00, 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x76, + 0x00, 0x79, 0x00, 0x79, 0x00, 0x0b, 0x07, 0x0d, + 0x00, 0x0b, 0xd8, 0xba, 0xa6, 0xf0, 0x03, 0xe3, + 0x28, 0xd7, 0xd8, 0xbb, 0x9d, 0x46, 0xcf, 0xd8, + 0xbb, 0xad, 0xf0, 0x17, 0xcb, 0x04, 0xc3, 0x01, + 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, 0x0e, 0xcb, + 0x04, 0xbe, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x03, + 0xe4, 0x28, 0x04, 0xc4, 0x01, 0x00, 0x00, 0x41, + 0xc5, 0x01, 0x00, 0x00, 0xcb, 0x24, 0x01, 0x00, + 0xba, 0xa8, 0xf0, 0x02, 0x29, 0xcb, 0x04, 0xbe, + 0x01, 0x00, 0x00, 0xad, 0x68, 0xda, 0x00, 0x00, + 0x00, 0xd8, 0x8d, 0xdc, 0xd7, 0xd8, 0xbb, 0x9d, + 0x46, 0xd3, 0x11, 0x04, 0xc6, 0x01, 0x00, 0x00, + 0xad, 0xf1, 0x13, 0x11, 0x04, 0xc7, 0x01, 0x00, + 0x00, 0xad, 0xf1, 0x0a, 0x11, 0x04, 0xc8, 0x01, + 0x00, 0x00, 0xad, 0xf0, 0x07, 0x04, 0x89, 0x01, + 0x00, 0x00, 0x28, 0x11, 0x04, 0xc9, 0x01, 0x00, + 0x00, 0xad, 0xf0, 0x05, 0x26, 0x00, 0x00, 0x28, + 0x11, 0x04, 0xca, 0x01, 0x00, 0x00, 0xad, 0xf0, + 0x07, 0xc4, 0x00, 0xc4, 0x01, 0x34, 0x28, 0xe5, + 0xcb, 0xf5, 0x68, 0x89, 0x00, 0x00, 0x00, 0xe6, + 0xd7, 0xd8, 0xf6, 0xd0, 0xd8, 0xcc, 0xef, 0x9d, + 0xd1, 0xcc, 0x04, 0x03, 0x00, 0x00, 0x00, 0xad, + 0x11, 0xf1, 0x09, 0x0e, 0xcc, 0x04, 0x02, 0x00, + 0x00, 0x00, 0xad, 0xf0, 0x03, 0x0a, 0x28, 0xcc, + 0x04, 0x01, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x03, + 0x07, 0x28, 0xcc, 0x04, 0x08, 0x00, 0x00, 0x00, + 0xad, 0xf0, 0x03, 0xe3, 0x28, 0x5d, 0x04, 0x00, + 0xcc, 0x8c, 0xf5, 0x95, 0xf0, 0x03, 0xba, 0x28, + 0x5d, 0x05, 0x00, 0xd7, 0xcd, 0xf6, 0xd6, 0xf9, + 0x11, 0xf1, 0x04, 0x0e, 0xce, 0xf8, 0xf0, 0x03, + 0xce, 0x28, 0xce, 0xcc, 0x46, 0xfa, 0xf1, 0x05, + 0xce, 0xcc, 0x46, 0x28, 0xcd, 0xbd, 0xa8, 0xf0, + 0x24, 0xd7, 0xcd, 0xbb, 0x9d, 0x46, 0x04, 0xca, + 0x01, 0x00, 0x00, 0xad, 0xf0, 0x17, 0xcc, 0x41, + 0xcb, 0x01, 0x00, 0x00, 0xc4, 0x02, 0xc4, 0x03, + 0x34, 0x24, 0x01, 0x00, 0xf0, 0x07, 0x5d, 0x06, + 0x00, 0x23, 0x00, 0x00, 0x0e, 0x0b, 0x28, 0xe3, + 0x28, 0x0c, 0x43, 0x02, 0x01, 0xb0, 0x05, 0x02, + 0x0b, 0x02, 0x06, 0x00, 0x05, 0x01, 0xa3, 0x02, + 0x0d, 0xfa, 0x06, 0x00, 0x01, 0x00, 0xde, 0x06, + 0x00, 0x01, 0x00, 0xf6, 0x06, 0x00, 0x00, 0x00, + 0x84, 0x07, 0x00, 0x01, 0x00, 0x98, 0x07, 0x00, + 0x02, 0x00, 0x9a, 0x07, 0x00, 0x03, 0x00, 0x86, + 0x06, 0x00, 0x04, 0x00, 0xb6, 0x06, 0x00, 0x05, + 0x00, 0x9c, 0x07, 0x00, 0x06, 0x00, 0x9e, 0x07, + 0x04, 0x00, 0x30, 0xa0, 0x07, 0x00, 0x07, 0x00, + 0xa2, 0x07, 0x00, 0x09, 0x00, 0xa4, 0x07, 0x0d, + 0x00, 0x21, 0xac, 0x05, 0x69, 0x00, 0xae, 0x05, + 0x6a, 0x00, 0xaa, 0x05, 0x68, 0x00, 0xfc, 0x03, + 0x11, 0x00, 0xbc, 0x02, 0x00, 0x00, 0x0c, 0x43, + 0x02, 0x01, 0xa4, 0x07, 0x02, 0x00, 0x02, 0x03, + 0x00, 0x00, 0x00, 0x34, 0x02, 0x92, 0x06, 0x00, + 0x01, 0x00, 0xaa, 0x06, 0x00, 0x01, 0x00, 0xd7, + 0xba, 0x46, 0xd8, 0xba, 0x46, 0xac, 0xf0, 0x1b, + 0xd7, 0xba, 0x46, 0x04, 0x8b, 0x01, 0x00, 0x00, + 0xab, 0xf0, 0x03, 0xbb, 0x28, 0xd8, 0xba, 0x46, + 0x04, 0x8b, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x03, + 0xb9, 0x28, 0xd7, 0xd8, 0xa5, 0xf0, 0x03, 0xb9, + 0x28, 0xd7, 0xd8, 0xa7, 0xf0, 0x04, 0xbb, 0x8c, + 0x28, 0xba, 0x28, 0xe3, 0xd7, 0xd8, 0xf6, 0xcf, + 0xe4, 0xd7, 0xd8, 0xcb, 0xef, 0x9d, 0xf6, 0xd1, + 0x26, 0x00, 0x00, 0xd2, 0xe5, 0xd7, 0xd8, 0xf6, + 0x95, 0xf0, 0x2b, 0x60, 0x07, 0x00, 0xe6, 0x7e, + 0xf2, 0x1e, 0xc8, 0x07, 0x61, 0x07, 0x00, 0x41, + 0xd3, 0x01, 0x00, 0x00, 0xcb, 0x24, 0x01, 0x00, + 0xf0, 0x0e, 0xce, 0x41, 0xb2, 0x01, 0x00, 0x00, + 0x61, 0x07, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x81, + 0x00, 0xf0, 0xe0, 0x0e, 0x83, 0xba, 0xc8, 0x04, + 0xcd, 0xd0, 0xc7, 0x04, 0xc2, 0x0a, 0xa5, 0xf0, + 0x6b, 0xcc, 0xf9, 0xf1, 0x67, 0xcc, 0x06, 0xae, + 0xf0, 0x62, 0x5d, 0x04, 0x00, 0x41, 0xd4, 0x01, + 0x00, 0x00, 0xcc, 0x24, 0x01, 0x00, 0xc8, 0x08, + 0xba, 0xc8, 0x05, 0xc7, 0x05, 0xc7, 0x08, 0xef, + 0xa5, 0xf0, 0x38, 0xc7, 0x08, 0xc7, 0x05, 0x46, + 0xc9, 0x09, 0x96, 0x04, 0x4c, 0x00, 0x00, 0x00, + 0xab, 0xf0, 0x24, 0xc6, 0xc7, 0x09, 0x8c, 0x9c, + 0xc7, 0x09, 0xac, 0xf0, 0x1a, 0xc7, 0x09, 0x41, + 0xd3, 0x01, 0x00, 0x00, 0xcb, 0x24, 0x01, 0x00, + 0xf0, 0x0d, 0xce, 0x41, 0xb2, 0x01, 0x00, 0x00, + 0xc7, 0x09, 0x24, 0x01, 0x00, 0x0e, 0x92, 0x05, + 0xf2, 0xc2, 0x5d, 0x04, 0x00, 0x41, 0x67, 0x00, + 0x00, 0x00, 0xcc, 0x24, 0x01, 0x00, 0xd0, 0x92, + 0x04, 0xf2, 0x90, 0xce, 0xef, 0xbb, 0xa7, 0xf0, + 0x51, 0xc5, 0x00, 0xc8, 0x0a, 0xc5, 0x00, 0x0e, + 0xce, 0x41, 0xd5, 0x01, 0x00, 0x00, 0x61, 0x0a, + 0x00, 0x24, 0x01, 0x00, 0x0e, 0xbb, 0xc9, 0x05, + 0xc8, 0x04, 0xc7, 0x04, 0xce, 0xef, 0xa5, 0xf0, + 0x29, 0xce, 0xc7, 0x04, 0x46, 0xce, 0xc7, 0x04, + 0xbb, 0x9d, 0x46, 0xac, 0xf0, 0x18, 0xce, 0xc7, + 0x05, 0x90, 0xc8, 0x05, 0x1b, 0x11, 0xaf, 0xf1, + 0x04, 0x1b, 0x71, 0x1b, 0x1b, 0xce, 0xc7, 0x04, + 0x46, 0x1b, 0x71, 0x1b, 0x48, 0x92, 0x04, 0xf2, + 0xd2, 0xce, 0xc7, 0x05, 0x42, 0x33, 0x00, 0x00, + 0x00, 0x0b, 0xce, 0x4b, 0x7a, 0x01, 0x00, 0x00, + 0xcb, 0xef, 0x4b, 0xaf, 0x01, 0x00, 0x00, 0xcd, + 0x4b, 0xd6, 0x01, 0x00, 0x00, 0x28, 0x0c, 0x43, + 0x02, 0x01, 0xb2, 0x05, 0x00, 0x0d, 0x00, 0x07, + 0x00, 0x0a, 0x00, 0xa1, 0x03, 0x0d, 0xf4, 0x05, + 0x00, 0x00, 0x00, 0xae, 0x07, 0x00, 0x01, 0x00, + 0xf6, 0x06, 0x00, 0x02, 0x00, 0x86, 0x06, 0x00, + 0x03, 0x00, 0xb6, 0x06, 0x00, 0x04, 0x00, 0xa0, + 0x06, 0x00, 0x05, 0x00, 0xb0, 0x07, 0x00, 0x06, + 0x00, 0xb2, 0x07, 0x00, 0x07, 0x00, 0xb4, 0x07, + 0x00, 0x08, 0x00, 0xb6, 0x07, 0x00, 0x09, 0x00, + 0xb8, 0x07, 0x00, 0x0a, 0x00, 0xba, 0x07, 0x00, + 0x0b, 0x00, 0xbc, 0x07, 0x00, 0x0c, 0x00, 0xb0, + 0x05, 0x6b, 0x00, 0xaa, 0x04, 0x28, 0x00, 0xac, + 0x04, 0x29, 0x00, 0xe2, 0x04, 0x44, 0x00, 0xb4, + 0x04, 0x2d, 0x00, 0xb2, 0x05, 0x6c, 0x00, 0xcc, + 0x02, 0x0b, 0x00, 0xc0, 0x04, 0x33, 0x00, 0xec, + 0x03, 0x00, 0x1a, 0xbe, 0x05, 0x72, 0x00, 0xe3, + 0xe4, 0xe5, 0xf6, 0xd4, 0x40, 0x7a, 0x01, 0x00, + 0x00, 0xd3, 0xef, 0xba, 0xad, 0xf0, 0x02, 0x29, + 0xcb, 0xba, 0x46, 0xd5, 0xef, 0xc8, 0x05, 0xbb, + 0xd2, 0xce, 0xcb, 0xef, 0xa5, 0xf0, 0x2a, 0xcb, + 0xce, 0x46, 0xc8, 0x06, 0xba, 0xc8, 0x04, 0xc7, + 0x04, 0xc7, 0x05, 0xa5, 0xf0, 0x17, 0xc7, 0x06, + 0xc7, 0x04, 0x46, 0xcd, 0xc7, 0x04, 0x46, 0xae, + 0xf0, 0x07, 0xc7, 0x04, 0xc8, 0x05, 0xf2, 0x05, + 0x92, 0x04, 0xf2, 0xe4, 0x92, 0x03, 0xf2, 0xd2, + 0xcc, 0x40, 0xaf, 0x01, 0x00, 0x00, 0xd2, 0xce, + 0xc7, 0x05, 0xa5, 0xf0, 0x0b, 0xe6, 0xcd, 0xce, + 0x46, 0xf5, 0x0e, 0x92, 0x03, 0xf2, 0xf1, 0x5d, + 0x04, 0x00, 0x5d, 0x05, 0x00, 0xad, 0xf0, 0x54, + 0xcb, 0xef, 0xbb, 0xab, 0xf0, 0x4e, 0xcb, 0xba, + 0x46, 0xd1, 0xcc, 0x40, 0xd6, 0x01, 0x00, 0x00, + 0xcd, 0x46, 0xc9, 0x0c, 0xfb, 0xf0, 0x1a, 0xe6, + 0x04, 0xdf, 0x01, 0x00, 0x00, 0xf5, 0x0e, 0xc7, + 0x0c, 0xef, 0xba, 0xab, 0xf0, 0x2e, 0xe6, 0x04, + 0xe0, 0x01, 0x00, 0x00, 0xf5, 0x0e, 0xf2, 0x24, + 0xc7, 0x0c, 0x96, 0x04, 0x4d, 0x00, 0x00, 0x00, + 0xab, 0x11, 0xf1, 0x0e, 0x0e, 0xc7, 0x0c, 0xfa, + 0xf0, 0x12, 0xcd, 0x04, 0x08, 0x00, 0x00, 0x00, + 0xab, 0xf0, 0x09, 0xe6, 0x04, 0xbe, 0x01, 0x00, + 0x00, 0xf5, 0x0e, 0x5d, 0x04, 0x00, 0x5d, 0x05, + 0x00, 0xad, 0x68, 0xdc, 0x00, 0x00, 0x00, 0xcb, + 0xef, 0xbc, 0xa8, 0x68, 0xd3, 0x00, 0x00, 0x00, + 0xba, 0xc8, 0x07, 0xba, 0xd2, 0xce, 0xcb, 0xef, + 0xa5, 0xf0, 0x18, 0x5d, 0x06, 0x00, 0x41, 0xe1, + 0x01, 0x00, 0x00, 0xc7, 0x07, 0xcb, 0xce, 0x46, + 0xef, 0x24, 0x02, 0x00, 0xc8, 0x07, 0x92, 0x03, + 0xf2, 0xe4, 0xbc, 0x93, 0x07, 0x5d, 0x06, 0x00, + 0x41, 0xe1, 0x01, 0x00, 0x00, 0xbb, 0x5d, 0x06, + 0x00, 0x41, 0xe2, 0x01, 0x00, 0x00, 0x5d, 0x07, + 0x00, 0xbb, 0x9c, 0xc7, 0x07, 0x9a, 0x24, 0x01, + 0x00, 0x24, 0x02, 0x00, 0xc8, 0x09, 0x5d, 0x06, + 0x00, 0x41, 0xe3, 0x01, 0x00, 0x00, 0xcb, 0xef, + 0xc7, 0x09, 0x9a, 0x24, 0x01, 0x00, 0xc8, 0x0b, + 0x64, 0x08, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, + 0x04, 0xa4, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, + 0x0e, 0xba, 0xc8, 0x0a, 0xc7, 0x0a, 0xc7, 0x0b, + 0xa5, 0xf0, 0x58, 0xba, 0xc8, 0x08, 0xc7, 0x08, + 0xc7, 0x09, 0xa5, 0xf0, 0x39, 0xc7, 0x08, 0xc7, + 0x0b, 0x99, 0xc7, 0x0a, 0x9c, 0xd6, 0xcb, 0xef, + 0xa8, 0xf1, 0x2b, 0xcb, 0xce, 0x46, 0xd1, 0xc7, + 0x08, 0xc7, 0x09, 0xbb, 0x9d, 0xac, 0xf0, 0x0d, + 0xcd, 0x41, 0xe4, 0x01, 0x00, 0x00, 0xc7, 0x07, + 0x24, 0x01, 0x00, 0xd1, 0x64, 0x08, 0x00, 0x41, + 0x9d, 0x01, 0x00, 0x00, 0xcd, 0x24, 0x01, 0x00, + 0x0e, 0x92, 0x08, 0xf2, 0xc2, 0x64, 0x08, 0x00, + 0x41, 0x9d, 0x01, 0x00, 0x00, 0x04, 0xa4, 0x01, + 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x92, 0x0a, + 0xf2, 0xa3, 0x5d, 0x09, 0x00, 0xf4, 0x0e, 0x29, + 0x0c, 0x43, 0x02, 0x01, 0xb6, 0x05, 0x02, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x00, 0x10, 0x03, 0x9e, + 0x06, 0x00, 0x01, 0x00, 0xca, 0x07, 0x00, 0x01, + 0x00, 0xae, 0x07, 0x00, 0x00, 0x00, 0xc6, 0xcf, + 0xd8, 0x8f, 0xdc, 0xba, 0xa7, 0xf0, 0x06, 0xd7, + 0x93, 0x00, 0xf2, 0xf5, 0xcb, 0x28, 0x0c, 0x43, + 0x02, 0x01, 0xbe, 0x05, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x07, 0x00, 0x1e, 0x00, 0xec, 0x03, 0x00, + 0x1a, 0x9a, 0x04, 0x20, 0x00, 0xd4, 0x04, 0x3d, + 0x00, 0xc0, 0x04, 0x33, 0x00, 0xc2, 0x04, 0x34, + 0x00, 0xae, 0x04, 0x2a, 0x00, 0xb0, 0x04, 0x2b, + 0x00, 0x64, 0x00, 0x00, 0x41, 0x9d, 0x01, 0x00, + 0x00, 0xe4, 0x24, 0x01, 0x00, 0x0e, 0xe5, 0xe4, + 0xf5, 0xe6, 0x9b, 0x5e, 0x04, 0x00, 0xc6, 0x5e, + 0x05, 0x00, 0xba, 0x5e, 0x06, 0x00, 0x29, 0x0c, + 0x43, 0x02, 0x01, 0xc0, 0x05, 0x02, 0x01, 0x02, + 0x05, 0x00, 0x11, 0x00, 0x80, 0x01, 0x03, 0xcc, + 0x07, 0x00, 0x01, 0x00, 0xce, 0x07, 0x00, 0x01, + 0x00, 0xb0, 0x07, 0x00, 0x00, 0x00, 0xaa, 0x04, + 0x28, 0x00, 0xac, 0x04, 0x29, 0x00, 0x92, 0x04, + 0x1c, 0x00, 0x94, 0x04, 0x1d, 0x00, 0xbc, 0x05, + 0x71, 0x00, 0x98, 0x04, 0x1f, 0x00, 0x9a, 0x04, + 0x20, 0x00, 0xa6, 0x04, 0x26, 0x00, 0xb6, 0x05, + 0x6e, 0x00, 0x9c, 0x04, 0x21, 0x00, 0xa0, 0x04, + 0x23, 0x00, 0x86, 0x04, 0x16, 0x00, 0xa4, 0x04, + 0x25, 0x00, 0x9e, 0x04, 0x22, 0x00, 0xbe, 0x05, + 0x72, 0x00, 0xe0, 0x04, 0x43, 0x00, 0xba, 0x05, + 0x70, 0x00, 0xd7, 0x11, 0xf1, 0x03, 0x0e, 0xc6, + 0xeb, 0xef, 0xe8, 0xe5, 0xef, 0xea, 0xd8, 0x5e, + 0x04, 0x00, 0x5d, 0x05, 0x00, 0x5e, 0x06, 0x00, + 0x5d, 0x07, 0x00, 0xf0, 0x22, 0x5d, 0x06, 0x00, + 0x5d, 0x08, 0x00, 0x04, 0xe8, 0x01, 0x00, 0x00, + 0x5d, 0x09, 0x00, 0x5d, 0x06, 0x00, 0xef, 0x9d, + 0xf6, 0x9c, 0x5f, 0x06, 0x00, 0x5d, 0x0a, 0x00, + 0x9c, 0x5e, 0x06, 0x00, 0xf2, 0x36, 0x5d, 0x0b, + 0x00, 0xf0, 0x20, 0x5d, 0x0c, 0x00, 0xc3, 0xe8, + 0x03, 0x9a, 0xcf, 0x5d, 0x06, 0x00, 0xcb, 0x41, + 0xe9, 0x01, 0x00, 0x00, 0xc0, 0x24, 0x01, 0x00, + 0x04, 0xe8, 0x01, 0x00, 0x00, 0x9c, 0x9c, 0x5e, + 0x06, 0x00, 0x5d, 0x06, 0x00, 0xef, 0x5e, 0x09, + 0x00, 0x5d, 0x06, 0x00, 0x5d, 0x0d, 0x00, 0x9c, + 0x5e, 0x06, 0x00, 0x5d, 0x0e, 0x00, 0xf4, 0x0e, + 0x5d, 0x0f, 0x00, 0xf4, 0x0e, 0xba, 0x5e, 0x10, + 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xc2, 0x05, + 0x01, 0x01, 0x01, 0x03, 0x00, 0x04, 0x02, 0x86, + 0x01, 0x02, 0xd4, 0x07, 0x00, 0x01, 0x00, 0x8c, + 0x06, 0x00, 0x00, 0x00, 0xc4, 0x02, 0x01, 0x00, + 0xba, 0x05, 0x70, 0x00, 0xb8, 0x05, 0x6f, 0x00, + 0xc4, 0x05, 0x75, 0x00, 0x07, 0x02, 0x30, 0x07, + 0x02, 0x39, 0xe3, 0x41, 0xeb, 0x01, 0x00, 0x00, + 0xd7, 0x24, 0x01, 0x00, 0xcf, 0xe4, 0x11, 0xba, + 0xad, 0xf0, 0x14, 0xcb, 0x04, 0xec, 0x01, 0x00, + 0x00, 0xab, 0xf0, 0x06, 0xcb, 0xe9, 0xbb, 0xe8, + 0x29, 0xe6, 0xcb, 0xf5, 0x0e, 0x29, 0x11, 0xbb, + 0xad, 0xf0, 0x24, 0xe5, 0xcb, 0x9c, 0xe9, 0xcb, + 0x04, 0xed, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x04, + 0xbc, 0xe8, 0x29, 0xcb, 0x04, 0xee, 0x01, 0x00, + 0x00, 0xab, 0xf0, 0x04, 0xbd, 0xe8, 0x29, 0xe6, + 0xe5, 0xf5, 0x0e, 0xba, 0xe8, 0x29, 0x11, 0xbc, + 0xad, 0xf0, 0x26, 0xe5, 0xcb, 0x9c, 0xe9, 0xcb, + 0x04, 0xef, 0x01, 0x00, 0x00, 0xab, 0x11, 0xf1, + 0x0e, 0x0e, 0xcb, 0xc4, 0x00, 0xa8, 0x11, 0xf0, + 0x06, 0x0e, 0xcb, 0xc4, 0x01, 0xa6, 0x95, 0xf0, + 0x17, 0xe6, 0xe5, 0xf5, 0x0e, 0xba, 0xe8, 0x29, + 0x11, 0xbd, 0xad, 0xf0, 0x0b, 0xe5, 0xcb, 0x9c, + 0xe9, 0xe6, 0xe5, 0xf5, 0x0e, 0xba, 0xe8, 0x29, + 0x0c, 0x43, 0x02, 0x01, 0xc4, 0x05, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x0e, 0x00, 0xb6, 0x01, 0x02, + 0x62, 0x00, 0x01, 0x00, 0xe0, 0x07, 0x00, 0x00, + 0x00, 0xb6, 0x04, 0x2e, 0x00, 0xd4, 0x04, 0x3d, + 0x00, 0xe2, 0x04, 0x44, 0x00, 0xb4, 0x05, 0x6d, + 0x00, 0xb2, 0x04, 0x2c, 0x00, 0xbc, 0x05, 0x71, + 0x00, 0xaa, 0x04, 0x28, 0x00, 0xee, 0x03, 0x01, + 0x1a, 0xbc, 0x04, 0x31, 0x00, 0xee, 0x05, 0x8a, + 0x01, 0x00, 0xb4, 0x04, 0x2d, 0x00, 0xe8, 0x04, + 0x47, 0x00, 0xac, 0x04, 0x29, 0x00, 0xe0, 0x04, + 0x43, 0x00, 0xe3, 0xf0, 0x11, 0xe4, 0xd7, 0xf5, + 0xbb, 0xad, 0xf0, 0x05, 0xe5, 0xd7, 0xf5, 0x0e, + 0x09, 0xe7, 0xf3, 0x80, 0x00, 0xe6, 0xd7, 0x46, + 0xd3, 0xf0, 0x5a, 0xcb, 0x5e, 0x04, 0x00, 0xcb, + 0xd7, 0xf5, 0x11, 0xb9, 0xad, 0xf0, 0x09, 0x5d, + 0x05, 0x00, 0x5d, 0x06, 0x00, 0xf5, 0x29, 0x11, + 0xc2, 0xfe, 0xad, 0xf0, 0x07, 0x5d, 0x05, 0x00, + 0x07, 0xf5, 0x29, 0x11, 0xc2, 0xfd, 0xad, 0xf0, + 0x2b, 0x64, 0x07, 0x00, 0x41, 0x7f, 0x01, 0x00, + 0x00, 0x64, 0x07, 0x00, 0x40, 0x80, 0x01, 0x00, + 0x00, 0x07, 0x24, 0x02, 0x00, 0x0e, 0x64, 0x07, + 0x00, 0x41, 0x81, 0x01, 0x00, 0x00, 0x5d, 0x08, + 0x00, 0x07, 0x24, 0x02, 0x00, 0x0e, 0x5d, 0x09, + 0x00, 0xf4, 0x29, 0x0e, 0x5d, 0x04, 0x00, 0x5e, + 0x0a, 0x00, 0xf2, 0x20, 0xe4, 0xd7, 0xf5, 0xbb, + 0xad, 0xf0, 0x14, 0xd7, 0x04, 0xe8, 0x01, 0x00, + 0x00, 0xa8, 0xf0, 0x0b, 0xe5, 0xd7, 0xf5, 0x0e, + 0xe5, 0x5e, 0x0a, 0x00, 0xf2, 0x06, 0x5d, 0x0b, + 0x00, 0xf4, 0x0e, 0x5d, 0x0c, 0x00, 0xba, 0xa5, + 0xf0, 0x04, 0xba, 0xf2, 0x14, 0x5d, 0x0c, 0x00, + 0x5d, 0x06, 0x00, 0xef, 0xa7, 0xf0, 0x07, 0x5d, + 0x06, 0x00, 0xef, 0xf2, 0x04, 0x5d, 0x0c, 0x00, + 0x5e, 0x0c, 0x00, 0x5d, 0x0d, 0x00, 0xf4, 0x29, + 0x0c, 0x43, 0x02, 0x01, 0xc6, 0x05, 0x02, 0x01, + 0x02, 0x05, 0x00, 0x02, 0x01, 0x70, 0x03, 0x92, + 0x06, 0x00, 0x01, 0x00, 0xe2, 0x07, 0x00, 0x01, + 0x00, 0xf6, 0x06, 0x00, 0x00, 0x00, 0xf4, 0x03, + 0x0d, 0x00, 0xcc, 0x02, 0x0b, 0x00, 0x07, 0x02, + 0x30, 0xe3, 0xd7, 0xf5, 0x95, 0xf0, 0x0a, 0xd7, + 0x41, 0x3b, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, + 0xd7, 0xba, 0xab, 0xf0, 0x15, 0xbb, 0xd7, 0x9a, + 0xba, 0xa5, 0xf0, 0x09, 0x04, 0xf2, 0x01, 0x00, + 0x00, 0xcf, 0xf2, 0x4c, 0xc4, 0x00, 0xcf, 0xf2, + 0x47, 0xd8, 0xc2, 0x10, 0xab, 0xf0, 0x37, 0xd7, + 0xe4, 0x41, 0xe2, 0x01, 0x00, 0x00, 0xd7, 0x24, + 0x01, 0x00, 0xad, 0xf0, 0x29, 0xd7, 0xba, 0xa5, + 0xf0, 0x0c, 0xd7, 0x8b, 0xdb, 0x04, 0xf3, 0x01, + 0x00, 0x00, 0xcf, 0xf2, 0x03, 0xc6, 0xcf, 0xcb, + 0x04, 0xf4, 0x01, 0x00, 0x00, 0xd7, 0x41, 0x3b, + 0x00, 0x00, 0x00, 0xc2, 0x10, 0x24, 0x01, 0x00, + 0x9c, 0x9c, 0xcf, 0xf2, 0x0b, 0xd7, 0x41, 0x3b, + 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xcf, 0xcb, + 0x28, 0x0c, 0x43, 0x02, 0x01, 0xc8, 0x05, 0x02, + 0x01, 0x02, 0x05, 0x00, 0x00, 0x00, 0x40, 0x03, + 0x92, 0x06, 0x00, 0x01, 0x00, 0xe2, 0x07, 0x00, + 0x01, 0x00, 0xf6, 0x06, 0x00, 0x00, 0x00, 0xd8, + 0xc2, 0x10, 0xab, 0xf0, 0x29, 0xd7, 0xba, 0xa5, + 0xf0, 0x0c, 0xd7, 0x8b, 0xdb, 0x04, 0xf3, 0x01, + 0x00, 0x00, 0xcf, 0xf2, 0x03, 0xc6, 0xcf, 0xcb, + 0x04, 0xf4, 0x01, 0x00, 0x00, 0xd7, 0x41, 0x3b, + 0x00, 0x00, 0x00, 0xc2, 0x10, 0x24, 0x01, 0x00, + 0x9c, 0x9c, 0xcf, 0xf2, 0x0b, 0xd7, 0x41, 0x3b, + 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xcf, 0xcb, + 0x04, 0xa0, 0x01, 0x00, 0x00, 0x9c, 0x28, 0x0c, + 0x43, 0x02, 0x01, 0x00, 0x04, 0x18, 0x04, 0x06, + 0x19, 0x12, 0x0e, 0xea, 0x01, 0x1c, 0xea, 0x07, + 0x00, 0x01, 0x00, 0x8a, 0x04, 0x00, 0x01, 0x40, + 0x0a, 0xec, 0x07, 0x00, 0x01, 0x40, 0x07, 0xee, + 0x07, 0x00, 0x01, 0x40, 0x0d, 0xf0, 0x07, 0x00, + 0x00, 0x00, 0x8c, 0x01, 0x00, 0x01, 0x00, 0xf2, + 0x07, 0x00, 0x02, 0x40, 0x15, 0xf4, 0x07, 0x00, + 0x03, 0x40, 0x09, 0xf6, 0x07, 0x00, 0x04, 0x40, + 0x0c, 0xf8, 0x07, 0x00, 0x05, 0x40, 0x02, 0xfa, + 0x07, 0x00, 0x06, 0x40, 0x04, 0x72, 0x00, 0x07, + 0x40, 0x05, 0xfc, 0x07, 0x00, 0x08, 0x40, 0x00, + 0xfe, 0x07, 0x00, 0x09, 0x40, 0x0f, 0x80, 0x08, + 0x00, 0x0a, 0x40, 0x0e, 0x82, 0x08, 0x00, 0x0b, + 0x40, 0x03, 0x84, 0x08, 0x00, 0x0c, 0x40, 0x01, + 0x86, 0x08, 0x00, 0x0d, 0x40, 0x0b, 0x88, 0x08, + 0x00, 0x0e, 0x40, 0x06, 0x8a, 0x08, 0x00, 0x0f, + 0x40, 0x08, 0x8c, 0x08, 0x00, 0x10, 0x40, 0x10, + 0x8e, 0x08, 0x00, 0x11, 0x40, 0x13, 0x90, 0x08, + 0x00, 0x12, 0x40, 0x14, 0x92, 0x08, 0x00, 0x13, + 0x40, 0x11, 0x94, 0x08, 0x00, 0x14, 0x40, 0x12, + 0x96, 0x08, 0x00, 0x15, 0x40, 0x16, 0x98, 0x08, + 0x00, 0x16, 0x40, 0x17, 0x9a, 0x08, 0x00, 0x17, + 0x40, 0x18, 0xf8, 0x03, 0x0f, 0x00, 0xce, 0x02, + 0x0c, 0x00, 0xbc, 0x02, 0x00, 0x00, 0xc6, 0x05, + 0x76, 0x00, 0x8e, 0x04, 0x1a, 0x00, 0xc8, 0x05, + 0x77, 0x00, 0xc4, 0x02, 0x01, 0x00, 0xd0, 0x02, + 0x07, 0x00, 0xd8, 0x02, 0x08, 0x00, 0xc6, 0x02, + 0x03, 0x00, 0xc2, 0x02, 0x02, 0x00, 0xf8, 0x02, + 0x04, 0x00, 0xbe, 0x02, 0x06, 0x00, 0xe2, 0x02, + 0x05, 0x00, 0xfe, 0x03, 0x12, 0x00, 0x82, 0x04, + 0x14, 0x00, 0xcc, 0x02, 0x0b, 0x00, 0xc0, 0x04, + 0x33, 0x00, 0x0c, 0x43, 0x02, 0x01, 0x8c, 0x01, + 0x02, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x0e, + 0x02, 0x9c, 0x08, 0x00, 0x01, 0x00, 0x9e, 0x08, + 0x00, 0x01, 0x00, 0xf8, 0x03, 0x00, 0x02, 0xd7, + 0xfa, 0xf0, 0x03, 0xd8, 0x28, 0xd7, 0xf9, 0xf0, + 0x03, 0xe3, 0x28, 0xd7, 0x28, 0x0c, 0x43, 0x02, + 0x01, 0x82, 0x08, 0x01, 0x00, 0x01, 0x04, 0x00, + 0x01, 0x00, 0x54, 0x01, 0xf6, 0x06, 0x00, 0x01, + 0x00, 0xce, 0x02, 0x01, 0x02, 0xd7, 0x41, 0x8e, + 0x01, 0x00, 0x00, 0x04, 0xc6, 0x01, 0x00, 0x00, + 0x24, 0x01, 0x00, 0xf0, 0x0b, 0xe3, 0x41, 0x10, + 0x02, 0x00, 0x00, 0xd7, 0x25, 0x01, 0x00, 0xe3, + 0x41, 0x10, 0x02, 0x00, 0x00, 0xd7, 0x24, 0x01, + 0x00, 0x41, 0xbf, 0x01, 0x00, 0x00, 0xbb, 0xb9, + 0x24, 0x02, 0x00, 0x41, 0x11, 0x02, 0x00, 0x00, + 0x04, 0x12, 0x02, 0x00, 0x00, 0x04, 0xc7, 0x01, + 0x00, 0x00, 0x24, 0x02, 0x00, 0xdb, 0x04, 0xc6, + 0x01, 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, + 0xd7, 0x04, 0xc6, 0x01, 0x00, 0x00, 0x25, 0x02, + 0x00, 0x0c, 0x43, 0x02, 0x01, 0x84, 0x08, 0x01, + 0x00, 0x01, 0x04, 0x00, 0x01, 0x00, 0x0d, 0x01, + 0xf6, 0x06, 0x00, 0x01, 0x00, 0xfc, 0x07, 0x08, + 0x00, 0xe3, 0x41, 0xb2, 0x01, 0x00, 0x00, 0xc6, + 0xd7, 0x9c, 0x24, 0x01, 0x00, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0x86, 0x08, 0x01, 0x00, 0x01, 0x04, + 0x00, 0x01, 0x00, 0x0c, 0x01, 0xf6, 0x06, 0x00, + 0x01, 0x00, 0xfc, 0x07, 0x08, 0x00, 0xe3, 0xe3, + 0xef, 0xbb, 0x9d, 0x72, 0x13, 0x46, 0xd7, 0x9c, + 0x48, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x88, 0x08, + 0x01, 0x00, 0x01, 0x04, 0x00, 0x01, 0x00, 0x1f, + 0x01, 0xa6, 0x08, 0x00, 0x01, 0x00, 0xbc, 0x02, + 0x02, 0x02, 0xe3, 0x40, 0x3f, 0x00, 0x00, 0x00, + 0x40, 0x3b, 0x00, 0x00, 0x00, 0x41, 0x14, 0x02, + 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0x41, 0xbf, + 0x01, 0x00, 0x00, 0xc2, 0x08, 0xb9, 0x25, 0x02, + 0x00, 0x0c, 0x43, 0x02, 0x01, 0x8a, 0x08, 0x02, + 0x13, 0x02, 0x09, 0x00, 0x1a, 0x02, 0xdc, 0x0b, + 0x15, 0x92, 0x06, 0x00, 0x01, 0x00, 0xa8, 0x04, + 0x00, 0x01, 0x00, 0xc0, 0x06, 0x00, 0x00, 0x00, + 0xaa, 0x08, 0x00, 0x01, 0x00, 0x86, 0x06, 0x00, + 0x02, 0x00, 0xac, 0x08, 0x00, 0x03, 0x00, 0x62, + 0x00, 0x04, 0x00, 0xae, 0x08, 0x00, 0x05, 0x00, + 0xb0, 0x08, 0x00, 0x06, 0x00, 0xb2, 0x08, 0x00, + 0x07, 0x00, 0xb4, 0x08, 0x00, 0x08, 0x00, 0xb6, + 0x08, 0x00, 0x09, 0x00, 0xb8, 0x08, 0x00, 0x0a, + 0x00, 0xba, 0x08, 0x00, 0x0b, 0x00, 0xbc, 0x08, + 0x00, 0x0c, 0x00, 0xbe, 0x08, 0x00, 0x0d, 0x00, + 0xc0, 0x08, 0x00, 0x0e, 0x00, 0xa0, 0x06, 0x00, + 0x0f, 0x00, 0xb2, 0x06, 0x00, 0x10, 0x00, 0xc2, + 0x08, 0x00, 0x11, 0x00, 0xc4, 0x08, 0x00, 0x12, + 0x00, 0x84, 0x08, 0x0c, 0x00, 0xc6, 0x05, 0x03, + 0x02, 0x8e, 0x04, 0x04, 0x02, 0xc8, 0x05, 0x05, + 0x02, 0xf8, 0x07, 0x05, 0x00, 0x82, 0x08, 0x0b, + 0x00, 0xc4, 0x02, 0x06, 0x02, 0xfa, 0x07, 0x06, + 0x00, 0x72, 0x07, 0x00, 0xfc, 0x07, 0x08, 0x00, + 0x88, 0x08, 0x0e, 0x00, 0xd0, 0x02, 0x07, 0x02, + 0xce, 0x02, 0x01, 0x02, 0xd8, 0x02, 0x08, 0x02, + 0xc6, 0x02, 0x09, 0x02, 0xc2, 0x02, 0x0a, 0x02, + 0xf8, 0x02, 0x0b, 0x02, 0xbe, 0x02, 0x0c, 0x02, + 0xe2, 0x02, 0x0d, 0x02, 0xec, 0x07, 0x02, 0x01, + 0x8a, 0x08, 0x0f, 0x00, 0xf4, 0x07, 0x03, 0x00, + 0x8a, 0x04, 0x01, 0x01, 0xbc, 0x02, 0x02, 0x02, + 0x86, 0x08, 0x0d, 0x00, 0xf6, 0x07, 0x04, 0x00, + 0x07, 0x32, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, + 0x2d, 0x5a, 0x5f, 0x24, 0x5d, 0x5b, 0x30, 0x2d, + 0x39, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5f, + 0x24, 0x5d, 0x2a, 0x07, 0xaa, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x09, 0x06, + 0x00, 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, 0xff, + 0xff, 0x0c, 0x00, 0x06, 0x16, 0x04, 0x00, 0x24, + 0x00, 0x24, 0x00, 0x41, 0x00, 0x5a, 0x00, 0x5f, + 0x00, 0x5f, 0x00, 0x61, 0x00, 0x7a, 0x00, 0x1d, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, + 0x16, 0x05, 0x00, 0x24, 0x00, 0x24, 0x00, 0x30, + 0x00, 0x39, 0x00, 0x41, 0x00, 0x5a, 0x00, 0x5f, + 0x00, 0x5f, 0x00, 0x61, 0x00, 0x7a, 0x00, 0x0b, + 0x0d, 0x00, 0x0b, 0xd7, 0x96, 0xc9, 0x06, 0x11, + 0x04, 0x49, 0x00, 0x00, 0x00, 0xad, 0xf1, 0x0a, + 0x11, 0x04, 0x4b, 0x00, 0x00, 0x00, 0xad, 0xf0, + 0x06, 0xe3, 0xd7, 0xf5, 0x0e, 0x29, 0x11, 0x04, + 0x4a, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x11, 0xe3, + 0xe4, 0xd7, 0xe5, 0xf0, 0x05, 0xc2, 0x10, 0xf2, + 0x03, 0xc2, 0x0a, 0xf6, 0xf5, 0x0e, 0x29, 0x11, + 0x04, 0x96, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x11, + 0xe3, 0xe6, 0xd7, 0xe5, 0xf0, 0x05, 0xc2, 0x10, + 0xf2, 0x03, 0xc2, 0x0a, 0xf6, 0xf5, 0x0e, 0x29, + 0x11, 0x04, 0x4c, 0x00, 0x00, 0x00, 0xad, 0xf0, + 0x26, 0xd7, 0xef, 0x5d, 0x04, 0x00, 0xa7, 0xf0, + 0x15, 0xd7, 0x41, 0x9f, 0x01, 0x00, 0x00, 0xba, + 0x5d, 0x04, 0x00, 0x24, 0x02, 0x00, 0x04, 0x23, + 0x02, 0x00, 0x00, 0x9c, 0xdb, 0xe3, 0x5d, 0x05, + 0x00, 0xd7, 0xf5, 0xf5, 0x0e, 0x29, 0x11, 0x04, + 0x4e, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x0a, 0xe3, + 0x5d, 0x06, 0x00, 0xd7, 0xf5, 0xf5, 0x0e, 0x29, + 0x11, 0x04, 0x4d, 0x00, 0x00, 0x00, 0xad, 0xf1, + 0x0d, 0x11, 0x04, 0x1b, 0x00, 0x00, 0x00, 0xad, + 0x68, 0x35, 0x05, 0x00, 0x00, 0xd7, 0xf9, 0xf0, + 0x06, 0xe3, 0xd7, 0xf5, 0x0e, 0x29, 0x5d, 0x07, + 0x00, 0x41, 0xc5, 0x01, 0x00, 0x00, 0xd7, 0x24, + 0x01, 0x00, 0xd3, 0xba, 0xa8, 0xf0, 0x18, 0xe3, + 0x04, 0x24, 0x02, 0x00, 0x00, 0x41, 0x64, 0x00, + 0x00, 0x00, 0xcb, 0x04, 0xc9, 0x01, 0x00, 0x00, + 0x24, 0x02, 0x00, 0xf5, 0x0e, 0x29, 0x5d, 0x08, + 0x00, 0x41, 0xc5, 0x01, 0x00, 0x00, 0xd7, 0x24, + 0x01, 0x00, 0xd3, 0xba, 0xa8, 0xf0, 0x2c, 0xe3, + 0x04, 0x24, 0x02, 0x00, 0x00, 0x41, 0x64, 0x00, + 0x00, 0x00, 0x5d, 0x07, 0x00, 0xef, 0x04, 0xc9, + 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, 0x0e, + 0x5d, 0x07, 0x00, 0x41, 0xb2, 0x01, 0x00, 0x00, + 0x5d, 0x08, 0x00, 0xcb, 0x46, 0x24, 0x01, 0x00, + 0x0e, 0x29, 0x5d, 0x09, 0x00, 0xef, 0xc8, 0x0c, + 0x5d, 0x0a, 0x00, 0xd7, 0xf5, 0xc8, 0x0d, 0x5d, + 0x08, 0x00, 0x41, 0xb2, 0x01, 0x00, 0x00, 0xd7, + 0x24, 0x01, 0x00, 0x0e, 0xd7, 0x5d, 0x0b, 0x00, + 0xa9, 0xf0, 0x28, 0xe3, 0x04, 0x25, 0x02, 0x00, + 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0x5d, 0x0c, + 0x00, 0x41, 0x10, 0x02, 0x00, 0x00, 0xd7, 0x41, + 0x26, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, + 0x01, 0x00, 0x24, 0x01, 0x00, 0xf5, 0x0e, 0xf3, + 0xad, 0x01, 0xd7, 0x5d, 0x0d, 0x00, 0xa9, 0xf0, + 0x10, 0xe3, 0xd7, 0x41, 0x3b, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0xf5, 0x0e, 0xf3, 0x97, 0x01, + 0xd7, 0x5d, 0x0e, 0x00, 0xa9, 0x11, 0xf1, 0x10, + 0x0e, 0xd7, 0x5d, 0x0f, 0x00, 0xa9, 0x11, 0xf1, + 0x07, 0x0e, 0xd7, 0x5d, 0x10, 0x00, 0xa9, 0xf0, + 0x21, 0xe3, 0x04, 0xed, 0x01, 0x00, 0x00, 0x41, + 0x64, 0x00, 0x00, 0x00, 0xc7, 0x0d, 0x04, 0x27, + 0x02, 0x00, 0x00, 0xd7, 0x04, 0xc9, 0x01, 0x00, + 0x00, 0x24, 0x04, 0x00, 0xf5, 0x0e, 0xf3, 0x5e, + 0x01, 0xd7, 0x5d, 0x06, 0x00, 0xa9, 0xf0, 0x2c, + 0xe3, 0x04, 0xed, 0x01, 0x00, 0x00, 0x41, 0x64, + 0x00, 0x00, 0x00, 0xc7, 0x0d, 0x04, 0x27, 0x02, + 0x00, 0x00, 0x5d, 0x05, 0x00, 0xd7, 0xf5, 0x04, + 0xc9, 0x01, 0x00, 0x00, 0x24, 0x04, 0x00, 0xf5, + 0x0e, 0xd7, 0xef, 0xc8, 0x0f, 0xbb, 0xc8, 0x08, + 0xf3, 0x2c, 0x01, 0x5d, 0x11, 0x00, 0x41, 0x28, + 0x02, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0xf0, + 0x0f, 0xe3, 0x04, 0xed, 0x01, 0x00, 0x00, 0xf5, + 0x0e, 0xbb, 0xc8, 0x07, 0xf3, 0x10, 0x01, 0xc7, + 0x0d, 0x41, 0x8e, 0x01, 0x00, 0x00, 0x04, 0x9f, + 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0xf0, 0x2d, + 0xd7, 0x5d, 0x12, 0x00, 0x40, 0x48, 0x00, 0x00, + 0x00, 0xa9, 0xf0, 0x21, 0xe3, 0xc6, 0x41, 0x64, + 0x00, 0x00, 0x00, 0xc7, 0x0d, 0x04, 0xdf, 0x01, + 0x00, 0x00, 0xd7, 0xef, 0x04, 0x29, 0x02, 0x00, + 0x00, 0x24, 0x04, 0x00, 0xf5, 0x0e, 0xbb, 0xc8, + 0x07, 0xf3, 0xd3, 0x00, 0xc7, 0x06, 0x04, 0x1b, + 0x00, 0x00, 0x00, 0xad, 0xf0, 0x32, 0xd7, 0x40, + 0x3a, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0xe3, 0x04, + 0x2a, 0x02, 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, + 0x00, 0xd7, 0x40, 0x3a, 0x00, 0x00, 0x00, 0x04, + 0xc9, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, + 0x0e, 0xf3, 0xa3, 0x00, 0xe3, 0x04, 0x2b, 0x02, + 0x00, 0x00, 0xf5, 0x0e, 0xf3, 0x98, 0x00, 0xd7, + 0x40, 0x40, 0x00, 0x00, 0x00, 0x11, 0xf0, 0x0d, + 0x0e, 0xd7, 0x40, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x3a, 0x00, 0x00, 0x00, 0x11, 0xf1, 0x07, 0x0e, + 0x04, 0x9e, 0x00, 0x00, 0x00, 0xc8, 0x0e, 0xc7, + 0x0d, 0x04, 0x9e, 0x00, 0x00, 0x00, 0xae, 0xf0, + 0x1d, 0xe3, 0xc6, 0x41, 0x64, 0x00, 0x00, 0x00, + 0xc7, 0x0e, 0x04, 0x2c, 0x02, 0x00, 0x00, 0xc7, + 0x0d, 0x04, 0x2d, 0x02, 0x00, 0x00, 0x24, 0x04, + 0x00, 0xf5, 0x0e, 0xf2, 0x4a, 0xd7, 0x40, 0x48, + 0x00, 0x00, 0x00, 0xf9, 0xf0, 0x1a, 0xe3, 0x04, + 0xed, 0x01, 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, + 0x00, 0xc7, 0x0e, 0x04, 0x2e, 0x02, 0x00, 0x00, + 0x24, 0x02, 0x00, 0xf5, 0x0e, 0xf2, 0x28, 0xc7, + 0x0e, 0x04, 0x9e, 0x00, 0x00, 0x00, 0xae, 0xf0, + 0x16, 0xe3, 0xc6, 0x41, 0x64, 0x00, 0x00, 0x00, + 0xc7, 0x0e, 0x04, 0x2f, 0x02, 0x00, 0x00, 0x24, + 0x02, 0x00, 0xf5, 0x0e, 0xf2, 0x09, 0xe3, 0x04, + 0x30, 0x02, 0x00, 0x00, 0xf5, 0x0e, 0x04, 0x31, + 0x02, 0x00, 0x00, 0xc8, 0x0a, 0x07, 0xc8, 0x04, + 0xba, 0xcf, 0xba, 0xd0, 0xba, 0xd2, 0xc7, 0x07, + 0x68, 0xcb, 0x00, 0x00, 0x00, 0x04, 0xc9, 0x01, + 0x00, 0x00, 0xc8, 0x0a, 0xd7, 0xef, 0xc8, 0x0f, + 0xd8, 0x5d, 0x13, 0x00, 0xa7, 0xf0, 0x12, 0xc7, + 0x0f, 0xf0, 0x0e, 0xe3, 0x04, 0x23, 0x02, 0x00, + 0x00, 0xf5, 0x0e, 0xe3, 0xc7, 0x0a, 0xf5, 0x29, + 0xba, 0xd1, 0xcd, 0xc7, 0x0f, 0xa5, 0x68, 0x89, + 0x00, 0x00, 0x00, 0x92, 0x03, 0xcd, 0xd7, 0xaa, + 0xf0, 0x0e, 0x5d, 0x14, 0x00, 0xd7, 0xcd, 0x46, + 0xd8, 0xbb, 0x9c, 0xf6, 0x0e, 0xf2, 0x43, 0xcd, + 0xc8, 0x10, 0xcd, 0xbb, 0x9c, 0xc7, 0x0f, 0xa5, + 0xf0, 0x0d, 0xcd, 0xbb, 0x9c, 0xd7, 0xaa, 0x95, + 0xf0, 0x05, 0x92, 0x02, 0xf2, 0xed, 0xcd, 0xc7, + 0x10, 0xa7, 0xf0, 0x1e, 0xe3, 0x04, 0x32, 0x02, + 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0xcd, + 0xc7, 0x10, 0x9d, 0xbb, 0x9c, 0x04, 0x33, 0x02, + 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, 0x0e, 0xf2, + 0x09, 0xe3, 0x04, 0x34, 0x02, 0x00, 0x00, 0xf5, + 0x0e, 0xce, 0x5d, 0x15, 0x00, 0xa8, 0xf0, 0x24, + 0xc7, 0x0f, 0xce, 0x9d, 0xbf, 0xa7, 0xf0, 0x1c, + 0xe3, 0x04, 0x35, 0x02, 0x00, 0x00, 0x41, 0x64, + 0x00, 0x00, 0x00, 0xc7, 0x0f, 0xce, 0x9d, 0x04, + 0x36, 0x02, 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, + 0x0e, 0xf2, 0x06, 0x92, 0x02, 0xf3, 0x74, 0xff, + 0xbb, 0xc8, 0x08, 0xcd, 0xc7, 0x0f, 0xae, 0xf0, + 0x0c, 0xc7, 0x0f, 0xc3, 0xe8, 0x03, 0xa7, 0xf0, + 0x04, 0xbb, 0xc8, 0x09, 0xc7, 0x09, 0x95, 0xf0, + 0x24, 0x5d, 0x16, 0x00, 0xf0, 0x0f, 0x5d, 0x17, + 0x00, 0x41, 0xd4, 0x01, 0x00, 0x00, 0xd7, 0x24, + 0x01, 0x00, 0xf2, 0x0d, 0x5d, 0x17, 0x00, 0x41, + 0x31, 0x00, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, + 0xc9, 0x04, 0xef, 0xcf, 0xc7, 0x08, 0xf0, 0x1e, + 0xcc, 0xcb, 0xa5, 0xf0, 0x19, 0xc7, 0x04, 0xcc, + 0x46, 0x8c, 0xd5, 0xcd, 0xba, 0xa0, 0xae, 0x11, + 0xf1, 0x06, 0x0e, 0xcd, 0xc7, 0x0f, 0xa8, 0xf1, + 0x05, 0x92, 0x01, 0xf2, 0xe4, 0xcc, 0xcb, 0xa5, + 0x68, 0x5a, 0x01, 0x00, 0x00, 0xc7, 0x0a, 0x95, + 0xf0, 0x12, 0x5d, 0x18, 0x00, 0x04, 0x2f, 0x02, + 0x00, 0x00, 0xf5, 0x0e, 0x04, 0x31, 0x02, 0x00, + 0x00, 0xc8, 0x0a, 0xd8, 0x5d, 0x13, 0x00, 0xa7, + 0xf0, 0x13, 0xcc, 0xcb, 0xa5, 0xf0, 0x0e, 0xe3, + 0x04, 0x23, 0x02, 0x00, 0x00, 0xf5, 0x0e, 0xe3, + 0xc7, 0x0a, 0xf5, 0x29, 0xcc, 0xd1, 0xcd, 0xcb, + 0xa5, 0x68, 0x21, 0x01, 0x00, 0x00, 0xc7, 0x04, + 0xcd, 0x46, 0xc8, 0x05, 0x5d, 0x17, 0x00, 0x41, + 0x6e, 0x00, 0x00, 0x00, 0xd7, 0xc7, 0x05, 0x24, + 0x02, 0x00, 0xc9, 0x11, 0x95, 0x69, 0x00, 0x01, + 0x00, 0x00, 0xc7, 0x11, 0x40, 0x43, 0x00, 0x00, + 0x00, 0x95, 0xf0, 0x1e, 0xe3, 0x04, 0xed, 0x01, + 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0x5d, + 0x06, 0x00, 0xc7, 0x05, 0xf5, 0x04, 0xc9, 0x01, + 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, 0x0e, 0xf2, + 0x2e, 0xc7, 0x05, 0x8c, 0xc7, 0x05, 0xba, 0xa0, + 0xad, 0x11, 0xf1, 0x11, 0x0e, 0xc7, 0x05, 0x41, + 0xcb, 0x01, 0x00, 0x00, 0xc4, 0x00, 0xc4, 0x01, + 0x34, 0x24, 0x01, 0x00, 0xf0, 0x08, 0xe3, 0xc7, + 0x05, 0xf5, 0x0e, 0xf2, 0x0a, 0xe3, 0x5d, 0x05, + 0x00, 0xc7, 0x05, 0xf5, 0xf5, 0x0e, 0xe3, 0x04, + 0x37, 0x02, 0x00, 0x00, 0xf5, 0x0e, 0x04, 0x44, + 0x00, 0x00, 0x00, 0xc7, 0x11, 0xaa, 0xf0, 0x12, + 0x5d, 0x14, 0x00, 0xc7, 0x11, 0x40, 0x44, 0x00, + 0x00, 0x00, 0xd8, 0xbb, 0x9c, 0xf6, 0x0e, 0xf2, + 0x5c, 0x26, 0x00, 0x00, 0xc8, 0x12, 0xc7, 0x11, + 0x40, 0x45, 0x00, 0x00, 0x00, 0xf0, 0x11, 0xc7, + 0x12, 0x41, 0xb2, 0x01, 0x00, 0x00, 0x04, 0x38, + 0x02, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0xc7, + 0x11, 0x40, 0x46, 0x00, 0x00, 0x00, 0xf0, 0x11, + 0xc7, 0x12, 0x41, 0xb2, 0x01, 0x00, 0x00, 0x04, + 0x39, 0x02, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, + 0xe3, 0x04, 0xed, 0x01, 0x00, 0x00, 0x41, 0x64, + 0x00, 0x00, 0x00, 0xc7, 0x12, 0x41, 0x63, 0x00, + 0x00, 0x00, 0x04, 0xca, 0x01, 0x00, 0x00, 0x24, + 0x01, 0x00, 0x04, 0xc9, 0x01, 0x00, 0x00, 0x24, + 0x02, 0x00, 0xf5, 0x0e, 0x92, 0x03, 0xce, 0x5d, + 0x19, 0x00, 0xa7, 0xf0, 0x22, 0xcb, 0xce, 0x9d, + 0xbf, 0xa7, 0xf0, 0x1b, 0xe3, 0x04, 0x35, 0x02, + 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0xcb, + 0xce, 0x9d, 0x04, 0x3a, 0x02, 0x00, 0x00, 0x24, + 0x02, 0x00, 0xf5, 0x0e, 0xf2, 0x06, 0x92, 0x02, + 0xf3, 0xdd, 0xfe, 0xc7, 0x0a, 0xf0, 0x06, 0xe3, + 0xc7, 0x0a, 0xf5, 0x0e, 0x5d, 0x08, 0x00, 0x41, + 0x3b, 0x02, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, + 0x0e, 0x5d, 0x07, 0x00, 0x41, 0xc5, 0x01, 0x00, + 0x00, 0xd7, 0x24, 0x01, 0x00, 0xd5, 0xba, 0xa7, + 0xf0, 0x35, 0x5d, 0x09, 0x00, 0xc7, 0x0c, 0x1b, + 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, 0x1b, + 0x04, 0x3c, 0x02, 0x00, 0x00, 0x41, 0x64, 0x00, + 0x00, 0x00, 0xcd, 0x04, 0x3d, 0x02, 0x00, 0x00, + 0x5d, 0x09, 0x00, 0xc7, 0x0c, 0x46, 0x24, 0x03, + 0x00, 0x1b, 0x71, 0x1b, 0x48, 0x29, 0xe3, 0x5d, + 0x06, 0x00, 0xd7, 0xf5, 0xf5, 0x0e, 0x29, 0x0c, + 0x43, 0x02, 0x01, 0x8c, 0x08, 0x02, 0x01, 0x02, + 0x03, 0x00, 0x05, 0x00, 0x3d, 0x03, 0xf6, 0x06, + 0x00, 0x01, 0x00, 0xb8, 0x06, 0x00, 0x01, 0x00, + 0xfc, 0x08, 0x00, 0x00, 0x00, 0xee, 0x07, 0x03, + 0x01, 0x80, 0x08, 0x0a, 0x00, 0xfe, 0x07, 0x09, + 0x00, 0xfe, 0x03, 0x0e, 0x02, 0x82, 0x04, 0x0f, + 0x02, 0xe3, 0xf0, 0x30, 0xe4, 0xd8, 0xae, 0xf0, + 0x13, 0xe5, 0x41, 0xb2, 0x01, 0x00, 0x00, 0xe6, + 0x40, 0x9e, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, + 0x0e, 0xd8, 0xe8, 0xd8, 0xf0, 0x16, 0xe6, 0x5d, + 0x04, 0x00, 0xd8, 0x46, 0x46, 0xd3, 0xf0, 0x0c, + 0xe5, 0x41, 0xb2, 0x01, 0x00, 0x00, 0xcb, 0x24, + 0x01, 0x00, 0x0e, 0xe5, 0x41, 0xb2, 0x01, 0x00, + 0x00, 0xd7, 0x24, 0x01, 0x00, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0x8e, 0x08, 0x01, 0x00, 0x01, 0x03, + 0x00, 0x01, 0x02, 0x2c, 0x01, 0xf6, 0x06, 0x00, + 0x01, 0x00, 0x8c, 0x08, 0x10, 0x00, 0x07, 0x02, + 0x30, 0x07, 0x02, 0x39, 0xd7, 0xba, 0x46, 0xc4, + 0x00, 0xa8, 0xf0, 0x14, 0xd7, 0xba, 0x46, 0xc4, + 0x01, 0xa6, 0xf0, 0x0c, 0xe3, 0xd7, 0x04, 0x4a, + 0x00, 0x00, 0x00, 0xf6, 0x0e, 0xf2, 0x0a, 0xe3, + 0xd7, 0x04, 0x3f, 0x02, 0x00, 0x00, 0xf6, 0x0e, + 0xe3, 0x04, 0x27, 0x02, 0x00, 0x00, 0xf5, 0x29, + 0x0c, 0x43, 0x02, 0x01, 0x90, 0x08, 0x01, 0x04, + 0x01, 0x05, 0x00, 0x03, 0x14, 0xa1, 0x04, 0x05, + 0xf6, 0x06, 0x00, 0x01, 0x00, 0xb8, 0x06, 0x00, + 0x00, 0x00, 0x80, 0x09, 0x00, 0x01, 0x00, 0xa0, + 0x06, 0x00, 0x02, 0x00, 0xbc, 0x07, 0x00, 0x03, + 0x00, 0xee, 0x07, 0x03, 0x01, 0x8c, 0x08, 0x10, + 0x00, 0x92, 0x08, 0x13, 0x00, 0x07, 0x20, 0x5e, + 0x22, 0x28, 0x5b, 0x5e, 0x5c, 0x5c, 0x22, 0x5d, + 0x7c, 0x5c, 0x5c, 0x2e, 0x29, 0x2a, 0x22, 0x07, + 0x98, 0x01, 0x00, 0x00, 0x02, 0x01, 0x44, 0x00, + 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, 0x00, 0x05, + 0x08, 0xf5, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x06, + 0x01, 0x22, 0x0e, 0x01, 0x01, 0x0a, 0x27, 0x00, + 0x00, 0x00, 0x1a, 0x0c, 0x01, 0x0a, 0x14, 0x00, + 0x00, 0x00, 0x16, 0x03, 0x00, 0x00, 0x00, 0x21, + 0x00, 0x23, 0x00, 0x5b, 0x00, 0x5d, 0x00, 0xff, + 0xff, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01, 0x5c, + 0x04, 0x0d, 0x01, 0x1b, 0x08, 0xd4, 0xff, 0xff, + 0xff, 0x01, 0x22, 0x0d, 0x00, 0x0b, 0x07, 0x20, + 0x5e, 0x27, 0x28, 0x5b, 0x5e, 0x5c, 0x5c, 0x27, + 0x5d, 0x7c, 0x5c, 0x5c, 0x2e, 0x29, 0x2a, 0x27, + 0x07, 0x98, 0x01, 0x00, 0x00, 0x02, 0x01, 0x44, + 0x00, 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, 0x00, + 0x05, 0x08, 0xf5, 0xff, 0xff, 0xff, 0x0c, 0x00, + 0x06, 0x01, 0x27, 0x0e, 0x01, 0x01, 0x0a, 0x27, + 0x00, 0x00, 0x00, 0x1a, 0x0c, 0x01, 0x0a, 0x14, + 0x00, 0x00, 0x00, 0x16, 0x03, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x28, 0x00, 0x5b, 0x00, 0x5d, 0x00, + 0xff, 0xff, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01, + 0x5c, 0x04, 0x0d, 0x01, 0x1b, 0x08, 0xd4, 0xff, + 0xff, 0xff, 0x01, 0x27, 0x0d, 0x00, 0x0b, 0x07, + 0x16, 0x5e, 0x5c, 0x3c, 0x5b, 0x5e, 0x5c, 0x3e, + 0x5d, 0x2b, 0x5c, 0x3e, 0x07, 0x74, 0x00, 0x00, + 0x01, 0x00, 0x32, 0x00, 0x00, 0x00, 0x09, 0x06, + 0x00, 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, 0xff, + 0xff, 0x0c, 0x00, 0x06, 0x01, 0x3c, 0x1d, 0x0c, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, 0x16, + 0x02, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x3f, 0x00, + 0xff, 0xff, 0x0b, 0x01, 0x3e, 0x0d, 0x00, 0x0b, + 0x07, 0x16, 0x5e, 0x5c, 0x5b, 0x5b, 0x5e, 0x5c, + 0x5d, 0x5d, 0x2b, 0x5c, 0x5d, 0x07, 0x74, 0x00, + 0x00, 0x01, 0x00, 0x32, 0x00, 0x00, 0x00, 0x09, + 0x06, 0x00, 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, + 0xff, 0xff, 0x0c, 0x00, 0x06, 0x01, 0x5b, 0x1d, + 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, + 0x16, 0x02, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x5e, + 0x00, 0xff, 0xff, 0x0b, 0x01, 0x5d, 0x0d, 0x00, + 0x0b, 0x07, 0x02, 0x30, 0x07, 0x02, 0x31, 0x07, + 0x02, 0x32, 0x07, 0x02, 0x33, 0x07, 0x02, 0x34, + 0x07, 0x02, 0x35, 0x07, 0x02, 0x36, 0x07, 0x02, + 0x37, 0x07, 0x02, 0x38, 0x07, 0x02, 0x39, 0x07, + 0x56, 0x5e, 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, + 0x7a, 0x5f, 0x5d, 0x2b, 0x5b, 0x2e, 0x5d, 0x3f, + 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x7a, 0x5f, + 0x5d, 0x2a, 0x5b, 0x65, 0x45, 0x70, 0x50, 0x5d, + 0x3f, 0x5b, 0x2b, 0x2d, 0x5d, 0x3f, 0x5b, 0x30, + 0x2d, 0x39, 0x5d, 0x2a, 0x07, 0x9e, 0x03, 0x00, + 0x00, 0x01, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x09, + 0x06, 0x00, 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, + 0xff, 0xff, 0x0c, 0x00, 0x06, 0x1d, 0x10, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, 0x16, 0x03, + 0x00, 0x30, 0x00, 0x39, 0x00, 0x5f, 0x00, 0x5f, + 0x00, 0x61, 0x00, 0x7a, 0x00, 0x0b, 0x1d, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, + 0x01, 0x00, 0x2e, 0x00, 0x2e, 0x00, 0x0b, 0x1d, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, + 0x16, 0x03, 0x00, 0x30, 0x00, 0x39, 0x00, 0x5f, + 0x00, 0x5f, 0x00, 0x61, 0x00, 0x7a, 0x00, 0x0b, + 0x1d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x16, 0x04, 0x00, 0x45, 0x00, 0x45, 0x00, + 0x50, 0x00, 0x50, 0x00, 0x65, 0x00, 0x65, 0x00, + 0x70, 0x00, 0x70, 0x00, 0x0b, 0x1d, 0x0c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, 0x02, + 0x00, 0x2b, 0x00, 0x2b, 0x00, 0x2d, 0x00, 0x2d, + 0x00, 0x0b, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x01, + 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x30, 0x00, + 0x39, 0x00, 0x0b, 0x0d, 0x00, 0x0b, 0xe3, 0x95, + 0xf0, 0x05, 0xe4, 0xd7, 0xf5, 0x29, 0xd7, 0xef, + 0xba, 0xa7, 0x68, 0x13, 0x02, 0x00, 0x00, 0x04, + 0x9e, 0x01, 0x00, 0x00, 0xcf, 0xd7, 0xd0, 0xba, + 0xd1, 0x07, 0xd2, 0xd7, 0xba, 0x46, 0x11, 0x04, + 0xc7, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x19, 0x04, + 0x4c, 0x00, 0x00, 0x00, 0xcf, 0xd7, 0x41, 0xcb, + 0x01, 0x00, 0x00, 0xc4, 0x00, 0xc4, 0x01, 0x34, + 0x24, 0x01, 0x00, 0xd2, 0xf3, 0xb3, 0x01, 0x11, + 0x04, 0xc6, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x19, + 0x04, 0x4c, 0x00, 0x00, 0x00, 0xcf, 0xd7, 0x41, + 0xcb, 0x01, 0x00, 0x00, 0xc4, 0x02, 0xc4, 0x03, + 0x34, 0x24, 0x01, 0x00, 0xd2, 0xf3, 0x92, 0x01, + 0x11, 0x04, 0xca, 0x01, 0x00, 0x00, 0xad, 0xf0, + 0x0a, 0x04, 0x41, 0x02, 0x00, 0x00, 0xcf, 0xf3, + 0x80, 0x01, 0x11, 0x04, 0x32, 0x02, 0x00, 0x00, + 0xad, 0xf0, 0x1e, 0xd7, 0x41, 0xcb, 0x01, 0x00, + 0x00, 0xc4, 0x04, 0xc4, 0x05, 0x34, 0x24, 0x01, + 0x00, 0xd6, 0x68, 0x65, 0x01, 0x00, 0x00, 0x04, + 0x42, 0x02, 0x00, 0x00, 0xcf, 0xf3, 0x5a, 0x01, + 0x11, 0x04, 0xed, 0x01, 0x00, 0x00, 0xad, 0xf0, + 0x1b, 0xd7, 0x41, 0xcb, 0x01, 0x00, 0x00, 0xc4, + 0x06, 0xc4, 0x07, 0x34, 0x24, 0x01, 0x00, 0xd6, + 0xf0, 0x2e, 0x04, 0x42, 0x02, 0x00, 0x00, 0xcf, + 0xf3, 0x37, 0x01, 0x11, 0x04, 0xc9, 0x01, 0x00, + 0x00, 0xad, 0xf1, 0x1c, 0x11, 0x04, 0x31, 0x02, + 0x00, 0x00, 0xad, 0xf1, 0x13, 0x11, 0x04, 0x43, + 0x02, 0x00, 0x00, 0xad, 0xf1, 0x0a, 0x11, 0x04, + 0xe8, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x0c, 0x04, + 0x44, 0x02, 0x00, 0x00, 0xcf, 0xbb, 0xd1, 0xf3, + 0x08, 0x01, 0x11, 0x04, 0xbe, 0x01, 0x00, 0x00, + 0xad, 0xf0, 0x0a, 0x04, 0x42, 0x02, 0x00, 0x00, + 0xcf, 0xf3, 0xf6, 0x00, 0x11, 0xc4, 0x08, 0xad, + 0xf1, 0x37, 0x11, 0xc4, 0x09, 0xad, 0xf1, 0x31, + 0x11, 0xc4, 0x0a, 0xad, 0xf1, 0x2b, 0x11, 0xc4, + 0x0b, 0xad, 0xf1, 0x25, 0x11, 0xc4, 0x0c, 0xad, + 0xf1, 0x1f, 0x11, 0xc4, 0x0d, 0xad, 0xf1, 0x19, + 0x11, 0xc4, 0x0e, 0xad, 0xf1, 0x13, 0x11, 0xc4, + 0x0f, 0xad, 0xf1, 0x0d, 0x11, 0xc4, 0x10, 0xad, + 0xf1, 0x07, 0x11, 0xc4, 0x11, 0xad, 0xf0, 0x19, + 0x04, 0x4a, 0x00, 0x00, 0x00, 0xcf, 0xd7, 0x41, + 0xcb, 0x01, 0x00, 0x00, 0xc4, 0x12, 0xc4, 0x13, + 0x34, 0x24, 0x01, 0x00, 0xd2, 0xf3, 0xa2, 0x00, + 0x11, 0x04, 0xf3, 0x01, 0x00, 0x00, 0xad, 0xf0, + 0x06, 0xbb, 0xd1, 0xf3, 0x94, 0x00, 0xe5, 0xd7, + 0xf5, 0xf0, 0x06, 0xd7, 0xef, 0xbb, 0x9d, 0xd1, + 0xd7, 0x41, 0xd3, 0x01, 0x00, 0x00, 0x04, 0xa8, + 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0xf0, 0x09, + 0x04, 0x45, 0x02, 0x00, 0x00, 0xcf, 0xf2, 0x71, + 0xd7, 0x41, 0xd3, 0x01, 0x00, 0x00, 0x04, 0xa4, + 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0xf0, 0x09, + 0x04, 0x4e, 0x00, 0x00, 0x00, 0xcf, 0xf2, 0x59, + 0xd7, 0x04, 0xfc, 0x00, 0x00, 0x00, 0xad, 0x11, + 0xf1, 0x09, 0x0e, 0xd7, 0x04, 0x46, 0x02, 0x00, + 0x00, 0xad, 0xf0, 0x09, 0x04, 0x47, 0x02, 0x00, + 0x00, 0xcf, 0xf2, 0x3d, 0xd7, 0x04, 0x03, 0x00, + 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, 0x0e, 0xd7, + 0x04, 0x02, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x09, + 0x04, 0x4b, 0x00, 0x00, 0x00, 0xcf, 0xf2, 0x21, + 0xd7, 0x04, 0x01, 0x00, 0x00, 0x00, 0xad, 0xf0, + 0x09, 0x04, 0x01, 0x00, 0x00, 0x00, 0xcf, 0xf2, + 0x10, 0xd7, 0x04, 0x49, 0x00, 0x00, 0x00, 0xad, + 0xf0, 0x07, 0x04, 0x49, 0x00, 0x00, 0x00, 0xcf, + 0x0e, 0xce, 0xf0, 0x06, 0xce, 0xba, 0x46, 0xef, + 0xd1, 0xcd, 0xba, 0xa7, 0xf0, 0x0d, 0xd7, 0x41, + 0xbf, 0x01, 0x00, 0x00, 0xba, 0xcd, 0x24, 0x02, + 0x00, 0xd0, 0xe4, 0xcc, 0xcb, 0xf6, 0x0e, 0xd7, + 0x41, 0xbf, 0x01, 0x00, 0x00, 0xcc, 0xef, 0x24, + 0x01, 0x00, 0xdb, 0xf3, 0xea, 0xfd, 0x29, 0x0c, + 0x43, 0x02, 0x01, 0x92, 0x08, 0x01, 0x01, 0x01, + 0x03, 0x00, 0x00, 0x00, 0x19, 0x02, 0xf6, 0x06, + 0x00, 0x01, 0x00, 0x8c, 0x06, 0x00, 0x00, 0x00, + 0xd7, 0xd7, 0xef, 0xbb, 0x9d, 0x46, 0xd3, 0x04, + 0xed, 0x01, 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, + 0x0e, 0xcb, 0x04, 0x30, 0x02, 0x00, 0x00, 0xad, + 0x28, 0x0c, 0x43, 0x02, 0x01, 0x94, 0x08, 0x01, + 0x04, 0x01, 0x06, 0x00, 0x03, 0x00, 0x6e, 0x05, + 0x86, 0x06, 0x00, 0x01, 0x00, 0x90, 0x09, 0x00, + 0x00, 0x00, 0x92, 0x09, 0x00, 0x01, 0x00, 0x94, + 0x09, 0x00, 0x02, 0x00, 0xf6, 0x06, 0x00, 0x03, + 0x00, 0xfc, 0x07, 0x08, 0x00, 0x92, 0x08, 0x13, + 0x00, 0x94, 0x08, 0x14, 0x00, 0xe3, 0xd7, 0x46, + 0xef, 0xcf, 0xe3, 0xd7, 0xbb, 0x9c, 0x46, 0x04, + 0x37, 0x02, 0x00, 0x00, 0xad, 0xf0, 0x0e, 0xd7, + 0xbc, 0x9c, 0xdb, 0xcb, 0xbc, 0xe3, 0xd7, 0x46, + 0xef, 0x9c, 0x9c, 0xcf, 0xcb, 0xd0, 0xe4, 0xe3, + 0xd7, 0x46, 0xf5, 0xf0, 0x41, 0xbb, 0xd1, 0xd7, + 0x8e, 0xdf, 0xe3, 0xef, 0xa5, 0xf0, 0x37, 0xcd, + 0x93, 0x01, 0xe3, 0xd7, 0x46, 0xd6, 0x04, 0xc9, + 0x01, 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, 0x0e, + 0xce, 0x04, 0x31, 0x02, 0x00, 0x00, 0xad, 0xf1, + 0x1d, 0xf2, 0x0e, 0x11, 0x7e, 0x81, 0x00, 0x0e, + 0xdb, 0x81, 0x00, 0x0e, 0xcf, 0x83, 0xf2, 0x06, + 0xe5, 0xd7, 0xf5, 0xf2, 0xef, 0x0e, 0xcb, 0x93, + 0x01, 0xbc, 0xd1, 0xf2, 0xc3, 0xd7, 0xcc, 0x26, + 0x02, 0x00, 0x28, 0x0c, 0x43, 0x02, 0x01, 0x96, + 0x08, 0x02, 0x02, 0x02, 0x03, 0x00, 0x05, 0x00, + 0x67, 0x04, 0x86, 0x06, 0x00, 0x01, 0x00, 0x96, + 0x09, 0x00, 0x01, 0x00, 0xba, 0x08, 0x00, 0x00, + 0x00, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xfc, 0x07, + 0x08, 0x00, 0x8c, 0x08, 0x10, 0x00, 0x8e, 0x08, + 0x11, 0x00, 0x90, 0x08, 0x12, 0x00, 0x92, 0x08, + 0x13, 0x00, 0xc6, 0xcf, 0xd7, 0xd8, 0xa6, 0xf0, + 0x60, 0xe3, 0xd7, 0x90, 0xdb, 0x46, 0xd4, 0x04, + 0xc9, 0x01, 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, + 0x0e, 0xcc, 0x04, 0x31, 0x02, 0x00, 0x00, 0xad, + 0xf0, 0x11, 0xcb, 0xef, 0xbb, 0xa7, 0xf0, 0x27, + 0xe4, 0x04, 0xe8, 0x01, 0x00, 0x00, 0xf5, 0x0e, + 0xf2, 0x1d, 0xe4, 0xcb, 0xf5, 0x0e, 0xe3, 0xd7, + 0x46, 0x04, 0x37, 0x02, 0x00, 0x00, 0xad, 0xf0, + 0x0e, 0xe5, 0xcc, 0xf5, 0x0e, 0xd7, 0x8e, 0xdb, + 0xe3, 0xd7, 0x90, 0xdb, 0x46, 0xd0, 0xe6, 0xcc, + 0xf5, 0x0e, 0x5d, 0x04, 0x00, 0xcc, 0xf5, 0xf0, + 0x08, 0x04, 0xe8, 0x01, 0x00, 0x00, 0xf2, 0x06, + 0x04, 0x4c, 0x02, 0x00, 0x00, 0xcf, 0xf2, 0x9d, + 0x29, 0x0c, 0x43, 0x02, 0x01, 0x98, 0x08, 0x02, + 0x00, 0x02, 0x04, 0x00, 0x01, 0x00, 0x1a, 0x02, + 0xf6, 0x06, 0x00, 0x01, 0x00, 0xca, 0x07, 0x00, + 0x01, 0x00, 0x8c, 0x08, 0x10, 0x00, 0xd8, 0xba, + 0xa7, 0xf0, 0x12, 0xd7, 0x04, 0xe8, 0x01, 0x00, + 0x00, 0x41, 0x4d, 0x02, 0x00, 0x00, 0xd8, 0x24, + 0x01, 0x00, 0x9c, 0xdb, 0xe3, 0xd7, 0xf5, 0x29, + 0x0c, 0x43, 0x02, 0x01, 0x9a, 0x08, 0x02, 0x0c, + 0x02, 0x07, 0x00, 0x0b, 0x00, 0xe7, 0x04, 0x0e, + 0x9c, 0x09, 0x00, 0x01, 0x00, 0x86, 0x02, 0x00, + 0x01, 0x00, 0x9e, 0x09, 0x00, 0x00, 0x00, 0x96, + 0x09, 0x00, 0x01, 0x00, 0x92, 0x09, 0x00, 0x02, + 0x00, 0xba, 0x08, 0x00, 0x03, 0x00, 0xa0, 0x09, + 0x00, 0x04, 0x00, 0x86, 0x06, 0x00, 0x05, 0x00, + 0x90, 0x09, 0x00, 0x06, 0x00, 0xac, 0x08, 0x00, + 0x07, 0x00, 0xb4, 0x07, 0x00, 0x08, 0x00, 0xa2, + 0x09, 0x00, 0x09, 0x00, 0xf4, 0x05, 0x00, 0x0a, + 0x00, 0xa4, 0x09, 0x00, 0x0b, 0x00, 0xf2, 0x07, + 0x02, 0x00, 0x94, 0x08, 0x14, 0x00, 0x96, 0x08, + 0x15, 0x00, 0xfc, 0x07, 0x08, 0x00, 0x8e, 0x08, + 0x11, 0x00, 0x90, 0x08, 0x12, 0x00, 0x92, 0x08, + 0x13, 0x00, 0xcc, 0x02, 0x10, 0x02, 0x8c, 0x08, + 0x10, 0x00, 0x98, 0x08, 0x16, 0x00, 0x9a, 0x08, + 0x17, 0x00, 0xe3, 0xd7, 0x9d, 0xbc, 0x9d, 0xcf, + 0x06, 0x11, 0xf8, 0xf1, 0x0d, 0x7e, 0x81, 0x00, + 0x0e, 0xd0, 0x81, 0x00, 0x0e, 0xd1, 0x83, 0xf2, + 0x07, 0x0e, 0xe4, 0xd8, 0xf5, 0xf2, 0xef, 0xcd, + 0xcb, 0xa6, 0xf0, 0x0c, 0xe5, 0xd8, 0xcc, 0xf6, + 0x0e, 0xcc, 0xcd, 0x26, 0x02, 0x00, 0x28, 0xe6, + 0xd8, 0xbb, 0x9c, 0x46, 0x04, 0x37, 0x02, 0x00, + 0x00, 0xad, 0xf0, 0x0d, 0x5d, 0x04, 0x00, 0xe6, + 0xd8, 0x46, 0xf5, 0x0e, 0xd8, 0xbc, 0x9c, 0xdc, + 0x5d, 0x05, 0x00, 0xe6, 0xd8, 0x46, 0xf5, 0x0e, + 0x5d, 0x06, 0x00, 0xe6, 0xd8, 0x46, 0xf5, 0x95, + 0xf0, 0x07, 0xd8, 0xcd, 0x26, 0x02, 0x00, 0x28, + 0xd7, 0xbc, 0x9c, 0xdb, 0xcb, 0xbc, 0x9d, 0xcf, + 0xc6, 0xd2, 0xd8, 0xbb, 0x9c, 0xc8, 0x04, 0xe6, + 0xd8, 0x46, 0x41, 0x53, 0x02, 0x00, 0x00, 0x04, + 0xed, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x68, + 0x8d, 0x01, 0x00, 0x00, 0xba, 0xc8, 0x07, 0x26, + 0x00, 0x00, 0xc8, 0x0a, 0xc7, 0x04, 0xc8, 0x05, + 0xc7, 0x05, 0xcc, 0xa5, 0xf0, 0x51, 0xe6, 0xc7, + 0x05, 0x46, 0xba, 0x46, 0x04, 0xbe, 0x01, 0x00, + 0x00, 0xad, 0x11, 0xf1, 0x0e, 0x0e, 0xe6, 0xc7, + 0x05, 0xbb, 0x9c, 0x46, 0x04, 0x37, 0x02, 0x00, + 0x00, 0xad, 0xf1, 0x33, 0xf2, 0x10, 0x11, 0x7e, + 0x81, 0x00, 0x0e, 0xc8, 0x05, 0x81, 0x00, 0x0e, + 0xc8, 0x06, 0x83, 0xf2, 0x07, 0xe4, 0xc7, 0x05, + 0xf5, 0xf2, 0xec, 0x0e, 0xc7, 0x0a, 0xc7, 0x07, + 0x90, 0xc8, 0x07, 0x1b, 0x11, 0xaf, 0xf1, 0x04, + 0x1b, 0x71, 0x1b, 0x1b, 0xc7, 0x06, 0x1b, 0x71, + 0x1b, 0x48, 0x92, 0x05, 0xf2, 0xab, 0x5d, 0x07, + 0x00, 0x41, 0xa5, 0x01, 0x00, 0x00, 0xcb, 0xbd, + 0x9a, 0xc7, 0x0a, 0xef, 0xc2, 0x10, 0x24, 0x03, + 0x00, 0xc8, 0x09, 0xc7, 0x09, 0xbb, 0xa7, 0xf0, + 0x73, 0x26, 0x00, 0x00, 0xc8, 0x0b, 0xba, 0xc8, + 0x08, 0xba, 0xc8, 0x07, 0xc7, 0x07, 0xc7, 0x0a, + 0xef, 0xa5, 0xf0, 0x3b, 0xc7, 0x0b, 0xc7, 0x08, + 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, + 0x1b, 0x5d, 0x07, 0x00, 0x41, 0xe1, 0x01, 0x00, + 0x00, 0xc7, 0x0b, 0xc7, 0x08, 0x46, 0x11, 0xf1, + 0x03, 0x0e, 0xba, 0xc7, 0x0a, 0xc7, 0x07, 0x46, + 0xbc, 0x9c, 0x24, 0x02, 0x00, 0x1b, 0x71, 0x1b, + 0x48, 0xc7, 0x08, 0xbb, 0x9c, 0xc7, 0x09, 0x9b, + 0xc8, 0x08, 0x92, 0x07, 0xf2, 0xbf, 0xba, 0xc8, + 0x06, 0xba, 0xc8, 0x08, 0xc7, 0x08, 0xc7, 0x09, + 0xa5, 0xf0, 0x0f, 0xc7, 0x06, 0xc7, 0x0b, 0xc7, + 0x08, 0x46, 0x9c, 0xc8, 0x06, 0x92, 0x08, 0xf2, + 0xec, 0xc7, 0x06, 0xcb, 0xa6, 0xf1, 0x05, 0x91, + 0x09, 0xf2, 0x89, 0xc7, 0x09, 0xbb, 0xa7, 0x68, + 0x95, 0x00, 0x00, 0x00, 0xba, 0xc8, 0x06, 0xc7, + 0x09, 0xbb, 0x9d, 0xc8, 0x08, 0xc7, 0x04, 0xc8, + 0x05, 0xc7, 0x05, 0xcc, 0xa5, 0xf0, 0x7b, 0xe6, + 0xc7, 0x05, 0x46, 0xba, 0x46, 0x04, 0xbe, 0x01, + 0x00, 0x00, 0xad, 0x11, 0xf1, 0x0e, 0x0e, 0xe6, + 0xc7, 0x05, 0xbb, 0x9c, 0x46, 0x04, 0x37, 0x02, + 0x00, 0x00, 0xad, 0xf1, 0x5d, 0xc7, 0x06, 0xce, + 0xef, 0x9c, 0xc8, 0x06, 0x5d, 0x08, 0x00, 0xce, + 0xf5, 0x0e, 0x04, 0x43, 0x02, 0x00, 0x00, 0xd2, + 0xc7, 0x08, 0xc7, 0x09, 0xbb, 0x9d, 0xad, 0xf0, + 0x11, 0x5d, 0x09, 0x00, 0x04, 0xa4, 0x01, 0x00, + 0x00, 0xd7, 0xf6, 0x0e, 0xba, 0xc8, 0x08, 0xf2, + 0x23, 0x5d, 0x09, 0x00, 0xc6, 0xc7, 0x0b, 0xc7, + 0x08, 0x90, 0xc8, 0x08, 0x46, 0xc7, 0x06, 0x9d, + 0xf6, 0x0e, 0xf2, 0x10, 0x11, 0x7e, 0x81, 0x00, + 0x0e, 0xc8, 0x05, 0x81, 0x00, 0x0e, 0xc8, 0x06, + 0x83, 0xf2, 0x0a, 0x5d, 0x0a, 0x00, 0xd7, 0xc7, + 0x05, 0xf6, 0xf2, 0xe9, 0x0e, 0x92, 0x05, 0xf2, + 0x81, 0xc7, 0x05, 0xc8, 0x04, 0xc7, 0x04, 0xc8, + 0x05, 0xc7, 0x05, 0xcc, 0xa5, 0xf0, 0x37, 0x5d, + 0x08, 0x00, 0xce, 0xf5, 0x0e, 0x04, 0x43, 0x02, + 0x00, 0x00, 0xd2, 0x5d, 0x09, 0x00, 0x04, 0xa4, + 0x01, 0x00, 0x00, 0xd7, 0xf6, 0x0e, 0xf2, 0x10, + 0x11, 0x7e, 0x81, 0x00, 0x0e, 0xc8, 0x05, 0x81, + 0x00, 0x0e, 0xc8, 0x06, 0x83, 0xf2, 0x0a, 0x5d, + 0x0a, 0x00, 0xd7, 0xc7, 0x05, 0xf6, 0xf2, 0xe9, + 0x0e, 0x92, 0x05, 0xf2, 0xc5, 0x5d, 0x09, 0x00, + 0x04, 0xa4, 0x01, 0x00, 0x00, 0xd7, 0xbc, 0x9d, + 0xdf, 0xf6, 0x0e, 0x5d, 0x05, 0x00, 0xe6, 0xcc, + 0x46, 0xf5, 0x0e, 0xcc, 0xe3, 0x26, 0x02, 0x00, + 0x28, 0xc5, 0x00, 0xd0, 0xc5, 0x01, 0xc8, 0x0b, + 0xc5, 0x02, 0xc8, 0x0c, 0xc5, 0x03, 0xc8, 0x0d, + 0xc5, 0x04, 0xc8, 0x0e, 0xc5, 0x05, 0xc8, 0x0f, + 0xc5, 0x06, 0xc8, 0x10, 0xc5, 0x07, 0xc8, 0x11, + 0xc5, 0x08, 0xc8, 0x12, 0xc5, 0x09, 0xc8, 0x13, + 0xc5, 0x0a, 0xc8, 0x14, 0xc5, 0x0b, 0xc8, 0x15, + 0xc5, 0x0c, 0xc8, 0x16, 0xc5, 0x0d, 0xc8, 0x17, + 0x0b, 0xcf, 0xd8, 0x96, 0x04, 0x4d, 0x00, 0x00, + 0x00, 0xad, 0xf0, 0x1c, 0xd8, 0x07, 0xae, 0xf0, + 0x17, 0xd8, 0xd3, 0x40, 0x54, 0x02, 0x00, 0x00, + 0xdc, 0xcb, 0x40, 0x55, 0x02, 0x00, 0x00, 0xdd, + 0xcb, 0x40, 0xff, 0x00, 0x00, 0x00, 0xde, 0xd8, + 0x96, 0x04, 0x4b, 0x00, 0x00, 0x00, 0xae, 0xf0, + 0x03, 0x09, 0xdc, 0xcc, 0xd9, 0xbc, 0xf6, 0xdd, + 0xcc, 0xda, 0x0a, 0xf6, 0xde, 0xcc, 0xcb, 0x40, + 0xf9, 0x01, 0x00, 0x00, 0x5d, 0x10, 0x00, 0x41, + 0xa5, 0x01, 0x00, 0x00, 0x5d, 0x11, 0x00, 0xc2, + 0x50, 0x24, 0x02, 0x00, 0xf6, 0xd1, 0xcc, 0xcb, + 0x40, 0xfa, 0x01, 0x00, 0x00, 0xc2, 0x64, 0xf6, + 0xd2, 0xcc, 0xcb, 0x40, 0xfb, 0x01, 0x00, 0x00, + 0xce, 0xc2, 0x0a, 0x9c, 0xf6, 0xc8, 0x04, 0xcc, + 0xcb, 0x40, 0xfc, 0x01, 0x00, 0x00, 0xc2, 0x4e, + 0xf6, 0xc8, 0x05, 0x0b, 0x26, 0x01, 0x00, 0xc8, + 0x06, 0x26, 0x00, 0x00, 0xc8, 0x07, 0x26, 0x00, + 0x00, 0xc8, 0x08, 0x26, 0x00, 0x00, 0xc8, 0x09, + 0x04, 0x9e, 0x01, 0x00, 0x00, 0xc8, 0x0a, 0xc7, + 0x0f, 0xd7, 0xba, 0xf6, 0x0e, 0xc7, 0x17, 0xba, + 0xba, 0xf6, 0x0e, 0xc7, 0x10, 0xc6, 0xf5, 0x0e, + 0xc7, 0x09, 0x41, 0x63, 0x00, 0x00, 0x00, 0xc6, + 0x25, 0x01, 0x00, 0x0c, 0x43, 0x02, 0x01, 0xcc, + 0x05, 0x01, 0x00, 0x01, 0x07, 0x00, 0x05, 0x00, + 0x3c, 0x01, 0xea, 0x07, 0x00, 0x01, 0x00, 0xec, + 0x03, 0x00, 0x1a, 0xca, 0x05, 0x78, 0x00, 0x8c, + 0x04, 0x19, 0x00, 0x88, 0x04, 0x17, 0x00, 0x8a, + 0x04, 0x18, 0x00, 0x64, 0x00, 0x00, 0x41, 0x9d, + 0x01, 0x00, 0x00, 0xe4, 0x41, 0x56, 0x02, 0x00, + 0x00, 0xd7, 0x0b, 0xe5, 0x4b, 0x55, 0x02, 0x00, + 0x00, 0xe6, 0x4b, 0xff, 0x00, 0x00, 0x00, 0x5d, + 0x04, 0x00, 0x4b, 0x54, 0x02, 0x00, 0x00, 0x24, + 0x02, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x64, 0x00, + 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, 0x04, 0xa4, + 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x29, 0x0c, + 0x43, 0x02, 0x01, 0xce, 0x05, 0x01, 0x05, 0x01, + 0x06, 0x00, 0x03, 0x00, 0xb4, 0x01, 0x06, 0x92, + 0x06, 0x00, 0x01, 0x00, 0xde, 0x06, 0x00, 0x00, + 0x00, 0xaa, 0x04, 0x00, 0x01, 0x00, 0xae, 0x09, + 0x00, 0x02, 0x00, 0xe0, 0x07, 0x00, 0x03, 0x00, + 0xb0, 0x09, 0x00, 0x04, 0x00, 0xd0, 0x05, 0x7b, + 0x00, 0xd8, 0x05, 0x7f, 0x00, 0xec, 0x03, 0x00, + 0x1a, 0xd7, 0x04, 0x59, 0x02, 0x00, 0x00, 0xad, + 0xf0, 0x06, 0xe3, 0xf4, 0x0e, 0x0a, 0x28, 0xd7, + 0xba, 0x46, 0x04, 0xc3, 0x01, 0x00, 0x00, 0xae, + 0xf0, 0x0e, 0xd7, 0xba, 0x46, 0x04, 0xbe, 0x01, + 0x00, 0x00, 0xae, 0xf0, 0x03, 0x09, 0x28, 0xbb, + 0xcf, 0xcb, 0xd7, 0xef, 0xa5, 0xf0, 0x10, 0xd7, + 0xcb, 0x46, 0x04, 0xe8, 0x01, 0x00, 0x00, 0xae, + 0xf0, 0x05, 0x92, 0x00, 0xf2, 0xec, 0xd7, 0x41, + 0x9f, 0x01, 0x00, 0x00, 0xbb, 0xcb, 0x24, 0x02, + 0x00, 0xd0, 0xba, 0xd1, 0xe4, 0x7d, 0xf2, 0x21, + 0xc8, 0x04, 0xc7, 0x04, 0x41, 0xd3, 0x01, 0x00, + 0x00, 0xcc, 0x24, 0x01, 0x00, 0xf0, 0x12, 0xe4, + 0xc7, 0x04, 0x46, 0xd2, 0x92, 0x02, 0xc7, 0x04, + 0xcc, 0xad, 0xf0, 0x05, 0xba, 0xd1, 0xf2, 0x05, + 0x80, 0xf0, 0xde, 0x0e, 0x0e, 0xce, 0xf0, 0x1d, + 0xcd, 0xbc, 0xa5, 0xf0, 0x18, 0xce, 0xd7, 0x41, + 0x9f, 0x01, 0x00, 0x00, 0xcb, 0x24, 0x01, 0x00, + 0x41, 0x5a, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, + 0xf5, 0x0e, 0xf2, 0x20, 0x64, 0x02, 0x00, 0x41, + 0x9d, 0x01, 0x00, 0x00, 0x04, 0x5b, 0x02, 0x00, + 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0xcc, 0x04, + 0xa4, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, 0x24, + 0x01, 0x00, 0x0e, 0x0a, 0x28, 0x0c, 0x43, 0x02, + 0x01, 0xd0, 0x05, 0x00, 0x01, 0x00, 0x07, 0x00, + 0x09, 0x01, 0xdc, 0x01, 0x01, 0xb8, 0x09, 0x00, + 0x00, 0x00, 0xec, 0x03, 0x00, 0x1a, 0x8e, 0x04, + 0x1a, 0x00, 0x86, 0x04, 0x16, 0x00, 0x90, 0x04, + 0x1b, 0x00, 0x8c, 0x04, 0x19, 0x00, 0x8a, 0x04, + 0x18, 0x00, 0x88, 0x04, 0x17, 0x00, 0x82, 0x04, + 0x14, 0x00, 0x80, 0x04, 0x13, 0x00, 0x0c, 0x42, + 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x0f, 0x01, 0xc0, 0x06, 0x00, 0x01, + 0x00, 0xd7, 0xf0, 0x07, 0x04, 0x87, 0x00, 0x00, + 0x00, 0x28, 0x04, 0xe8, 0x01, 0x00, 0x00, 0x28, + 0xc5, 0x00, 0x4c, 0x5c, 0x02, 0x00, 0x00, 0xcf, + 0x64, 0x00, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, + 0x04, 0x5d, 0x02, 0x00, 0x00, 0x04, 0x5e, 0x02, + 0x00, 0x00, 0x9c, 0xcb, 0xe4, 0xf5, 0x9c, 0x04, + 0x5f, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x60, 0x02, + 0x00, 0x00, 0x9c, 0xcb, 0xe4, 0x95, 0xf5, 0x9c, + 0x04, 0x61, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x62, + 0x02, 0x00, 0x00, 0x9c, 0xcb, 0xe5, 0xf5, 0x9c, + 0x04, 0x63, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x64, + 0x02, 0x00, 0x00, 0x9c, 0xcb, 0xe6, 0xf5, 0x9c, + 0x04, 0x65, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x66, + 0x02, 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, + 0x5d, 0x04, 0x00, 0x04, 0x67, 0x02, 0x00, 0x00, + 0x24, 0x02, 0x00, 0x9c, 0x04, 0x68, 0x02, 0x00, + 0x00, 0x9c, 0xcb, 0x5d, 0x05, 0x00, 0xf5, 0x9c, + 0x04, 0x69, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x6a, + 0x02, 0x00, 0x00, 0x9c, 0xcb, 0x5d, 0x06, 0x00, + 0xf5, 0x9c, 0x04, 0x6b, 0x02, 0x00, 0x00, 0x9c, + 0x04, 0x6c, 0x02, 0x00, 0x00, 0x9c, 0xcb, 0x5d, + 0x07, 0x00, 0x5d, 0x08, 0x00, 0x40, 0x6d, 0x02, + 0x00, 0x00, 0xab, 0xf5, 0x9c, 0x04, 0x6e, 0x02, + 0x00, 0x00, 0x9c, 0x04, 0x6f, 0x02, 0x00, 0x00, + 0x9c, 0xcb, 0x5d, 0x07, 0x00, 0x5d, 0x08, 0x00, + 0x40, 0x70, 0x02, 0x00, 0x00, 0xab, 0xf5, 0x9c, + 0x04, 0x71, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x72, + 0x02, 0x00, 0x00, 0x9c, 0x04, 0x73, 0x02, 0x00, + 0x00, 0x9c, 0x04, 0x74, 0x02, 0x00, 0x00, 0x9c, + 0x24, 0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, + 0xd2, 0x05, 0x01, 0x01, 0x01, 0x07, 0x00, 0x01, + 0x00, 0x5f, 0x02, 0xf6, 0x06, 0x00, 0x01, 0x00, + 0xea, 0x09, 0x04, 0x00, 0x03, 0xec, 0x03, 0x00, + 0x1a, 0xd7, 0x41, 0x76, 0x02, 0x00, 0x00, 0x04, + 0xbe, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0xd7, + 0x41, 0x76, 0x02, 0x00, 0x00, 0x04, 0xca, 0x01, + 0x00, 0x00, 0x24, 0x01, 0x00, 0xa6, 0xf0, 0x09, + 0xd7, 0x04, 0x77, 0x02, 0x00, 0x00, 0x9c, 0xdb, + 0x6b, 0x13, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x41, 0x78, 0x02, 0x00, 0x00, 0xd7, 0x24, 0x01, + 0x00, 0x0e, 0x0e, 0x29, 0xcf, 0x6b, 0x21, 0x00, + 0x00, 0x00, 0x64, 0x00, 0x00, 0x41, 0x9d, 0x01, + 0x00, 0x00, 0xc6, 0x41, 0x64, 0x00, 0x00, 0x00, + 0xcb, 0x04, 0xa4, 0x01, 0x00, 0x00, 0x24, 0x02, + 0x00, 0x24, 0x01, 0x00, 0x0e, 0x0e, 0x29, 0x30, + 0x0c, 0x43, 0x02, 0x01, 0xd4, 0x05, 0x01, 0x00, + 0x01, 0x03, 0x00, 0x02, 0x00, 0x10, 0x01, 0xea, + 0x09, 0x00, 0x01, 0x00, 0xee, 0x05, 0x8a, 0x01, + 0x00, 0xec, 0x03, 0x00, 0x1a, 0xe3, 0xf4, 0x0e, + 0x64, 0x01, 0x00, 0x41, 0x6a, 0x01, 0x00, 0x00, + 0xd7, 0x24, 0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0xd6, 0x05, 0x02, 0x00, 0x02, 0x03, 0x00, + 0x00, 0x00, 0x14, 0x02, 0xf6, 0x06, 0x00, 0x01, + 0x00, 0x9e, 0x08, 0x00, 0x01, 0x00, 0xd7, 0xf0, + 0x10, 0x04, 0x79, 0x02, 0x00, 0x00, 0x41, 0x8e, + 0x01, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0x28, + 0xd8, 0x28, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x03, 0x00, 0x02, 0x00, 0x06, 0x01, + 0xf6, 0x06, 0x00, 0x01, 0x00, 0xd6, 0x05, 0x7e, + 0x00, 0x8e, 0x04, 0x1a, 0x00, 0xe3, 0xd7, 0x0a, + 0xf6, 0xe8, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x03, 0x00, 0x02, 0x00, 0x07, + 0x01, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xd6, 0x05, + 0x7e, 0x00, 0x8e, 0x04, 0x1a, 0x00, 0xe3, 0xd7, + 0x0a, 0xf6, 0x95, 0xe8, 0x29, 0x0c, 0x42, 0x02, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x02, + 0x00, 0x07, 0x01, 0xf6, 0x06, 0x00, 0x01, 0x00, + 0xd6, 0x05, 0x7e, 0x00, 0x86, 0x04, 0x16, 0x00, + 0xe3, 0xd7, 0xe4, 0x95, 0xf6, 0xe8, 0x29, 0x0c, + 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x03, + 0x00, 0x02, 0x00, 0x07, 0x01, 0xf6, 0x06, 0x00, + 0x01, 0x00, 0xd6, 0x05, 0x7e, 0x00, 0x90, 0x04, + 0x1b, 0x00, 0xe3, 0xd7, 0xe4, 0x95, 0xf6, 0xe8, + 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x02, 0x00, 0x01, 0x00, 0x09, 0x01, 0xf6, + 0x06, 0x00, 0x01, 0x00, 0x8c, 0x04, 0x19, 0x00, + 0xd7, 0x8c, 0x11, 0xf1, 0x03, 0x0e, 0xbc, 0xe7, + 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x03, 0x00, 0x02, 0x00, 0x07, 0x01, 0xf6, + 0x06, 0x00, 0x01, 0x00, 0xd6, 0x05, 0x7e, 0x00, + 0x8a, 0x04, 0x18, 0x00, 0xe3, 0xd7, 0xe4, 0x95, + 0xf6, 0xe8, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x03, 0x00, 0x02, 0x00, 0x07, + 0x01, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xd6, 0x05, + 0x7e, 0x00, 0x88, 0x04, 0x17, 0x00, 0xe3, 0xd7, + 0xe4, 0x95, 0xf6, 0xe8, 0x29, 0x0c, 0x42, 0x02, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, + 0x00, 0x08, 0x00, 0x80, 0x04, 0x13, 0x00, 0x82, + 0x04, 0x14, 0x00, 0xe3, 0x40, 0x6d, 0x02, 0x00, + 0x00, 0xe8, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x08, + 0x00, 0x80, 0x04, 0x13, 0x00, 0x82, 0x04, 0x14, + 0x00, 0xe3, 0x40, 0x70, 0x02, 0x00, 0x00, 0xe8, + 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x01, 0x00, 0x11, 0x00, 0xec, + 0x03, 0x00, 0x1a, 0x64, 0x00, 0x00, 0x41, 0x9d, + 0x01, 0x00, 0x00, 0x04, 0x7a, 0x02, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x29, 0x0c, 0x42, 0x02, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x04, 0x00, 0xd4, 0x05, 0x7d, 0x00, 0xe3, 0xba, + 0xf5, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xda, 0x05, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x14, + 0x00, 0xec, 0x03, 0x00, 0x1a, 0xdc, 0x05, 0x81, + 0x01, 0x00, 0x64, 0x00, 0x00, 0x41, 0x9d, 0x01, + 0x00, 0x00, 0x04, 0x7b, 0x02, 0x00, 0x00, 0x24, + 0x01, 0x00, 0x0e, 0xe4, 0xf4, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0xdc, 0x05, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x04, 0x00, 0x0c, 0x00, 0xc0, 0x05, 0x73, + 0x00, 0xb6, 0x05, 0x6e, 0x00, 0xa8, 0x04, 0x27, + 0x00, 0xde, 0x05, 0x82, 0x01, 0x00, 0xe3, 0xe4, + 0x04, 0x7c, 0x02, 0x00, 0x00, 0xe5, 0xf6, 0xe6, + 0xf6, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xde, 0x05, + 0x01, 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x0a, + 0x01, 0xfa, 0x09, 0x00, 0x01, 0x00, 0xe0, 0x05, + 0x83, 0x01, 0x00, 0xdc, 0x05, 0x81, 0x01, 0x00, + 0xe3, 0xd7, 0xf5, 0x95, 0xf0, 0x04, 0xe4, 0xf4, + 0x0e, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xe0, 0x05, + 0x01, 0x01, 0x01, 0x02, 0x00, 0x06, 0x00, 0x3a, + 0x02, 0xfa, 0x09, 0x00, 0x01, 0x00, 0xd2, 0x06, + 0x00, 0x00, 0x00, 0xa6, 0x04, 0x26, 0x00, 0xce, + 0x05, 0x7a, 0x00, 0xea, 0x05, 0x88, 0x01, 0x00, + 0x98, 0x04, 0x1f, 0x00, 0xa8, 0x04, 0x27, 0x00, + 0xe2, 0x05, 0x84, 0x01, 0x00, 0xd7, 0x95, 0xf0, + 0x03, 0x09, 0x28, 0xe3, 0xf0, 0x0d, 0xe3, 0x04, + 0xa4, 0x01, 0x00, 0x00, 0x9c, 0xd7, 0x9c, 0xdb, + 0xf2, 0x08, 0xe4, 0xd7, 0xf5, 0xf0, 0x03, 0x09, + 0x28, 0xe5, 0xd7, 0xf5, 0xd3, 0xba, 0x46, 0xea, + 0xcb, 0xbb, 0x46, 0x5e, 0x04, 0x00, 0xe6, 0xf0, + 0x05, 0xd7, 0xe7, 0x09, 0x28, 0xc6, 0xe7, 0x5d, + 0x05, 0x00, 0xd7, 0xf5, 0x0e, 0x0a, 0x28, 0x0c, + 0x43, 0x02, 0x01, 0xe2, 0x05, 0x01, 0x01, 0x01, + 0x06, 0x00, 0x06, 0x00, 0x4a, 0x02, 0xfa, 0x09, + 0x00, 0x01, 0x00, 0xfc, 0x09, 0x00, 0x00, 0x00, + 0x90, 0x04, 0x1b, 0x00, 0xee, 0x03, 0x01, 0x1a, + 0xa2, 0x04, 0x24, 0x00, 0xec, 0x03, 0x00, 0x1a, + 0xe4, 0x05, 0x85, 0x01, 0x00, 0xe6, 0x05, 0x86, + 0x01, 0x00, 0xe3, 0xf0, 0x09, 0x04, 0x7f, 0x02, + 0x00, 0x00, 0xd7, 0x9c, 0xdb, 0x64, 0x01, 0x00, + 0x41, 0x80, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, + 0xe9, 0x38, 0xce, 0x00, 0x00, 0x00, 0x41, 0x18, + 0x00, 0x00, 0x00, 0x64, 0x03, 0x00, 0x40, 0x81, + 0x02, 0x00, 0x00, 0xd7, 0x0b, 0x0a, 0x4b, 0x82, + 0x02, 0x00, 0x00, 0x0a, 0x4b, 0x8f, 0x00, 0x00, + 0x00, 0x24, 0x03, 0x00, 0xd3, 0x41, 0x89, 0x00, + 0x00, 0x00, 0x5d, 0x04, 0x00, 0x5d, 0x05, 0x00, + 0x24, 0x02, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, + 0xe4, 0x05, 0x01, 0x00, 0x01, 0x02, 0x00, 0x06, + 0x00, 0x27, 0x01, 0xfc, 0x09, 0x00, 0x01, 0x00, + 0xee, 0x03, 0x01, 0x1a, 0xa2, 0x04, 0x24, 0x00, + 0xa4, 0x04, 0x25, 0x00, 0xcc, 0x05, 0x79, 0x00, + 0xf2, 0x03, 0x00, 0x01, 0xe8, 0x05, 0x87, 0x01, + 0x00, 0xd7, 0x40, 0x44, 0x00, 0x00, 0x00, 0xdb, + 0x64, 0x00, 0x00, 0x41, 0x80, 0x02, 0x00, 0x00, + 0x24, 0x00, 0x00, 0xe4, 0x9d, 0xe9, 0xe6, 0xd7, + 0xf5, 0x0e, 0x5d, 0x04, 0x00, 0xd7, 0x42, 0x8b, + 0x01, 0x00, 0x00, 0x5d, 0x05, 0x00, 0xf4, 0x29, + 0x0c, 0x43, 0x02, 0x01, 0xe6, 0x05, 0x01, 0x00, + 0x01, 0x04, 0x00, 0x06, 0x00, 0xa1, 0x01, 0x01, + 0x6e, 0x00, 0x01, 0x00, 0x88, 0x04, 0x17, 0x00, + 0xec, 0x03, 0x00, 0x1a, 0xfe, 0x03, 0x12, 0x00, + 0x82, 0x04, 0x14, 0x00, 0xc0, 0x02, 0x09, 0x00, + 0xe8, 0x05, 0x87, 0x01, 0x00, 0xe3, 0xf0, 0x15, + 0x64, 0x01, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, + 0xe5, 0xe6, 0x40, 0x37, 0x00, 0x00, 0x00, 0x46, + 0x24, 0x01, 0x00, 0x0e, 0xd7, 0x5d, 0x04, 0x00, + 0xa9, 0xf0, 0x3b, 0x64, 0x01, 0x00, 0x41, 0x9d, + 0x01, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0x0e, + 0x64, 0x01, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, + 0x04, 0xa4, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, + 0x0e, 0xd7, 0x40, 0x39, 0x00, 0x00, 0x00, 0xf0, + 0x44, 0x64, 0x01, 0x00, 0x41, 0x9d, 0x01, 0x00, + 0x00, 0xd7, 0x40, 0x39, 0x00, 0x00, 0x00, 0x24, + 0x01, 0x00, 0x0e, 0xf2, 0x30, 0x64, 0x01, 0x00, + 0x41, 0x9d, 0x01, 0x00, 0x00, 0x04, 0x83, 0x02, + 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x64, 0x01, + 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, 0xd7, 0x24, + 0x01, 0x00, 0x0e, 0x64, 0x01, 0x00, 0x41, 0x9d, + 0x01, 0x00, 0x00, 0x04, 0xa4, 0x01, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x0e, 0xe3, 0xf0, 0x13, 0x64, + 0x01, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, 0xe5, + 0x40, 0x9e, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, + 0x0e, 0x5d, 0x05, 0x00, 0xf4, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0xe8, 0x05, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x03, 0x00, 0x11, 0x00, 0xa8, 0x04, 0x27, + 0x00, 0xec, 0x03, 0x00, 0x1a, 0xdc, 0x05, 0x81, + 0x01, 0x00, 0xba, 0xe7, 0x64, 0x01, 0x00, 0x41, + 0x84, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, 0x0e, + 0xe5, 0xf4, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xea, + 0x05, 0x01, 0x17, 0x01, 0x04, 0x0f, 0x03, 0x0a, + 0x84, 0x04, 0x18, 0x9e, 0x06, 0x00, 0x01, 0x40, + 0x06, 0x86, 0x06, 0x00, 0x00, 0x40, 0x04, 0x8c, + 0x06, 0x00, 0x01, 0x40, 0x08, 0xb2, 0x06, 0x00, + 0x02, 0x40, 0x0a, 0xc0, 0x06, 0x00, 0x03, 0x40, + 0x05, 0xb8, 0x06, 0x00, 0x04, 0x40, 0x02, 0x8a, + 0x0a, 0x00, 0x05, 0x40, 0x00, 0xa8, 0x04, 0x00, + 0x06, 0x00, 0x8c, 0x0a, 0x00, 0x07, 0x00, 0x8e, + 0x0a, 0x00, 0x08, 0x40, 0x09, 0x9a, 0x07, 0x00, + 0x09, 0x40, 0x0e, 0x90, 0x0a, 0x00, 0x0a, 0x40, + 0x03, 0x92, 0x0a, 0x00, 0x0b, 0x40, 0x01, 0x94, + 0x0a, 0x00, 0x0c, 0x40, 0x07, 0x96, 0x0a, 0x00, + 0x0d, 0x00, 0x98, 0x0a, 0x00, 0x0e, 0x00, 0x9a, + 0x0a, 0x00, 0x0f, 0x00, 0x9c, 0x0a, 0x00, 0x10, + 0x00, 0x9e, 0x0a, 0x00, 0x11, 0x00, 0xa0, 0x0a, + 0x00, 0x12, 0x40, 0x0b, 0xa2, 0x0a, 0x00, 0x13, + 0x40, 0x0c, 0xa4, 0x0a, 0x00, 0x14, 0x40, 0x0d, + 0xa6, 0x0a, 0x00, 0x15, 0x00, 0xa8, 0x0a, 0x00, + 0x16, 0x00, 0xd0, 0x04, 0x3b, 0x00, 0xd8, 0x04, + 0x3f, 0x00, 0xce, 0x04, 0x3a, 0x00, 0x0c, 0x43, + 0x02, 0x01, 0x90, 0x0a, 0x01, 0x00, 0x01, 0x02, + 0x00, 0x01, 0x00, 0x05, 0x01, 0x8c, 0x06, 0x00, + 0x01, 0x00, 0x8a, 0x0a, 0x05, 0x00, 0xe3, 0xd7, + 0x9c, 0xe7, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x92, + 0x0a, 0x01, 0x00, 0x01, 0x04, 0x00, 0x01, 0x00, + 0x0d, 0x01, 0x8c, 0x06, 0x00, 0x01, 0x00, 0x8a, + 0x0a, 0x05, 0x00, 0xe3, 0x41, 0x9f, 0x01, 0x00, + 0x00, 0xe3, 0xef, 0xbb, 0x9d, 0x25, 0x01, 0x00, + 0x0c, 0x43, 0x02, 0x01, 0x94, 0x0a, 0x01, 0x00, + 0x01, 0x05, 0x00, 0x02, 0x00, 0x14, 0x01, 0x8c, + 0x06, 0x00, 0x01, 0x00, 0x92, 0x0a, 0x0b, 0x00, + 0x8a, 0x0a, 0x05, 0x00, 0xe3, 0xf4, 0xdb, 0xe4, + 0x41, 0x9f, 0x01, 0x00, 0x00, 0xba, 0xe4, 0xef, + 0xbb, 0x9d, 0x24, 0x02, 0x00, 0xe8, 0xd7, 0x28, + 0x0c, 0x43, 0x02, 0x01, 0x96, 0x0a, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x06, 0x00, 0x49, 0x00, 0xb8, + 0x06, 0x04, 0x00, 0x90, 0x0a, 0x0a, 0x00, 0x86, + 0x06, 0x00, 0x00, 0xc0, 0x06, 0x03, 0x00, 0x9e, + 0x06, 0x00, 0x01, 0x94, 0x0a, 0x0c, 0x00, 0x04, + 0x95, 0x02, 0x00, 0x00, 0xe7, 0xe4, 0x04, 0xca, + 0x01, 0x00, 0x00, 0xf5, 0x0e, 0xe5, 0x8e, 0xe9, + 0xe5, 0xe6, 0xbb, 0x9d, 0xa5, 0xf0, 0x31, 0x5d, + 0x04, 0x00, 0xe5, 0x46, 0x04, 0x87, 0x00, 0x00, + 0x00, 0xab, 0xf0, 0x1f, 0x5d, 0x04, 0x00, 0xe5, + 0xbb, 0x9c, 0x46, 0x04, 0xca, 0x01, 0x00, 0x00, + 0xab, 0xf0, 0x10, 0xe5, 0xbc, 0x9c, 0xe9, 0x5d, + 0x05, 0x00, 0x04, 0xca, 0x01, 0x00, 0x00, 0xf5, + 0x0e, 0x29, 0xe5, 0x8e, 0xe9, 0xf2, 0xca, 0x29, + 0x0c, 0x43, 0x02, 0x01, 0x98, 0x0a, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x04, 0x00, 0x1f, 0x00, 0xb8, + 0x06, 0x04, 0x00, 0x86, 0x06, 0x00, 0x00, 0xc0, + 0x06, 0x03, 0x00, 0x9e, 0x06, 0x00, 0x01, 0x04, + 0x95, 0x02, 0x00, 0x00, 0xe7, 0xe4, 0x8e, 0xe8, + 0xe4, 0xe5, 0xa5, 0xf0, 0x11, 0xe6, 0xe4, 0x46, + 0x04, 0xa4, 0x01, 0x00, 0x00, 0xab, 0xf1, 0x06, + 0xe4, 0x8e, 0xe8, 0xf2, 0xec, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0x9a, 0x0a, 0x01, 0x00, 0x01, 0x03, + 0x00, 0x07, 0x00, 0x4c, 0x01, 0xac, 0x0a, 0x00, + 0x01, 0x00, 0xb8, 0x06, 0x04, 0x00, 0x90, 0x0a, + 0x0a, 0x00, 0x86, 0x06, 0x00, 0x00, 0xc0, 0x06, + 0x03, 0x00, 0x9e, 0x06, 0x00, 0x01, 0x8c, 0x06, + 0x01, 0x00, 0x94, 0x0a, 0x0c, 0x00, 0x04, 0x4c, + 0x00, 0x00, 0x00, 0xe7, 0xe4, 0xd7, 0xf5, 0x0e, + 0xe5, 0xe6, 0xa5, 0xf0, 0x3d, 0x5d, 0x04, 0x00, + 0xe5, 0x90, 0xe9, 0x46, 0x5f, 0x05, 0x00, 0x04, + 0xa4, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x09, 0x04, + 0x37, 0x00, 0x00, 0x00, 0xe7, 0xf2, 0xe2, 0x5d, + 0x05, 0x00, 0x04, 0xc3, 0x01, 0x00, 0x00, 0xab, + 0xf0, 0x0b, 0xe5, 0xe6, 0xa8, 0xf1, 0x13, 0xe5, + 0x8e, 0xe9, 0xf2, 0xcd, 0x5d, 0x05, 0x00, 0xd7, + 0xab, 0xf0, 0xc6, 0x5d, 0x06, 0x00, 0xf4, 0x0e, + 0x29, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x9c, 0x0a, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x09, 0x00, 0xc4, + 0x01, 0x00, 0xb8, 0x06, 0x04, 0x00, 0x90, 0x0a, + 0x0a, 0x00, 0x86, 0x06, 0x00, 0x00, 0xc0, 0x06, + 0x03, 0x00, 0x9e, 0x06, 0x00, 0x01, 0x8c, 0x06, + 0x01, 0x00, 0x92, 0x0a, 0x0b, 0x00, 0x94, 0x0a, + 0x0c, 0x00, 0xd0, 0x04, 0x00, 0x02, 0x04, 0x41, + 0x02, 0x00, 0x00, 0xe7, 0xe4, 0x04, 0xca, 0x01, + 0x00, 0x00, 0xf5, 0x0e, 0xe5, 0xe6, 0xa5, 0x68, + 0xb1, 0x00, 0x00, 0x00, 0x5d, 0x04, 0x00, 0xe5, + 0x90, 0xe9, 0x46, 0x5f, 0x05, 0x00, 0x04, 0xa4, + 0x01, 0x00, 0x00, 0xab, 0xf0, 0x09, 0x04, 0x37, + 0x00, 0x00, 0x00, 0xe7, 0xf2, 0xdf, 0x5d, 0x05, + 0x00, 0x04, 0xc3, 0x01, 0x00, 0x00, 0xab, 0xf0, + 0x0b, 0xe5, 0xe6, 0xa5, 0xf0, 0xcf, 0xe5, 0x8e, + 0xe9, 0xf2, 0xca, 0x5d, 0x06, 0x00, 0xf4, 0x04, + 0xed, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x13, 0x5d, + 0x05, 0x00, 0x04, 0xc9, 0x01, 0x00, 0x00, 0xab, + 0xf0, 0xb3, 0x5d, 0x07, 0x00, 0xf4, 0x0e, 0xf2, + 0xac, 0x5d, 0x05, 0x00, 0x04, 0xed, 0x01, 0x00, + 0x00, 0xab, 0xf0, 0x2e, 0xe4, 0x04, 0xed, 0x01, + 0x00, 0x00, 0xf5, 0x0e, 0x5d, 0x04, 0x00, 0xe5, + 0x46, 0x04, 0xed, 0x01, 0x00, 0x00, 0xab, 0x11, + 0xf1, 0x0d, 0x0e, 0x5d, 0x04, 0x00, 0xe5, 0x46, + 0x04, 0xc9, 0x01, 0x00, 0x00, 0xab, 0x68, 0x7d, + 0xff, 0xff, 0xff, 0xe5, 0x8e, 0xe9, 0xf3, 0x75, + 0xff, 0x5d, 0x05, 0x00, 0x04, 0xca, 0x01, 0x00, + 0x00, 0xab, 0x68, 0x69, 0xff, 0xff, 0xff, 0x5d, + 0x07, 0x00, 0xf4, 0x0e, 0xe5, 0xe6, 0xa5, 0xf0, + 0x11, 0x5d, 0x08, 0x00, 0x5d, 0x04, 0x00, 0xe5, + 0x46, 0xf5, 0xf0, 0x06, 0xe5, 0x8e, 0xe9, 0xf2, + 0xec, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x9e, 0x0a, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x00, 0x41, + 0x00, 0xb8, 0x06, 0x04, 0x00, 0x86, 0x06, 0x00, + 0x00, 0xc0, 0x06, 0x03, 0x00, 0xd0, 0x04, 0x00, + 0x02, 0x9e, 0x06, 0x00, 0x01, 0x04, 0x4a, 0x00, + 0x00, 0x00, 0xe7, 0xe4, 0xe5, 0xa5, 0xf0, 0x36, + 0xe6, 0x5d, 0x04, 0x00, 0xe4, 0x46, 0xf5, 0x11, + 0xf1, 0x25, 0x0e, 0x5d, 0x04, 0x00, 0xe4, 0x46, + 0x04, 0xbe, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x1e, + 0xe4, 0xe5, 0xbb, 0x9d, 0xab, 0x11, 0xf1, 0x0f, + 0x0e, 0x5d, 0x04, 0x00, 0xe4, 0xbb, 0x9c, 0x46, + 0x04, 0xbe, 0x01, 0x00, 0x00, 0xac, 0xf0, 0x06, + 0xe4, 0x8e, 0xe8, 0xf2, 0xc7, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0xa6, 0x0a, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x0a, 0x00, 0x95, 0x02, 0x03, 0xf6, 0x06, + 0x00, 0x00, 0x00, 0x90, 0x09, 0x00, 0x01, 0x00, + 0xae, 0x0a, 0x00, 0x02, 0x00, 0x8e, 0x0a, 0x08, + 0x00, 0x86, 0x06, 0x00, 0x00, 0xc0, 0x06, 0x03, + 0x00, 0xd0, 0x04, 0x00, 0x02, 0x9e, 0x06, 0x00, + 0x01, 0xb2, 0x06, 0x02, 0x00, 0xa0, 0x0a, 0x12, + 0x00, 0xb8, 0x06, 0x04, 0x00, 0xa2, 0x0a, 0x13, + 0x00, 0xa4, 0x0a, 0x14, 0x00, 0xbb, 0xe7, 0xe4, + 0xe5, 0xa5, 0xf0, 0x0f, 0xe6, 0x5d, 0x04, 0x00, + 0xe4, 0x46, 0xf5, 0xf0, 0x06, 0xe4, 0x8e, 0xe8, + 0xf2, 0xee, 0x5d, 0x04, 0x00, 0x41, 0x9f, 0x01, + 0x00, 0x00, 0x5d, 0x05, 0x00, 0xe4, 0x24, 0x02, + 0x00, 0xcf, 0x04, 0x98, 0x02, 0x00, 0x00, 0xcb, + 0x9c, 0x04, 0x98, 0x02, 0x00, 0x00, 0x9c, 0xd0, + 0x5d, 0x06, 0x00, 0x41, 0xc5, 0x01, 0x00, 0x00, + 0xcc, 0x24, 0x01, 0x00, 0xba, 0xa8, 0xf0, 0x7c, + 0x04, 0x47, 0x02, 0x00, 0x00, 0x5e, 0x07, 0x00, + 0xcb, 0x04, 0x03, 0x00, 0x00, 0x00, 0xad, 0x11, + 0xf1, 0x09, 0x0e, 0xcb, 0x04, 0x02, 0x00, 0x00, + 0x00, 0xad, 0xf0, 0x0b, 0x04, 0x4b, 0x00, 0x00, + 0x00, 0x5e, 0x07, 0x00, 0xf2, 0x43, 0xcb, 0x04, + 0x03, 0x00, 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, + 0x0e, 0xcb, 0x04, 0x02, 0x00, 0x00, 0x00, 0xad, + 0xf0, 0x0b, 0x04, 0x4b, 0x00, 0x00, 0x00, 0x5e, + 0x07, 0x00, 0xf2, 0x25, 0xcb, 0x04, 0x01, 0x00, + 0x00, 0x00, 0xad, 0xf0, 0x0b, 0x04, 0x01, 0x00, + 0x00, 0x00, 0x5e, 0x07, 0x00, 0xf2, 0x12, 0xcb, + 0x04, 0x49, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x09, + 0x04, 0x49, 0x00, 0x00, 0x00, 0x5e, 0x07, 0x00, + 0x5d, 0x08, 0x00, 0x41, 0xc5, 0x01, 0x00, 0x00, + 0xcc, 0x24, 0x01, 0x00, 0xba, 0xa8, 0xf0, 0x03, + 0xba, 0xe7, 0x29, 0xe4, 0xd1, 0xcd, 0xe5, 0xa5, + 0xf0, 0x12, 0x5d, 0x04, 0x00, 0xcd, 0x46, 0x04, + 0xe8, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x05, 0x92, + 0x02, 0xf2, 0xeb, 0xcd, 0xe5, 0xa5, 0xf0, 0x17, + 0x5d, 0x04, 0x00, 0xcd, 0x46, 0x04, 0xdf, 0x01, + 0x00, 0x00, 0xab, 0xf0, 0x0a, 0x04, 0x1b, 0x00, + 0x00, 0x00, 0x5e, 0x07, 0x00, 0x29, 0x5d, 0x09, + 0x00, 0x41, 0xc5, 0x01, 0x00, 0x00, 0xcc, 0x24, + 0x01, 0x00, 0xba, 0xa8, 0xf0, 0x0a, 0x04, 0x18, + 0x02, 0x00, 0x00, 0x5e, 0x07, 0x00, 0x29, 0x04, + 0x99, 0x02, 0x00, 0x00, 0x5e, 0x07, 0x00, 0xba, + 0xe7, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xa8, 0x0a, + 0x02, 0x00, 0x02, 0x03, 0x00, 0x02, 0x00, 0x2b, + 0x02, 0x86, 0x02, 0x00, 0x01, 0x00, 0xb4, 0x0a, + 0x00, 0x01, 0x00, 0x9a, 0x07, 0x09, 0x00, 0xb8, + 0x06, 0x04, 0x00, 0xe3, 0xef, 0xd7, 0xa5, 0xf0, + 0x12, 0xe3, 0x41, 0xb2, 0x01, 0x00, 0x00, 0x04, + 0x16, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, + 0xf2, 0xea, 0xe3, 0xef, 0xd8, 0xa5, 0xf0, 0x0e, + 0xe3, 0x41, 0xb2, 0x01, 0x00, 0x00, 0xe4, 0x24, + 0x01, 0x00, 0x0e, 0xf2, 0xee, 0x29, 0xc5, 0x00, + 0xc8, 0x0a, 0xc5, 0x01, 0xc8, 0x0b, 0xc5, 0x02, + 0xc8, 0x0c, 0xc5, 0x03, 0xc8, 0x0d, 0xc5, 0x04, + 0xc8, 0x0e, 0xc5, 0x05, 0xc8, 0x0f, 0xc5, 0x06, + 0xc8, 0x10, 0xc5, 0x07, 0xc8, 0x11, 0xc5, 0x08, + 0xc8, 0x15, 0xc5, 0x09, 0xc8, 0x16, 0xd7, 0xef, + 0xd2, 0xc6, 0xc8, 0x05, 0xba, 0xc8, 0x06, 0xbb, + 0xc8, 0x08, 0x26, 0x00, 0x00, 0xc8, 0x09, 0x04, + 0x98, 0x02, 0x00, 0x00, 0x04, 0x9b, 0x02, 0x00, + 0x00, 0x9c, 0x04, 0x9c, 0x02, 0x00, 0x00, 0x9c, + 0x04, 0x9d, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x9e, + 0x02, 0x00, 0x00, 0x9c, 0x04, 0x9f, 0x02, 0x00, + 0x00, 0x9c, 0x04, 0xa0, 0x02, 0x00, 0x00, 0x9c, + 0x04, 0xa1, 0x02, 0x00, 0x00, 0x9c, 0x04, 0xa2, + 0x02, 0x00, 0x00, 0x9c, 0x04, 0xa3, 0x02, 0x00, + 0x00, 0x9c, 0xc8, 0x12, 0x04, 0xa4, 0x02, 0x00, + 0x00, 0xc8, 0x13, 0x04, 0xa5, 0x02, 0x00, 0x00, + 0xc8, 0x14, 0xba, 0xcf, 0xcb, 0xce, 0xa5, 0x68, + 0x6a, 0x01, 0x00, 0x00, 0x07, 0xc8, 0x04, 0xcb, + 0xd1, 0xd7, 0xcb, 0x90, 0xcf, 0x46, 0xd4, 0x11, + 0x04, 0xe8, 0x01, 0x00, 0x00, 0xad, 0xf1, 0x1c, + 0x11, 0x04, 0xa6, 0x02, 0x00, 0x00, 0xad, 0xf1, + 0x13, 0x11, 0x04, 0xa7, 0x02, 0x00, 0x00, 0xad, + 0xf1, 0x0a, 0x11, 0x04, 0xa4, 0x01, 0x00, 0x00, + 0xad, 0xf0, 0x04, 0x0e, 0xf2, 0xc7, 0x11, 0x04, + 0xa8, 0x02, 0x00, 0x00, 0xad, 0xf1, 0x0a, 0x11, + 0x04, 0xf3, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x18, + 0xcb, 0xce, 0xa5, 0xf0, 0x0d, 0xd7, 0xcb, 0x46, + 0xcc, 0xab, 0xf0, 0x06, 0x92, 0x00, 0x0e, 0xf2, + 0xa4, 0xbb, 0xc8, 0x08, 0x0e, 0xf2, 0x9e, 0x11, + 0x04, 0xca, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x44, + 0xcb, 0xce, 0xa5, 0xf0, 0x13, 0xd7, 0xcb, 0x46, + 0x04, 0x87, 0x00, 0x00, 0x00, 0xab, 0xf0, 0x08, + 0xc7, 0x0d, 0xf4, 0x0e, 0xf3, 0xdc, 0x00, 0xcb, + 0xce, 0xa5, 0xf0, 0x13, 0xd7, 0xcb, 0x46, 0x04, + 0xca, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x08, 0xc7, + 0x0e, 0xf4, 0x0e, 0xf3, 0xc5, 0x00, 0xc7, 0x08, + 0xf0, 0x0b, 0xc7, 0x10, 0xf4, 0x0e, 0xba, 0xc8, + 0x08, 0xf3, 0xb7, 0x00, 0xbb, 0xc8, 0x08, 0x0e, + 0xf3, 0x53, 0xff, 0x11, 0x04, 0xc6, 0x01, 0x00, + 0x00, 0xad, 0xf1, 0x13, 0x11, 0x04, 0xc7, 0x01, + 0x00, 0x00, 0xad, 0xf1, 0x0a, 0x11, 0x04, 0xc8, + 0x01, 0x00, 0x00, 0xad, 0xf0, 0x0c, 0xc7, 0x0f, + 0xcc, 0xf5, 0x0e, 0xba, 0xc8, 0x08, 0xf3, 0x8a, + 0x00, 0x11, 0x04, 0xdf, 0x01, 0x00, 0x00, 0xad, + 0xf1, 0x13, 0x11, 0x04, 0xed, 0x01, 0x00, 0x00, + 0xad, 0xf1, 0x0a, 0x11, 0x04, 0x30, 0x02, 0x00, + 0x00, 0xad, 0xf0, 0x0f, 0xbb, 0xc8, 0x08, 0x92, + 0x06, 0xc7, 0x0a, 0xcc, 0xf5, 0x0e, 0x0e, 0xf3, + 0x04, 0xff, 0x11, 0x04, 0xe0, 0x01, 0x00, 0x00, + 0xad, 0xf1, 0x13, 0x11, 0x04, 0xc9, 0x01, 0x00, + 0x00, 0xad, 0xf1, 0x0a, 0x11, 0x04, 0x31, 0x02, + 0x00, 0x00, 0xad, 0xf0, 0x25, 0xba, 0xc8, 0x08, + 0xc7, 0x06, 0xba, 0xa7, 0xf0, 0x13, 0xe4, 0xc7, + 0x0b, 0xf4, 0xcc, 0xf6, 0xf0, 0x0b, 0x91, 0x06, + 0xc7, 0x0c, 0xf4, 0x0e, 0x0e, 0xf3, 0xce, 0xfe, + 0x04, 0x37, 0x00, 0x00, 0x00, 0xc8, 0x04, 0xf2, + 0x21, 0xe5, 0xcc, 0xf5, 0xf0, 0x0a, 0xc7, 0x11, + 0xf4, 0x0e, 0xba, 0xc8, 0x08, 0xf2, 0x13, 0xe3, + 0xcc, 0xf5, 0xf0, 0x07, 0xc7, 0x15, 0xf4, 0x0e, + 0xf2, 0x08, 0xbb, 0xc8, 0x08, 0x0e, 0xf3, 0xa5, + 0xfe, 0x0e, 0xc7, 0x04, 0x68, 0x9f, 0xfe, 0xff, + 0xff, 0xc7, 0x16, 0xcd, 0xcb, 0xf6, 0x0e, 0xf3, + 0x94, 0xfe, 0xc7, 0x16, 0xce, 0xce, 0xf6, 0x0e, + 0xc7, 0x05, 0xc7, 0x06, 0xc7, 0x09, 0x26, 0x03, + 0x00, 0x28, 0x0c, 0x43, 0x02, 0x01, 0xec, 0x05, + 0x01, 0x02, 0x01, 0x04, 0x00, 0x02, 0x00, 0x9d, + 0x01, 0x03, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xd2, + 0x0a, 0x00, 0x00, 0x00, 0xd4, 0x0a, 0x00, 0x01, + 0x00, 0xec, 0x03, 0x00, 0x1a, 0xee, 0x03, 0x01, + 0x1a, 0x64, 0x00, 0x00, 0x41, 0xab, 0x02, 0x00, + 0x00, 0x04, 0xac, 0x02, 0x00, 0x00, 0x24, 0x01, + 0x00, 0xd3, 0xf0, 0x16, 0xcb, 0xba, 0x46, 0x04, + 0xca, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x0b, 0xcb, + 0x04, 0xca, 0x01, 0x00, 0x00, 0x9c, 0xd7, 0x9c, + 0x28, 0x64, 0x00, 0x00, 0x41, 0xab, 0x02, 0x00, + 0x00, 0x04, 0xad, 0x02, 0x00, 0x00, 0x24, 0x01, + 0x00, 0xd0, 0x64, 0x01, 0x00, 0x40, 0xae, 0x02, + 0x00, 0x00, 0x04, 0xaf, 0x02, 0x00, 0x00, 0xad, + 0xf0, 0x0c, 0xcc, 0xf0, 0x09, 0xcc, 0x04, 0xb0, + 0x02, 0x00, 0x00, 0x9c, 0xcf, 0x64, 0x01, 0x00, + 0x41, 0xb1, 0x02, 0x00, 0x00, 0xcb, 0x04, 0xca, + 0x01, 0x00, 0x00, 0x9c, 0x24, 0x01, 0x00, 0xbb, + 0x46, 0xba, 0xad, 0xf0, 0x0b, 0xcb, 0x04, 0xca, + 0x01, 0x00, 0x00, 0x9c, 0xd7, 0x9c, 0x28, 0xcc, + 0x11, 0xf1, 0x1b, 0x0e, 0x64, 0x00, 0x00, 0x41, + 0xab, 0x02, 0x00, 0x00, 0x04, 0xb2, 0x02, 0x00, + 0x00, 0x24, 0x01, 0x00, 0x11, 0xf1, 0x07, 0x0e, + 0x04, 0xbe, 0x01, 0x00, 0x00, 0x04, 0xb3, 0x02, + 0x00, 0x00, 0x9c, 0xd7, 0x9c, 0x28, 0x0c, 0x43, + 0x02, 0x01, 0xee, 0x05, 0x00, 0x03, 0x00, 0x05, + 0x00, 0x03, 0x00, 0x67, 0x03, 0xf6, 0x06, 0x00, + 0x00, 0x00, 0xe8, 0x0a, 0x00, 0x01, 0x00, 0xea, + 0x09, 0x05, 0x00, 0x03, 0x92, 0x04, 0x1c, 0x00, + 0xec, 0x03, 0x00, 0x1a, 0xec, 0x05, 0x89, 0x01, + 0x00, 0xe3, 0x41, 0xbf, 0x01, 0x00, 0x00, 0xc3, + 0x18, 0xfc, 0x24, 0x01, 0x00, 0x41, 0x63, 0x00, + 0x00, 0x00, 0x04, 0xa4, 0x01, 0x00, 0x00, 0x24, + 0x01, 0x00, 0x41, 0x5a, 0x02, 0x00, 0x00, 0x24, + 0x00, 0x00, 0xd3, 0xf0, 0x43, 0x6b, 0x38, 0x00, + 0x00, 0x00, 0x64, 0x01, 0x00, 0x41, 0xb5, 0x02, + 0x00, 0x00, 0xe5, 0x04, 0xb6, 0x02, 0x00, 0x00, + 0xf5, 0x04, 0x48, 0x02, 0x00, 0x00, 0x24, 0x02, + 0x00, 0xd4, 0x41, 0x9d, 0x01, 0x00, 0x00, 0xcb, + 0x04, 0xa4, 0x01, 0x00, 0x00, 0x9c, 0x24, 0x01, + 0x00, 0x0e, 0xcc, 0x41, 0xb7, 0x02, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x0e, 0x0e, 0x29, 0xd1, 0x6b, + 0x06, 0x00, 0x00, 0x00, 0x0e, 0x29, 0x30, 0x29, + 0x0c, 0x43, 0x02, 0x01, 0xf0, 0x05, 0x00, 0x01, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x2f, 0x01, 0x92, + 0x06, 0x00, 0x00, 0x00, 0xec, 0x03, 0x00, 0x1a, + 0xec, 0x05, 0x89, 0x01, 0x00, 0x92, 0x04, 0x1c, + 0x00, 0x94, 0x04, 0x1d, 0x00, 0x64, 0x00, 0x00, + 0x41, 0xb8, 0x02, 0x00, 0x00, 0xe4, 0x04, 0xb6, + 0x02, 0x00, 0x00, 0xf5, 0x24, 0x01, 0x00, 0xd3, + 0xf0, 0x1a, 0xcb, 0x41, 0x5a, 0x02, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x41, 0x65, 0x00, 0x00, 0x00, + 0x04, 0xa4, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, + 0xed, 0xef, 0xea, 0x29, 0x0c, 0x43, 0x02, 0x01, + 0xf2, 0x05, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, + 0x02, 0x51, 0x02, 0xbc, 0x07, 0x00, 0x00, 0x00, + 0xf6, 0x06, 0x00, 0x01, 0x00, 0xec, 0x03, 0x00, + 0x1a, 0x80, 0x04, 0x13, 0x00, 0x82, 0x04, 0x14, + 0x00, 0x88, 0x04, 0x17, 0x00, 0x07, 0x16, 0x28, + 0x5c, 0x64, 0x2b, 0x29, 0x3b, 0x28, 0x5c, 0x64, + 0x2b, 0x29, 0x07, 0xa8, 0x01, 0x00, 0x00, 0x03, + 0x00, 0x4c, 0x00, 0x00, 0x00, 0x09, 0x06, 0x00, + 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, 0xff, 0xff, + 0x0c, 0x00, 0x0c, 0x01, 0x1d, 0x08, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x7f, 0x01, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, + 0x30, 0x00, 0x39, 0x00, 0x0b, 0x0d, 0x01, 0x01, + 0x3b, 0x0c, 0x02, 0x1d, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, + 0x01, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x30, + 0x00, 0x39, 0x00, 0x0b, 0x0d, 0x02, 0x0d, 0x00, + 0x0b, 0x64, 0x00, 0x00, 0x41, 0xab, 0x02, 0x00, + 0x00, 0x04, 0xb9, 0x02, 0x00, 0x00, 0x24, 0x01, + 0x00, 0xd4, 0xf0, 0x21, 0xcc, 0x41, 0xcb, 0x01, + 0x00, 0x00, 0xc4, 0x00, 0xc4, 0x01, 0x34, 0x24, + 0x01, 0x00, 0xd3, 0xf0, 0x10, 0xcb, 0xbc, 0x46, + 0x8c, 0xba, 0xae, 0xf0, 0x08, 0xe4, 0x40, 0x70, + 0x02, 0x00, 0x00, 0xe9, 0x64, 0x00, 0x00, 0x41, + 0xab, 0x02, 0x00, 0x00, 0x04, 0xba, 0x02, 0x00, + 0x00, 0x24, 0x01, 0x00, 0xd4, 0xf0, 0x0b, 0xcc, + 0xba, 0x46, 0x8c, 0xba, 0xae, 0xf0, 0x03, 0x09, + 0xea, 0x29, 0xc5, 0x00, 0xc8, 0x35, 0xc5, 0x01, + 0xc8, 0x36, 0xc5, 0x02, 0xc8, 0x37, 0xc5, 0x03, + 0xc8, 0x38, 0xc5, 0x04, 0xc8, 0x39, 0xc5, 0x05, + 0xc8, 0x3a, 0xc5, 0x06, 0xc8, 0x3b, 0xc5, 0x07, + 0xc8, 0x3c, 0xc5, 0x08, 0xc8, 0x3d, 0xc5, 0x09, + 0xc8, 0x3e, 0xc5, 0x0a, 0xc8, 0x3f, 0xc5, 0x0b, + 0xc8, 0x40, 0xc5, 0x0c, 0xc8, 0x41, 0xc5, 0x0d, + 0xc8, 0x42, 0xc5, 0x0e, 0xc8, 0x43, 0xc5, 0x0f, + 0xc8, 0x44, 0xc5, 0x10, 0xc8, 0x45, 0xc5, 0x11, + 0xc8, 0x46, 0xc5, 0x12, 0xc8, 0x47, 0xc5, 0x13, + 0xc8, 0x48, 0xc5, 0x14, 0xc8, 0x49, 0xc5, 0x15, + 0xc8, 0x4a, 0xc5, 0x16, 0xc8, 0x4b, 0xc5, 0x17, + 0xc8, 0x4c, 0xc5, 0x18, 0xc8, 0x4d, 0xc5, 0x19, + 0xc8, 0x4e, 0xc5, 0x1a, 0xc8, 0x4f, 0xc5, 0x1b, + 0xc8, 0x50, 0xc5, 0x1c, 0xc8, 0x51, 0xc5, 0x1d, + 0xc8, 0x52, 0xc5, 0x1e, 0xc8, 0x53, 0xc5, 0x1f, + 0xc8, 0x54, 0xc5, 0x20, 0xc8, 0x55, 0xc5, 0x21, + 0xc8, 0x56, 0xc5, 0x22, 0xc8, 0x57, 0xc5, 0x23, + 0xc8, 0x58, 0xc5, 0x24, 0xc8, 0x59, 0xc5, 0x25, + 0xc8, 0x5a, 0xc5, 0x26, 0xc8, 0x5b, 0xc5, 0x27, + 0xc8, 0x5c, 0xc5, 0x28, 0xc8, 0x5d, 0xc5, 0x29, + 0xc8, 0x5e, 0xc5, 0x2a, 0xc8, 0x5f, 0xc5, 0x2b, + 0xc8, 0x60, 0xc5, 0x2c, 0xc8, 0x61, 0xc5, 0x2d, + 0xc8, 0x62, 0xc5, 0x2e, 0xc8, 0x63, 0xc5, 0x2f, + 0xc8, 0x64, 0xc5, 0x30, 0xc8, 0x65, 0xc5, 0x31, + 0xc8, 0x66, 0xc5, 0x32, 0xc8, 0x67, 0xc5, 0x33, + 0xc8, 0x68, 0xc5, 0x34, 0xc8, 0x69, 0xc5, 0x35, + 0xc8, 0x6a, 0xc5, 0x36, 0xc8, 0x6b, 0xc5, 0x37, + 0xc8, 0x6c, 0xc5, 0x38, 0xc8, 0x6e, 0xc5, 0x39, + 0xc8, 0x72, 0xc5, 0x3a, 0xc8, 0x73, 0xc5, 0x3b, + 0xc8, 0x74, 0xc5, 0x3c, 0xc8, 0x75, 0xc5, 0x3d, + 0xc8, 0x76, 0xc5, 0x3e, 0xc8, 0x77, 0xc5, 0x40, + 0xc8, 0x79, 0xc5, 0x41, 0xc8, 0x7a, 0xc5, 0x42, + 0xc8, 0x7b, 0xc5, 0x43, 0xc8, 0x7c, 0xc5, 0x44, + 0xc8, 0x7d, 0xc5, 0x45, 0xc8, 0x7e, 0xc5, 0x51, + 0xc8, 0x80, 0xc5, 0x52, 0xc8, 0x81, 0xc5, 0x53, + 0xc8, 0x82, 0xc5, 0x54, 0xc8, 0x83, 0xc5, 0x55, + 0xc8, 0x84, 0xc5, 0x56, 0xc8, 0x85, 0xc5, 0x57, + 0xc8, 0x86, 0xc5, 0x58, 0xc8, 0x87, 0xc5, 0x59, + 0xc8, 0x88, 0xc5, 0x5a, 0xc8, 0x89, 0xc5, 0x5b, + 0xc8, 0x8a, 0xc5, 0x5c, 0xc8, 0x8b, 0xc5, 0x5d, + 0xc8, 0x8c, 0xd7, 0x64, 0x02, 0x00, 0x42, 0xf8, + 0x00, 0x00, 0x00, 0xd7, 0x64, 0x01, 0x00, 0x42, + 0xf7, 0x00, 0x00, 0x00, 0xd7, 0x64, 0x00, 0x00, + 0x42, 0xf6, 0x00, 0x00, 0x00, 0xd7, 0x40, 0x9e, + 0x00, 0x00, 0x00, 0xcf, 0xd7, 0x40, 0xa2, 0x00, + 0x00, 0x00, 0xd0, 0xd7, 0x40, 0xa1, 0x00, 0x00, + 0x00, 0xd1, 0xd7, 0x40, 0xa3, 0x00, 0x00, 0x00, + 0xd2, 0xd7, 0x40, 0xbc, 0x00, 0x00, 0x00, 0xc8, + 0x04, 0xd7, 0x40, 0xb1, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xd7, 0x40, 0x9f, 0x00, 0x00, 0x00, 0xc8, + 0x06, 0xd7, 0x40, 0xa8, 0x00, 0x00, 0x00, 0xc8, + 0x07, 0xd7, 0x40, 0xac, 0x00, 0x00, 0x00, 0xc8, + 0x08, 0xd7, 0x40, 0xa0, 0x00, 0x00, 0x00, 0xc8, + 0x09, 0xd7, 0x40, 0xa4, 0x00, 0x00, 0x00, 0xc8, + 0x0a, 0xd7, 0x40, 0xa6, 0x00, 0x00, 0x00, 0xc8, + 0x0b, 0xd7, 0x40, 0xa7, 0x00, 0x00, 0x00, 0xc8, + 0x0c, 0xd7, 0x40, 0xfa, 0x00, 0x00, 0x00, 0xc8, + 0x0d, 0xd7, 0x40, 0xfb, 0x00, 0x00, 0x00, 0xc8, + 0x0e, 0xd7, 0x40, 0xfc, 0x00, 0x00, 0x00, 0xc8, + 0x0f, 0xd7, 0x40, 0xfd, 0x00, 0x00, 0x00, 0xc8, + 0x10, 0x04, 0xbb, 0x02, 0x00, 0x00, 0x04, 0xbc, + 0x02, 0x00, 0x00, 0x04, 0xbd, 0x02, 0x00, 0x00, + 0x04, 0xbe, 0x02, 0x00, 0x00, 0x04, 0xbf, 0x02, + 0x00, 0x00, 0x04, 0xc0, 0x02, 0x00, 0x00, 0x04, + 0xc1, 0x02, 0x00, 0x00, 0x04, 0xc2, 0x02, 0x00, + 0x00, 0x04, 0xc3, 0x02, 0x00, 0x00, 0x04, 0xc4, + 0x02, 0x00, 0x00, 0x04, 0xc5, 0x02, 0x00, 0x00, + 0x04, 0xc6, 0x02, 0x00, 0x00, 0x04, 0xc7, 0x02, + 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x04, + 0xc8, 0x02, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, + 0x00, 0x04, 0xc9, 0x02, 0x00, 0x00, 0x04, 0xca, + 0x02, 0x00, 0x00, 0x04, 0xcb, 0x02, 0x00, 0x00, + 0x04, 0xcc, 0x02, 0x00, 0x00, 0x04, 0xcd, 0x02, + 0x00, 0x00, 0x26, 0x15, 0x00, 0xc8, 0x11, 0x0b, + 0x04, 0xce, 0x02, 0x00, 0x00, 0x4b, 0x9e, 0x01, + 0x00, 0x00, 0x04, 0xcf, 0x02, 0x00, 0x00, 0x4b, + 0xd0, 0x02, 0x00, 0x00, 0x04, 0xd1, 0x02, 0x00, + 0x00, 0x4b, 0xd2, 0x02, 0x00, 0x00, 0x04, 0xd3, + 0x02, 0x00, 0x00, 0x4b, 0xd4, 0x02, 0x00, 0x00, + 0x04, 0xd5, 0x02, 0x00, 0x00, 0x4b, 0xd6, 0x02, + 0x00, 0x00, 0x04, 0xd7, 0x02, 0x00, 0x00, 0x4b, + 0xd8, 0x02, 0x00, 0x00, 0x04, 0xd9, 0x02, 0x00, + 0x00, 0x4b, 0xda, 0x02, 0x00, 0x00, 0x04, 0xdb, + 0x02, 0x00, 0x00, 0x4b, 0xdc, 0x02, 0x00, 0x00, + 0x04, 0xdd, 0x02, 0x00, 0x00, 0x4b, 0xde, 0x02, + 0x00, 0x00, 0x04, 0xdf, 0x02, 0x00, 0x00, 0x4b, + 0xe0, 0x02, 0x00, 0x00, 0x04, 0xdf, 0x02, 0x00, + 0x00, 0x4b, 0xe1, 0x02, 0x00, 0x00, 0x04, 0xe2, + 0x02, 0x00, 0x00, 0x4b, 0xe3, 0x02, 0x00, 0x00, + 0x04, 0xe4, 0x02, 0x00, 0x00, 0x4b, 0xe5, 0x02, + 0x00, 0x00, 0x04, 0xe6, 0x02, 0x00, 0x00, 0x4b, + 0xe7, 0x02, 0x00, 0x00, 0x04, 0xe8, 0x02, 0x00, + 0x00, 0x4b, 0xe9, 0x02, 0x00, 0x00, 0x04, 0xea, + 0x02, 0x00, 0x00, 0x4b, 0xeb, 0x02, 0x00, 0x00, + 0x04, 0xec, 0x02, 0x00, 0x00, 0x4b, 0xed, 0x02, + 0x00, 0x00, 0x04, 0xee, 0x02, 0x00, 0x00, 0x4b, + 0xef, 0x02, 0x00, 0x00, 0xc8, 0x12, 0x0b, 0x0b, + 0x04, 0xdc, 0x02, 0x00, 0x00, 0x4b, 0x42, 0x02, + 0x00, 0x00, 0x04, 0xef, 0x02, 0x00, 0x00, 0x4b, + 0x4b, 0x00, 0x00, 0x00, 0x04, 0xde, 0x02, 0x00, + 0x00, 0x4b, 0x95, 0x02, 0x00, 0x00, 0x04, 0xda, + 0x02, 0x00, 0x00, 0x4b, 0x45, 0x02, 0x00, 0x00, + 0x04, 0xe5, 0x02, 0x00, 0x00, 0x4b, 0x16, 0x00, + 0x00, 0x00, 0x04, 0xe3, 0x02, 0x00, 0x00, 0x4b, + 0x37, 0x00, 0x00, 0x00, 0x04, 0xe7, 0x02, 0x00, + 0x00, 0x4b, 0x1b, 0x00, 0x00, 0x00, 0x04, 0xe5, + 0x02, 0x00, 0x00, 0x4b, 0x99, 0x02, 0x00, 0x00, + 0x04, 0xef, 0x02, 0x00, 0x00, 0x4b, 0x47, 0x02, + 0x00, 0x00, 0x04, 0xef, 0x02, 0x00, 0x00, 0x4b, + 0x01, 0x00, 0x00, 0x00, 0x04, 0xd4, 0x02, 0x00, + 0x00, 0x4b, 0x4a, 0x00, 0x00, 0x00, 0x04, 0xde, + 0x02, 0x00, 0x00, 0x4b, 0x44, 0x02, 0x00, 0x00, + 0x04, 0xde, 0x02, 0x00, 0x00, 0x4b, 0x3f, 0x02, + 0x00, 0x00, 0x04, 0xdc, 0x02, 0x00, 0x00, 0x4b, + 0x41, 0x02, 0x00, 0x00, 0x04, 0xed, 0x02, 0x00, + 0x00, 0x4b, 0x4c, 0x00, 0x00, 0x00, 0x04, 0xef, + 0x02, 0x00, 0x00, 0x4b, 0x4e, 0x00, 0x00, 0x00, + 0x04, 0xeb, 0x02, 0x00, 0x00, 0x4b, 0x18, 0x02, + 0x00, 0x00, 0x04, 0xef, 0x02, 0x00, 0x00, 0x4b, + 0x49, 0x00, 0x00, 0x00, 0x4b, 0x6d, 0x02, 0x00, + 0x00, 0x0b, 0x04, 0xdc, 0x02, 0x00, 0x00, 0x4b, + 0x42, 0x02, 0x00, 0x00, 0x04, 0xeb, 0x02, 0x00, + 0x00, 0x4b, 0x4b, 0x00, 0x00, 0x00, 0x04, 0xe1, + 0x02, 0x00, 0x00, 0x4b, 0x95, 0x02, 0x00, 0x00, + 0x04, 0xda, 0x02, 0x00, 0x00, 0x4b, 0x45, 0x02, + 0x00, 0x00, 0x04, 0xd0, 0x02, 0x00, 0x00, 0x4b, + 0x16, 0x00, 0x00, 0x00, 0x04, 0xd2, 0x02, 0x00, + 0x00, 0x4b, 0x37, 0x00, 0x00, 0x00, 0x04, 0xe7, + 0x02, 0x00, 0x00, 0x4b, 0x1b, 0x00, 0x00, 0x00, + 0x04, 0xd0, 0x02, 0x00, 0x00, 0x4b, 0x99, 0x02, + 0x00, 0x00, 0x04, 0xeb, 0x02, 0x00, 0x00, 0x4b, + 0x47, 0x02, 0x00, 0x00, 0x04, 0xeb, 0x02, 0x00, + 0x00, 0x4b, 0x01, 0x00, 0x00, 0x00, 0x04, 0xd4, + 0x02, 0x00, 0x00, 0x4b, 0x4a, 0x00, 0x00, 0x00, + 0x04, 0xd0, 0x02, 0x00, 0x00, 0x4b, 0x44, 0x02, + 0x00, 0x00, 0x04, 0xd0, 0x02, 0x00, 0x00, 0x4b, + 0x3f, 0x02, 0x00, 0x00, 0x04, 0xdc, 0x02, 0x00, + 0x00, 0x4b, 0x41, 0x02, 0x00, 0x00, 0x04, 0xed, + 0x02, 0x00, 0x00, 0x4b, 0x4c, 0x00, 0x00, 0x00, + 0x04, 0xe1, 0x02, 0x00, 0x00, 0x4b, 0x4e, 0x00, + 0x00, 0x00, 0x04, 0xeb, 0x02, 0x00, 0x00, 0x4b, + 0x18, 0x02, 0x00, 0x00, 0x04, 0xeb, 0x02, 0x00, + 0x00, 0x4b, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x70, + 0x02, 0x00, 0x00, 0xc9, 0x13, 0x40, 0x6d, 0x02, + 0x00, 0x00, 0xc8, 0x14, 0x0a, 0xc8, 0x15, 0x09, + 0xc8, 0x16, 0x0a, 0xc8, 0x17, 0x09, 0xc8, 0x18, + 0xbc, 0xc8, 0x19, 0x09, 0xc8, 0x1a, 0x09, 0xc8, + 0x1b, 0x26, 0x00, 0x00, 0xc8, 0x1c, 0xc6, 0xc8, + 0x1e, 0xc6, 0xc8, 0x1f, 0xc6, 0xc8, 0x20, 0xba, + 0xc8, 0x21, 0x04, 0xf0, 0x02, 0x00, 0x00, 0xc8, + 0x22, 0x04, 0xf1, 0x02, 0x00, 0x00, 0xc8, 0x23, + 0xba, 0xc8, 0x25, 0xc6, 0xc8, 0x26, 0xba, 0xc8, + 0x27, 0xc6, 0xc8, 0x28, 0xba, 0xc8, 0x29, 0xc6, + 0xc8, 0x2a, 0xba, 0xc8, 0x2b, 0x09, 0xc8, 0x2e, + 0xba, 0xc8, 0x2f, 0xba, 0xc8, 0x30, 0xba, 0xc8, + 0x34, 0x0b, 0xc7, 0x48, 0x4b, 0xf2, 0x02, 0x00, + 0x00, 0xc7, 0x4b, 0x4b, 0xf3, 0x02, 0x00, 0x00, + 0xc7, 0x66, 0x4b, 0xf4, 0x02, 0x00, 0x00, 0xc7, + 0x5a, 0x4b, 0xf5, 0x02, 0x00, 0x00, 0xc7, 0x49, + 0x4b, 0xf6, 0x02, 0x00, 0x00, 0xc7, 0x4a, 0x4b, + 0xf7, 0x02, 0x00, 0x00, 0xc7, 0x46, 0x4b, 0xf8, + 0x02, 0x00, 0x00, 0xc7, 0x5b, 0x4b, 0xf9, 0x02, + 0x00, 0x00, 0xc7, 0x6c, 0x4b, 0xa6, 0x02, 0x00, + 0x00, 0xc7, 0x51, 0x4b, 0xa4, 0x01, 0x00, 0x00, + 0xc7, 0x61, 0x4b, 0xfa, 0x02, 0x00, 0x00, 0xc7, + 0x50, 0x4b, 0xfb, 0x02, 0x00, 0x00, 0xc7, 0x51, + 0x4b, 0xa7, 0x02, 0x00, 0x00, 0xc7, 0x54, 0x4b, + 0xfc, 0x02, 0x00, 0x00, 0xc7, 0x53, 0x4b, 0xfd, + 0x02, 0x00, 0x00, 0xc7, 0x45, 0x4b, 0xfe, 0x02, + 0x00, 0x00, 0xc7, 0x47, 0x4b, 0xff, 0x02, 0x00, + 0x00, 0xc7, 0x47, 0x4b, 0x00, 0x03, 0x00, 0x00, + 0xc7, 0x5c, 0x4b, 0x01, 0x03, 0x00, 0x00, 0xc7, + 0x64, 0x4b, 0x02, 0x03, 0x00, 0x00, 0xc7, 0x67, + 0x4b, 0x03, 0x03, 0x00, 0x00, 0xc7, 0x65, 0x4b, + 0x04, 0x03, 0x00, 0x00, 0xc7, 0x53, 0x4b, 0x05, + 0x03, 0x00, 0x00, 0xc7, 0x54, 0x4b, 0x06, 0x03, + 0x00, 0x00, 0xc7, 0x4a, 0x4b, 0x07, 0x03, 0x00, + 0x00, 0xc7, 0x4b, 0x4b, 0x08, 0x03, 0x00, 0x00, + 0xc7, 0x4e, 0x4b, 0x09, 0x03, 0x00, 0x00, 0xc7, + 0x4f, 0x4b, 0x0a, 0x03, 0x00, 0x00, 0xc7, 0x4e, + 0x4b, 0x0b, 0x03, 0x00, 0x00, 0xc7, 0x4f, 0x4b, + 0x0c, 0x03, 0x00, 0x00, 0xc7, 0x48, 0x4b, 0x0d, + 0x03, 0x00, 0x00, 0xc7, 0x59, 0x4b, 0x0e, 0x03, + 0x00, 0x00, 0xc7, 0x49, 0x4b, 0x0f, 0x03, 0x00, + 0x00, 0xc7, 0x56, 0x4b, 0x10, 0x03, 0x00, 0x00, + 0xc7, 0x57, 0x4b, 0x11, 0x03, 0x00, 0x00, 0xc7, + 0x53, 0x4b, 0x12, 0x03, 0x00, 0x00, 0xc7, 0x54, + 0x4b, 0x13, 0x03, 0x00, 0x00, 0xc7, 0x4a, 0x4b, + 0x14, 0x03, 0x00, 0x00, 0xc7, 0x4b, 0x4b, 0x15, + 0x03, 0x00, 0x00, 0xc7, 0x49, 0x4b, 0x16, 0x03, + 0x00, 0x00, 0xc7, 0x48, 0x4b, 0x17, 0x03, 0x00, + 0x00, 0xc7, 0x64, 0x4b, 0x18, 0x03, 0x00, 0x00, + 0xc7, 0x4f, 0x4b, 0x19, 0x03, 0x00, 0x00, 0xc7, + 0x63, 0x4b, 0x1a, 0x03, 0x00, 0x00, 0xc7, 0x4e, + 0x4b, 0x1b, 0x03, 0x00, 0x00, 0xc7, 0x62, 0x4b, + 0x1c, 0x03, 0x00, 0x00, 0xc7, 0x5f, 0x4b, 0x1d, + 0x03, 0x00, 0x00, 0xc7, 0x5d, 0x4b, 0x1e, 0x03, + 0x00, 0x00, 0xc7, 0x5e, 0x4b, 0x1f, 0x03, 0x00, + 0x00, 0xc7, 0x5b, 0x4b, 0x20, 0x03, 0x00, 0x00, + 0xc8, 0x6d, 0x0b, 0xc9, 0x78, 0xc5, 0x3f, 0x42, + 0x56, 0x02, 0x00, 0x00, 0xcb, 0x41, 0x68, 0x00, + 0x00, 0x00, 0x0b, 0xc7, 0x7b, 0x4b, 0x68, 0x01, + 0x00, 0x00, 0xc7, 0x7c, 0x4b, 0x69, 0x01, 0x00, + 0x00, 0xc5, 0x46, 0x4c, 0x21, 0x03, 0x00, 0x00, + 0x4b, 0x21, 0x03, 0x00, 0x00, 0xc5, 0x47, 0x4c, + 0x22, 0x03, 0x00, 0x00, 0x4b, 0x22, 0x03, 0x00, + 0x00, 0xc5, 0x48, 0x4c, 0x23, 0x03, 0x00, 0x00, + 0x4b, 0x23, 0x03, 0x00, 0x00, 0xc5, 0x49, 0x4c, + 0x24, 0x03, 0x00, 0x00, 0x4b, 0x24, 0x03, 0x00, + 0x00, 0xc5, 0x4a, 0x4c, 0x55, 0x02, 0x00, 0x00, + 0x4b, 0x55, 0x02, 0x00, 0x00, 0xc5, 0x4b, 0x4c, + 0x25, 0x03, 0x00, 0x00, 0x4b, 0x25, 0x03, 0x00, + 0x00, 0xc5, 0x4c, 0x4c, 0x3e, 0x02, 0x00, 0x00, + 0x4b, 0x3e, 0x02, 0x00, 0x00, 0xc5, 0x4d, 0x4c, + 0x6d, 0x02, 0x00, 0x00, 0x4b, 0x6d, 0x02, 0x00, + 0x00, 0xc5, 0x4e, 0x4c, 0x70, 0x02, 0x00, 0x00, + 0x4b, 0x70, 0x02, 0x00, 0x00, 0xc5, 0x4f, 0x4c, + 0xb0, 0x01, 0x00, 0x00, 0x4b, 0xb0, 0x01, 0x00, + 0x00, 0xc5, 0x50, 0x4c, 0x26, 0x03, 0x00, 0x00, + 0x4b, 0x26, 0x03, 0x00, 0x00, 0x07, 0x24, 0x02, + 0x00, 0xc8, 0x7f, 0xc7, 0x8c, 0xf4, 0x0e, 0xc7, + 0x8b, 0xf4, 0x0e, 0xc7, 0x35, 0xf4, 0x0e, 0xc7, + 0x80, 0xf4, 0x29, 0x08, 0xf0, 0x02, 0x29, 0xc5, + 0x00, 0x38, 0x95, 0x00, 0x00, 0x00, 0xf5, 0x0e, + 0x06, 0x2f, +}; + diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/standalone.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/standalone.c new file mode 100755 index 00000000..2a106902 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/standalone.c @@ -0,0 +1,323 @@ +/* File generated automatically by the QuickJS-ng compiler. */ + +#include + +const uint32_t qjsc_standalone_size = 2512; + +const uint8_t qjsc_standalone[2512] = { + 0x1a, 0x64, 0x80, 0xb9, 0x26, 0x4c, 0x01, 0x1a, + 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6f, + 0x6e, 0x65, 0x2e, 0x6a, 0x73, 0x01, 0x0e, 0x71, + 0x6a, 0x73, 0x3a, 0x73, 0x74, 0x64, 0x01, 0x0c, + 0x71, 0x6a, 0x73, 0x3a, 0x6f, 0x73, 0x01, 0x12, + 0x71, 0x6a, 0x73, 0x3a, 0x62, 0x6a, 0x73, 0x6f, + 0x6e, 0x01, 0x22, 0x63, 0x6f, 0x6d, 0x70, 0x69, + 0x6c, 0x65, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, + 0x6c, 0x6f, 0x6e, 0x65, 0x01, 0x1a, 0x72, 0x75, + 0x6e, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x6c, + 0x6f, 0x6e, 0x65, 0x01, 0x06, 0x73, 0x74, 0x64, + 0x01, 0x04, 0x6f, 0x73, 0x01, 0x0a, 0x62, 0x6a, + 0x73, 0x6f, 0x6e, 0x01, 0x28, 0x4a, 0x53, 0x5f, + 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x42, 0x4a, + 0x5f, 0x42, 0x59, 0x54, 0x45, 0x43, 0x4f, 0x44, + 0x45, 0x01, 0x2a, 0x4a, 0x53, 0x5f, 0x52, 0x45, + 0x41, 0x44, 0x5f, 0x4f, 0x42, 0x4a, 0x5f, 0x52, + 0x45, 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, + 0x01, 0x2a, 0x4a, 0x53, 0x5f, 0x57, 0x52, 0x49, + 0x54, 0x45, 0x5f, 0x4f, 0x42, 0x4a, 0x5f, 0x42, + 0x59, 0x54, 0x45, 0x43, 0x4f, 0x44, 0x45, 0x01, + 0x2c, 0x4a, 0x53, 0x5f, 0x57, 0x52, 0x49, 0x54, + 0x45, 0x5f, 0x4f, 0x42, 0x4a, 0x5f, 0x52, 0x45, + 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x01, + 0x32, 0x4a, 0x53, 0x5f, 0x57, 0x52, 0x49, 0x54, + 0x45, 0x5f, 0x4f, 0x42, 0x4a, 0x5f, 0x53, 0x54, + 0x52, 0x49, 0x50, 0x5f, 0x53, 0x4f, 0x55, 0x52, + 0x43, 0x45, 0x01, 0x0e, 0x54, 0x72, 0x61, 0x69, + 0x6c, 0x65, 0x72, 0x01, 0x16, 0x65, 0x6e, 0x63, + 0x6f, 0x64, 0x65, 0x41, 0x73, 0x63, 0x69, 0x69, + 0x01, 0x16, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, + 0x41, 0x73, 0x63, 0x69, 0x69, 0x01, 0x06, 0x74, + 0x78, 0x74, 0x01, 0x02, 0x63, 0x01, 0x14, 0x63, + 0x68, 0x61, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x41, + 0x74, 0x01, 0x06, 0x6d, 0x61, 0x70, 0x01, 0x06, + 0x62, 0x75, 0x66, 0x01, 0x18, 0x66, 0x72, 0x6f, + 0x6d, 0x43, 0x68, 0x61, 0x72, 0x43, 0x6f, 0x64, + 0x65, 0x01, 0x0c, 0x69, 0x6e, 0x46, 0x69, 0x6c, + 0x65, 0x01, 0x0e, 0x6f, 0x75, 0x74, 0x46, 0x69, + 0x6c, 0x65, 0x01, 0x12, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x45, 0x78, 0x65, 0x01, 0x04, 0x6a, + 0x73, 0x01, 0x08, 0x63, 0x6f, 0x64, 0x65, 0x01, + 0x10, 0x62, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, + 0x65, 0x01, 0x16, 0x65, 0x78, 0x65, 0x46, 0x69, + 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x01, 0x06, + 0x65, 0x78, 0x65, 0x01, 0x0e, 0x65, 0x78, 0x65, + 0x53, 0x69, 0x7a, 0x65, 0x01, 0x12, 0x6e, 0x65, + 0x77, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x01, + 0x0c, 0x6e, 0x65, 0x77, 0x45, 0x78, 0x65, 0x01, + 0x04, 0x64, 0x77, 0x01, 0x0a, 0x6e, 0x65, 0x77, + 0x46, 0x64, 0x01, 0x10, 0x6c, 0x6f, 0x61, 0x64, + 0x46, 0x69, 0x6c, 0x65, 0x01, 0x1e, 0x66, 0x61, + 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, + 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x01, 0x14, 0x65, + 0x76, 0x61, 0x6c, 0x53, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x01, 0x18, 0x63, 0x6f, 0x6d, 0x70, 0x69, + 0x6c, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x01, + 0x1c, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, + 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x01, + 0x0a, 0x77, 0x72, 0x69, 0x74, 0x65, 0x01, 0x0e, + 0x65, 0x78, 0x65, 0x50, 0x61, 0x74, 0x68, 0x01, + 0x0a, 0x61, 0x72, 0x67, 0x76, 0x30, 0x01, 0x0c, + 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x01, 0x36, + 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, + 0x6f, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x65, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x3a, 0x20, 0x01, 0x0c, 0x62, 0x75, 0x66, + 0x66, 0x65, 0x72, 0x01, 0x10, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x66, 0x65, 0x72, 0x01, 0x08, 0x53, + 0x69, 0x7a, 0x65, 0x01, 0x0a, 0x4d, 0x61, 0x67, + 0x69, 0x63, 0x01, 0x12, 0x4d, 0x61, 0x67, 0x69, + 0x63, 0x53, 0x69, 0x7a, 0x65, 0x01, 0x10, 0x44, + 0x61, 0x74, 0x61, 0x53, 0x69, 0x7a, 0x65, 0x01, + 0x12, 0x73, 0x65, 0x74, 0x55, 0x69, 0x6e, 0x74, + 0x33, 0x32, 0x01, 0x08, 0x6f, 0x70, 0x65, 0x6e, + 0x01, 0x10, 0x4f, 0x5f, 0x57, 0x52, 0x4f, 0x4e, + 0x4c, 0x59, 0x01, 0x0e, 0x4f, 0x5f, 0x43, 0x52, + 0x45, 0x41, 0x54, 0x01, 0x0e, 0x4f, 0x5f, 0x54, + 0x52, 0x55, 0x4e, 0x43, 0x01, 0x22, 0x66, 0x61, + 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x01, + 0x14, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x01, 0x0a, 0x63, 0x6c, 0x6f, + 0x73, 0x65, 0x01, 0x3c, 0x66, 0x61, 0x69, 0x6c, + 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x72, + 0x69, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x6f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x01, 0x08, 0x66, 0x69, 0x6c, 0x65, + 0x01, 0x02, 0x72, 0x01, 0x0e, 0x74, 0x72, 0x61, + 0x69, 0x6c, 0x65, 0x72, 0x01, 0x0a, 0x6d, 0x61, + 0x67, 0x69, 0x63, 0x01, 0x16, 0x62, 0x79, 0x74, + 0x65, 0x63, 0x6f, 0x64, 0x65, 0x6c, 0x65, 0x6e, + 0x01, 0x04, 0x72, 0x62, 0x01, 0x08, 0x73, 0x65, + 0x65, 0x6b, 0x01, 0x10, 0x53, 0x45, 0x45, 0x4b, + 0x5f, 0x45, 0x4e, 0x44, 0x01, 0x18, 0x73, 0x65, + 0x65, 0x6b, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x3a, 0x20, 0x01, 0x08, 0x72, 0x65, 0x61, 0x64, + 0x01, 0x40, 0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, + 0x74, 0x65, 0x64, 0x20, 0x62, 0x69, 0x6e, 0x61, + 0x72, 0x79, 0x2c, 0x20, 0x6d, 0x61, 0x67, 0x69, + 0x63, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x01, 0x12, 0x67, 0x65, 0x74, 0x55, + 0x69, 0x6e, 0x74, 0x33, 0x32, 0x01, 0x14, 0x72, + 0x65, 0x61, 0x64, 0x20, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x01, 0x16, 0x65, 0x76, 0x61, 0x6c, 0x5f, + 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x01, 0x10, + 0x71, 0x75, 0x69, 0x63, 0x6b, 0x6a, 0x73, 0x32, + 0x0d, 0xe4, 0x03, 0x03, 0xe6, 0x03, 0xe8, 0x03, + 0xea, 0x03, 0x02, 0x00, 0x0b, 0xec, 0x03, 0x00, + 0x0c, 0xee, 0x03, 0x00, 0x03, 0x00, 0x8e, 0x02, + 0x00, 0x01, 0x8e, 0x02, 0x01, 0x02, 0x8e, 0x02, + 0x02, 0x00, 0x0c, 0x20, 0x02, 0x01, 0xa8, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x0d, 0x04, 0x58, + 0x00, 0xf0, 0x03, 0x00, 0x1e, 0xf2, 0x03, 0x01, + 0x1e, 0xf4, 0x03, 0x02, 0x1e, 0xf6, 0x03, 0x00, + 0x1e, 0xf8, 0x03, 0x01, 0x1e, 0xfa, 0x03, 0x02, + 0x1e, 0xfc, 0x03, 0x03, 0x1e, 0xfe, 0x03, 0x04, + 0x1e, 0x80, 0x04, 0x05, 0x1e, 0x82, 0x04, 0x06, + 0x06, 0x84, 0x04, 0x07, 0x06, 0xec, 0x03, 0x08, + 0x06, 0xee, 0x03, 0x09, 0x06, 0x0c, 0x43, 0x02, + 0x01, 0x82, 0x04, 0x01, 0x00, 0x01, 0x05, 0x00, + 0x00, 0x01, 0x1e, 0x01, 0x86, 0x04, 0x00, 0x01, + 0x00, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x03, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x88, + 0x04, 0x00, 0x01, 0x00, 0xd7, 0x41, 0x05, 0x01, + 0x00, 0x00, 0xba, 0x25, 0x01, 0x00, 0x38, 0xb1, + 0x00, 0x00, 0x00, 0x11, 0xd7, 0x41, 0x65, 0x00, + 0x00, 0x00, 0xc6, 0x24, 0x01, 0x00, 0x41, 0x06, + 0x01, 0x00, 0x00, 0xc5, 0x00, 0x24, 0x01, 0x00, + 0x21, 0x01, 0x00, 0x28, 0x0c, 0x43, 0x02, 0x01, + 0x84, 0x04, 0x01, 0x00, 0x01, 0x03, 0x00, 0x00, + 0x01, 0x21, 0x01, 0x8e, 0x04, 0x00, 0x01, 0x00, + 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x03, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x88, 0x04, + 0x00, 0x01, 0x00, 0x38, 0xa2, 0x00, 0x00, 0x00, + 0x41, 0x08, 0x01, 0x00, 0x00, 0xd7, 0x25, 0x01, + 0x00, 0x38, 0x9f, 0x00, 0x00, 0x00, 0x41, 0x83, + 0x00, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0x41, + 0x06, 0x01, 0x00, 0x00, 0xc5, 0x00, 0x24, 0x01, + 0x00, 0x41, 0x63, 0x00, 0x00, 0x00, 0xc6, 0x25, + 0x01, 0x00, 0x0c, 0x43, 0x02, 0x01, 0xec, 0x03, + 0x03, 0x0a, 0x03, 0x07, 0x00, 0x08, 0x00, 0x97, + 0x04, 0x0d, 0x92, 0x04, 0x00, 0x01, 0x00, 0x94, + 0x04, 0x00, 0x01, 0x00, 0x96, 0x04, 0x00, 0x01, + 0x00, 0x98, 0x04, 0x01, 0x00, 0x30, 0x9a, 0x04, + 0x01, 0x01, 0x30, 0x9c, 0x04, 0x01, 0x02, 0x30, + 0x9e, 0x04, 0x01, 0x03, 0x30, 0xa0, 0x04, 0x01, + 0x04, 0x30, 0xa2, 0x04, 0x01, 0x05, 0x30, 0xa4, + 0x04, 0x01, 0x06, 0x30, 0xa6, 0x04, 0x01, 0x07, + 0x30, 0xa8, 0x04, 0x01, 0x08, 0x30, 0xaa, 0x04, + 0x01, 0x09, 0x30, 0xf0, 0x03, 0x00, 0x1a, 0xf4, + 0x03, 0x02, 0x1a, 0xfa, 0x03, 0x05, 0x1a, 0xfc, + 0x03, 0x06, 0x1a, 0xfe, 0x03, 0x07, 0x1a, 0xf2, + 0x03, 0x01, 0x1a, 0x80, 0x04, 0x08, 0x1a, 0x82, + 0x04, 0x09, 0x02, 0x60, 0x09, 0x00, 0x60, 0x08, + 0x00, 0x60, 0x07, 0x00, 0x60, 0x06, 0x00, 0x60, + 0x05, 0x00, 0x60, 0x04, 0x00, 0x60, 0x03, 0x00, + 0x60, 0x02, 0x00, 0x60, 0x01, 0x00, 0x60, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x41, 0x16, 0x01, 0x00, + 0x00, 0xd7, 0x24, 0x01, 0x00, 0xcf, 0x61, 0x00, + 0x00, 0x95, 0xf0, 0x19, 0x38, 0xa0, 0x00, 0x00, + 0x00, 0x11, 0x04, 0x17, 0x01, 0x00, 0x00, 0x41, + 0x64, 0x00, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, + 0x21, 0x01, 0x00, 0x30, 0x64, 0x00, 0x00, 0x41, + 0x18, 0x01, 0x00, 0x00, 0x61, 0x00, 0x00, 0x0b, + 0x0a, 0x4b, 0x19, 0x01, 0x00, 0x00, 0x0a, 0x4b, + 0x1a, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, 0xd0, + 0x38, 0xb1, 0x00, 0x00, 0x00, 0x11, 0x64, 0x01, + 0x00, 0x41, 0x1b, 0x01, 0x00, 0x00, 0x61, 0x01, + 0x00, 0x64, 0x02, 0x00, 0x64, 0x03, 0x00, 0xa3, + 0x64, 0x04, 0x00, 0xa3, 0x24, 0x02, 0x00, 0x21, + 0x01, 0x00, 0xd1, 0xd9, 0x11, 0xaf, 0xf0, 0x1c, + 0x0e, 0x64, 0x05, 0x00, 0x41, 0x1c, 0x01, 0x00, + 0x00, 0x24, 0x00, 0x00, 0x11, 0xaf, 0xf0, 0x0c, + 0x0e, 0x38, 0x95, 0x00, 0x00, 0x00, 0x40, 0x1d, + 0x01, 0x00, 0x00, 0xd2, 0x64, 0x00, 0x00, 0x41, + 0x16, 0x01, 0x00, 0x00, 0x61, 0x03, 0x00, 0x0b, + 0x0a, 0x4b, 0x1e, 0x01, 0x00, 0x00, 0x24, 0x02, + 0x00, 0xc8, 0x04, 0x61, 0x04, 0x00, 0x95, 0xf0, + 0x1b, 0x38, 0xa0, 0x00, 0x00, 0x00, 0x11, 0x04, + 0x1f, 0x01, 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, + 0x00, 0x61, 0x03, 0x00, 0x24, 0x01, 0x00, 0x21, + 0x01, 0x00, 0x30, 0x61, 0x04, 0x00, 0xef, 0xc8, + 0x05, 0x61, 0x04, 0x00, 0x40, 0x20, 0x01, 0x00, + 0x00, 0x41, 0x21, 0x01, 0x00, 0x00, 0x61, 0x05, + 0x00, 0x61, 0x02, 0x00, 0xef, 0x9c, 0x64, 0x06, + 0x00, 0x40, 0x22, 0x01, 0x00, 0x00, 0x9c, 0x24, + 0x01, 0x00, 0xc8, 0x06, 0x38, 0xb1, 0x00, 0x00, + 0x00, 0x11, 0x61, 0x06, 0x00, 0x21, 0x01, 0x00, + 0xc8, 0x07, 0x61, 0x07, 0x00, 0x41, 0x46, 0x00, + 0x00, 0x00, 0x61, 0x02, 0x00, 0x61, 0x05, 0x00, + 0x24, 0x02, 0x00, 0x0e, 0x61, 0x07, 0x00, 0x41, + 0x46, 0x00, 0x00, 0x00, 0x5d, 0x07, 0x00, 0x64, + 0x06, 0x00, 0x40, 0x23, 0x01, 0x00, 0x00, 0xf5, + 0x61, 0x05, 0x00, 0x61, 0x02, 0x00, 0xef, 0x9c, + 0x24, 0x02, 0x00, 0x0e, 0x38, 0xbb, 0x00, 0x00, + 0x00, 0x11, 0x61, 0x06, 0x00, 0x61, 0x05, 0x00, + 0x61, 0x02, 0x00, 0xef, 0x9c, 0x64, 0x06, 0x00, + 0x40, 0x24, 0x01, 0x00, 0x00, 0x9c, 0x64, 0x06, + 0x00, 0x40, 0x25, 0x01, 0x00, 0x00, 0x21, 0x03, + 0x00, 0xc8, 0x08, 0x61, 0x08, 0x00, 0x41, 0x26, + 0x01, 0x00, 0x00, 0xba, 0x61, 0x02, 0x00, 0xef, + 0x0a, 0x24, 0x03, 0x00, 0x0e, 0x64, 0x05, 0x00, + 0x41, 0x27, 0x01, 0x00, 0x00, 0xd8, 0x64, 0x05, + 0x00, 0x40, 0x28, 0x01, 0x00, 0x00, 0x64, 0x05, + 0x00, 0x40, 0x29, 0x01, 0x00, 0x00, 0xa3, 0x64, + 0x05, 0x00, 0x40, 0x2a, 0x01, 0x00, 0x00, 0xa3, + 0xc3, 0xed, 0x01, 0x24, 0x03, 0x00, 0xc8, 0x09, + 0x61, 0x09, 0x00, 0xba, 0xa5, 0xf0, 0x19, 0x38, + 0xa0, 0x00, 0x00, 0x00, 0x11, 0x04, 0x2b, 0x01, + 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0xd8, + 0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x30, 0x64, + 0x05, 0x00, 0x41, 0x1b, 0x01, 0x00, 0x00, 0x61, + 0x09, 0x00, 0x61, 0x06, 0x00, 0xba, 0x61, 0x06, + 0x00, 0x40, 0x2c, 0x01, 0x00, 0x00, 0x24, 0x04, + 0x00, 0xba, 0xa5, 0xf0, 0x1f, 0x64, 0x05, 0x00, + 0x41, 0x2d, 0x01, 0x00, 0x00, 0x61, 0x09, 0x00, + 0x24, 0x01, 0x00, 0x0e, 0x38, 0xa0, 0x00, 0x00, + 0x00, 0x11, 0x04, 0x2e, 0x01, 0x00, 0x00, 0x21, + 0x01, 0x00, 0x30, 0x64, 0x05, 0x00, 0x41, 0x2d, + 0x01, 0x00, 0x00, 0x61, 0x09, 0x00, 0x24, 0x01, + 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xee, 0x03, + 0x00, 0x09, 0x00, 0x07, 0x00, 0x07, 0x00, 0xb5, + 0x04, 0x09, 0xde, 0x04, 0x01, 0x00, 0x30, 0xa0, + 0x04, 0x01, 0x01, 0x30, 0xe0, 0x04, 0x01, 0x02, + 0x20, 0xe2, 0x04, 0x01, 0x03, 0x30, 0xe4, 0x04, + 0x01, 0x04, 0x30, 0xa8, 0x04, 0x01, 0x05, 0x30, + 0xe6, 0x04, 0x01, 0x06, 0x30, 0x9c, 0x04, 0x01, + 0x07, 0x30, 0x9a, 0x04, 0x01, 0x08, 0x30, 0xf2, + 0x03, 0x01, 0x1a, 0xf0, 0x03, 0x00, 0x1a, 0x80, + 0x04, 0x08, 0x1a, 0x84, 0x04, 0x0a, 0x02, 0xf4, + 0x03, 0x02, 0x1a, 0xf6, 0x03, 0x03, 0x1a, 0xf8, + 0x03, 0x04, 0x1a, 0x60, 0x08, 0x00, 0x60, 0x07, + 0x00, 0x60, 0x06, 0x00, 0x60, 0x05, 0x00, 0x60, + 0x04, 0x00, 0x60, 0x03, 0x00, 0x60, 0x02, 0x00, + 0x60, 0x01, 0x00, 0x60, 0x00, 0x00, 0x64, 0x00, + 0x00, 0x41, 0x1c, 0x01, 0x00, 0x00, 0x24, 0x00, + 0x00, 0x11, 0xaf, 0xf0, 0x0c, 0x0e, 0x38, 0x95, + 0x00, 0x00, 0x00, 0x40, 0x1d, 0x01, 0x00, 0x00, + 0xcf, 0x64, 0x01, 0x00, 0x41, 0x27, 0x01, 0x00, + 0x00, 0x61, 0x00, 0x00, 0x04, 0x34, 0x01, 0x00, + 0x00, 0x24, 0x02, 0x00, 0xd0, 0x61, 0x01, 0x00, + 0x95, 0xf0, 0x1b, 0x38, 0xa0, 0x00, 0x00, 0x00, + 0x11, 0x04, 0x1f, 0x01, 0x00, 0x00, 0x41, 0x64, + 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x24, 0x01, + 0x00, 0x21, 0x01, 0x00, 0x30, 0x61, 0x01, 0x00, + 0x41, 0x35, 0x01, 0x00, 0x00, 0x64, 0x02, 0x00, + 0x40, 0x22, 0x01, 0x00, 0x00, 0x8b, 0x64, 0x01, + 0x00, 0x40, 0x36, 0x01, 0x00, 0x00, 0x24, 0x02, + 0x00, 0xd1, 0x61, 0x02, 0x00, 0xba, 0xa5, 0xf0, + 0x1c, 0x38, 0xa0, 0x00, 0x00, 0x00, 0x11, 0x04, + 0x37, 0x01, 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, + 0x00, 0x61, 0x02, 0x00, 0x8b, 0x24, 0x01, 0x00, + 0x21, 0x01, 0x00, 0x30, 0x38, 0xb1, 0x00, 0x00, + 0x00, 0x11, 0x64, 0x02, 0x00, 0x40, 0x22, 0x01, + 0x00, 0x00, 0x21, 0x01, 0x00, 0xd2, 0x61, 0x01, + 0x00, 0x41, 0x38, 0x01, 0x00, 0x00, 0x61, 0x03, + 0x00, 0x40, 0x20, 0x01, 0x00, 0x00, 0xba, 0x64, + 0x02, 0x00, 0x40, 0x22, 0x01, 0x00, 0x00, 0x24, + 0x03, 0x00, 0x0e, 0x38, 0xb1, 0x00, 0x00, 0x00, + 0x11, 0x61, 0x03, 0x00, 0x40, 0x20, 0x01, 0x00, + 0x00, 0xba, 0x64, 0x02, 0x00, 0x40, 0x24, 0x01, + 0x00, 0x00, 0x21, 0x03, 0x00, 0xc8, 0x04, 0xe6, + 0x61, 0x04, 0x00, 0xf5, 0x64, 0x02, 0x00, 0x40, + 0x23, 0x01, 0x00, 0x00, 0xae, 0xf0, 0x1c, 0x61, + 0x01, 0x00, 0x41, 0x2d, 0x01, 0x00, 0x00, 0x24, + 0x00, 0x00, 0x0e, 0x38, 0xa0, 0x00, 0x00, 0x00, + 0x11, 0x04, 0x39, 0x01, 0x00, 0x00, 0x21, 0x01, + 0x00, 0x30, 0x38, 0xbb, 0x00, 0x00, 0x00, 0x11, + 0x61, 0x03, 0x00, 0x40, 0x20, 0x01, 0x00, 0x00, + 0x64, 0x02, 0x00, 0x40, 0x24, 0x01, 0x00, 0x00, + 0x64, 0x02, 0x00, 0x40, 0x25, 0x01, 0x00, 0x00, + 0x21, 0x03, 0x00, 0xc8, 0x05, 0x61, 0x05, 0x00, + 0x41, 0x3a, 0x01, 0x00, 0x00, 0xba, 0x0a, 0x24, + 0x02, 0x00, 0xc8, 0x06, 0x38, 0xb1, 0x00, 0x00, + 0x00, 0x11, 0x61, 0x06, 0x00, 0x21, 0x01, 0x00, + 0xc8, 0x07, 0x61, 0x01, 0x00, 0x41, 0x35, 0x01, + 0x00, 0x00, 0x61, 0x06, 0x00, 0x64, 0x02, 0x00, + 0x40, 0x22, 0x01, 0x00, 0x00, 0x9c, 0x8b, 0x64, + 0x01, 0x00, 0x40, 0x36, 0x01, 0x00, 0x00, 0x24, + 0x02, 0x00, 0x11, 0x62, 0x02, 0x00, 0x0e, 0x61, + 0x02, 0x00, 0xba, 0xa5, 0xf0, 0x28, 0x61, 0x01, + 0x00, 0x41, 0x2d, 0x01, 0x00, 0x00, 0x24, 0x00, + 0x00, 0x0e, 0x38, 0xa0, 0x00, 0x00, 0x00, 0x11, + 0x04, 0x37, 0x01, 0x00, 0x00, 0x41, 0x64, 0x00, + 0x00, 0x00, 0x61, 0x02, 0x00, 0x8b, 0x24, 0x01, + 0x00, 0x21, 0x01, 0x00, 0x30, 0x61, 0x01, 0x00, + 0x41, 0x38, 0x01, 0x00, 0x00, 0x61, 0x07, 0x00, + 0x40, 0x20, 0x01, 0x00, 0x00, 0xba, 0x61, 0x07, + 0x00, 0xef, 0x24, 0x03, 0x00, 0x0e, 0x61, 0x01, + 0x00, 0x41, 0x37, 0x00, 0x00, 0x00, 0x24, 0x00, + 0x00, 0xf0, 0x1c, 0x61, 0x01, 0x00, 0x41, 0x2d, + 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, 0x0e, 0x38, + 0xa0, 0x00, 0x00, 0x00, 0x11, 0x04, 0x3b, 0x01, + 0x00, 0x00, 0x21, 0x01, 0x00, 0x30, 0x61, 0x01, + 0x00, 0x41, 0x2d, 0x01, 0x00, 0x00, 0x24, 0x00, + 0x00, 0x0e, 0x64, 0x04, 0x00, 0x41, 0x38, 0x01, + 0x00, 0x00, 0x61, 0x07, 0x00, 0x40, 0x20, 0x01, + 0x00, 0x00, 0xba, 0x61, 0x07, 0x00, 0xef, 0x64, + 0x05, 0x00, 0x64, 0x06, 0x00, 0xa3, 0x24, 0x04, + 0x00, 0xc8, 0x08, 0x64, 0x01, 0x00, 0x41, 0x18, + 0x01, 0x00, 0x00, 0x61, 0x08, 0x00, 0x0b, 0x0a, + 0x4b, 0x3c, 0x01, 0x00, 0x00, 0x25, 0x02, 0x00, + 0x08, 0xf0, 0x16, 0xc5, 0x00, 0x5e, 0x09, 0x00, + 0xc5, 0x01, 0x5e, 0x0a, 0x00, 0xc5, 0x02, 0x5e, + 0x0b, 0x00, 0xc5, 0x03, 0x5e, 0x0c, 0x00, 0x29, + 0xbb, 0xba, 0x9e, 0xea, 0xbb, 0xbd, 0x9e, 0x5e, + 0x04, 0x00, 0xbb, 0xba, 0x9e, 0x5e, 0x05, 0x00, + 0xbb, 0xbd, 0x9e, 0x5e, 0x06, 0x00, 0xbb, 0xbe, + 0x9e, 0x5e, 0x07, 0x00, 0x0b, 0x04, 0x3d, 0x01, + 0x00, 0x00, 0x4b, 0x23, 0x01, 0x00, 0x00, 0xc2, + 0x08, 0x4b, 0x24, 0x01, 0x00, 0x00, 0xbe, 0x4b, + 0x25, 0x01, 0x00, 0x00, 0xc2, 0x0c, 0x4b, 0x22, + 0x01, 0x00, 0x00, 0x5e, 0x08, 0x00, 0x06, 0x2f, +}; + diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/test_fib.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/test_fib.c new file mode 100755 index 00000000..4959e2b3 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/gen/test_fib.c @@ -0,0 +1,81 @@ +/* File generated automatically by the QuickJS-ng compiler. */ + +#include "quickjs-libc.h" + +const uint32_t qjsc_test_fib_size = 300; + +const uint8_t qjsc_test_fib[300] = { + 0x1a, 0x68, 0x46, 0x85, 0x68, 0x0e, 0x01, 0x28, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, + 0x2f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x66, 0x69, + 0x62, 0x2e, 0x6a, 0x73, 0x01, 0x0c, 0x71, 0x6a, + 0x73, 0x3a, 0x6f, 0x73, 0x01, 0x04, 0x6f, 0x73, + 0x01, 0x0a, 0x69, 0x73, 0x57, 0x69, 0x6e, 0x01, + 0x06, 0x66, 0x69, 0x62, 0x01, 0x10, 0x70, 0x6c, + 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x01, 0x0a, + 0x77, 0x69, 0x6e, 0x33, 0x32, 0x01, 0x0c, 0x2e, + 0x2f, 0x66, 0x69, 0x62, 0x2e, 0x01, 0x06, 0x64, + 0x6c, 0x6c, 0x01, 0x04, 0x73, 0x6f, 0x01, 0x0e, + 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x01, + 0x06, 0x6c, 0x6f, 0x67, 0x01, 0x16, 0x48, 0x65, + 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, + 0x64, 0x01, 0x10, 0x66, 0x69, 0x62, 0x28, 0x31, + 0x30, 0x29, 0x3d, 0x0d, 0xe4, 0x03, 0x01, 0xe6, + 0x03, 0x00, 0x00, 0x01, 0x00, 0x8e, 0x02, 0x00, + 0x01, 0x0c, 0x20, 0x0a, 0x01, 0xa8, 0x01, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x74, 0x00, + 0xe8, 0x03, 0x00, 0x1e, 0xea, 0x03, 0x00, 0x1e, + 0xec, 0x03, 0x01, 0x1e, 0x08, 0xf0, 0x02, 0x29, + 0x64, 0x00, 0x00, 0x40, 0xf7, 0x00, 0x00, 0x00, + 0x04, 0xf8, 0x00, 0x00, 0x00, 0xad, 0xe8, 0x06, + 0x11, 0xf8, 0xf1, 0x0b, 0x70, 0x41, 0xf6, 0x00, + 0x00, 0x00, 0xe9, 0x0e, 0xf2, 0x25, 0x0e, 0x04, + 0xf9, 0x00, 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, + 0x00, 0x64, 0x01, 0x00, 0xf0, 0x08, 0x04, 0xfa, + 0x00, 0x00, 0x00, 0xf2, 0x06, 0x04, 0xfb, 0x00, + 0x00, 0x00, 0x24, 0x01, 0x00, 0x06, 0x36, 0x8a, + 0xf2, 0xd3, 0x38, 0xfc, 0x00, 0x00, 0x00, 0x41, + 0xfd, 0x00, 0x00, 0x00, 0x04, 0xfe, 0x00, 0x00, + 0x00, 0x24, 0x01, 0x00, 0x0e, 0x38, 0xfc, 0x00, + 0x00, 0x00, 0x41, 0xfd, 0x00, 0x00, 0x00, 0x04, + 0xff, 0x00, 0x00, 0x00, 0x64, 0x02, 0x00, 0xc2, + 0x0a, 0xf5, 0x24, 0x02, 0x00, 0x0e, 0x06, 0x2f, + 0xe4, 0x03, 0x01, 0x01, 0x0e, 0x41, 0x3c, 0x00, + 0x3a, 0x06, 0x3b, 0x34, 0x10, 0x30, 0x0f, 0x34, + 0x10, 0x2a, 0x20, 0x00, +}; + +static JSContext *JS_NewCustomContext(JSRuntime *rt) +{ + JSContext *ctx = JS_NewContext(rt); + if (!ctx) + return NULL; + { + extern JSModuleDef *js_init_module_os(JSContext *ctx, const char *name); + js_init_module_os(ctx, "qjs:os"); + } + return ctx; +} + +int main(int argc, char **argv) +{ + int r; + JSRuntime *rt; + JSContext *ctx; + r = 0; + rt = JS_NewRuntime(); + js_std_set_worker_new_context_func(JS_NewCustomContext); + js_std_init_handlers(rt); + JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL); + ctx = JS_NewCustomContext(rt); + js_std_add_helpers(ctx, argc, argv); + js_std_eval_binary(ctx, qjsc_test_fib, qjsc_test_fib_size, 0); + r = js_std_loop(ctx); + if (r) { + js_std_dump_error(ctx); + } + js_std_free_handlers(rt); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return r; +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libregexp.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libregexp.c index ac60650c..ec558a41 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libregexp.c +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libregexp.c @@ -31,6 +31,10 @@ #include "cutils.h" #include "libregexp.h" +#if defined(__sun) +#include +#endif + /* TODO: @@ -116,7 +120,7 @@ static inline int lre_is_digit(int c) { /* insert 'len' bytes at position 'pos'. Return < 0 if error. */ static int dbuf_insert(DynBuf *s, int pos, int len) { - if (dbuf_realloc(s, s->size + len)) + if (dbuf_claim(s, len)) return -1; memmove(s->buf + pos + len, s->buf + pos, s->size - pos); s->size += len; @@ -837,7 +841,9 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp) const char *s = verboten; int n = 1; do { - if (!memcmp(s, p, n)) + // not memcmp because some implementations compare word instead + // of byte at a time and will happily read past end of input + if (!strncmp(s, (const char *)p, n)) if (p[n] == ']') goto invalid_class_range; s += n; @@ -1694,7 +1700,7 @@ static int re_parse_alternative(REParseState *s, bool is_backward_dir) speed is not really critical here) */ end = s->byte_code.size; term_size = end - term_start; - if (dbuf_realloc(&s->byte_code, end + term_size)) + if (dbuf_claim(&s->byte_code, term_size)) return -1; memmove(s->byte_code.buf + start + term_size, s->byte_code.buf + start, @@ -2244,7 +2250,8 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, case REOP_save_start: case REOP_save_end: val = *pc++; - assert(val < s->capture_count); + if (val >= s->capture_count) + return LRE_RET_BYTECODE_ERROR; capture[2 * val + opcode - REOP_save_start] = (uint8_t *)cptr; break; case REOP_save_reset: @@ -2253,7 +2260,8 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, val = pc[0]; val2 = pc[1]; pc += 2; - assert(val2 < s->capture_count); + if (val2 >= s->capture_count) + return LRE_RET_BYTECODE_ERROR; while (val <= val2) { capture[2 * val] = NULL; capture[2 * val + 1] = NULL; @@ -2546,80 +2554,6 @@ const char *lre_get_groupnames(const uint8_t *bc_buf) return (const char *)(bc_buf + RE_HEADER_LEN + re_bytecode_len); } -void lre_byte_swap(uint8_t *buf, size_t len, bool is_byte_swapped) -{ - uint8_t *p, *pe; - uint32_t n, r, nw; - - p = buf; - if (len < RE_HEADER_LEN) - abort(); - - // format is: - //
- // - // - // - // etc. - inplace_bswap16(&p[RE_HEADER_FLAGS]); - - n = get_u32(&p[RE_HEADER_BYTECODE_LEN]); - inplace_bswap32(&p[RE_HEADER_BYTECODE_LEN]); - if (is_byte_swapped) - n = bswap32(n); - if (n > len - RE_HEADER_LEN) - abort(); - - p = &buf[RE_HEADER_LEN]; - pe = &p[n]; - - while (p < pe) { - n = reopcode_info[*p].size; - switch (n) { - case 1: - case 2: - break; - case 3: - switch (*p) { - case REOP_save_reset: // has two 8 bit arguments - break; - case REOP_range32: // variable length - nw = get_u16(&p[1]); // number of pairs of uint32_t - if (is_byte_swapped) - n = bswap16(n); - for (r = 3 + 8 * nw; n < r; n += 4) - inplace_bswap32(&p[n]); - goto doswap16; - case REOP_range: // variable length - nw = get_u16(&p[1]); // number of pairs of uint16_t - if (is_byte_swapped) - n = bswap16(n); - for (r = 3 + 4 * nw; n < r; n += 2) - inplace_bswap16(&p[n]); - goto doswap16; - default: - doswap16: - inplace_bswap16(&p[1]); - break; - } - break; - case 5: - inplace_bswap32(&p[1]); - break; - case 17: - assert(*p == REOP_simple_greedy_quant); - inplace_bswap32(&p[1]); - inplace_bswap32(&p[5]); - inplace_bswap32(&p[9]); - inplace_bswap32(&p[13]); - break; - default: - abort(); - } - p = &p[n]; - } -} - #ifdef TEST bool lre_check_stack_overflow(void *opaque, size_t alloca_size) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libregexp.h b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libregexp.h index 898e9a7a..7d24c114 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libregexp.h +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libregexp.h @@ -43,8 +43,9 @@ extern "C" { #define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */ #define LRE_FLAG_UNICODE_SETS (1 << 8) -#define LRE_RET_MEMORY_ERROR (-1) -#define LRE_RET_TIMEOUT (-2) +#define LRE_RET_MEMORY_ERROR (-1) +#define LRE_RET_TIMEOUT (-2) +#define LRE_RET_BYTECODE_ERROR (-3) uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, const char *buf, size_t buf_len, int re_flags, @@ -59,8 +60,6 @@ int lre_exec(uint8_t **capture, int lre_parse_escape(const uint8_t **pp, int allow_utf16); bool lre_is_space(int c); -void lre_byte_swap(uint8_t *buf, size_t len, bool is_byte_swapped); - /* must be provided by the user */ bool lre_check_stack_overflow(void *opaque, size_t alloca_size); /* must be provided by the user, return non zero if time out */ diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libunicode-table.h b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libunicode-table.h index b48a3a74..c75e9e38 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libunicode-table.h +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libunicode-table.h @@ -87,17 +87,17 @@ static const uint32_t case_conv_table1[378] = { 0x53d50130, 0x53d58130, 0x53d60130, 0x53d68130, 0x53d70130, 0x53d80130, 0x53d88130, 0x53d90130, 0x53d98131, 0x53da1040, 0x53e20131, 0x53e28130, - 0x53e30130, 0x53e38440, 0x53e58130, 0x53e60240, - 0x53e80240, 0x53eb0640, 0x53ee0130, 0x53fa8240, - 0x55a98101, 0x55b85020, 0x7d8001b2, 0x7d8081b2, - 0x7d8101b2, 0x7d8181da, 0x7d8201da, 0x7d8281b3, - 0x7d8301b3, 0x7d8981bb, 0x7d8a01bb, 0x7d8a81bb, - 0x7d8b01bc, 0x7d8b81bb, 0x7f909a31, 0x7fa09a01, - 0x82002831, 0x82142801, 0x82582431, 0x826c2401, - 0x82b80b31, 0x82be0f31, 0x82c60731, 0x82ca0231, - 0x82cb8b01, 0x82d18f01, 0x82d98701, 0x82dd8201, - 0x86403331, 0x86603301, 0x86a81631, 0x86b81601, - 0x8c502031, 0x8c602001, 0xb7202031, 0xb7302001, + 0x53e30130, 0x53e38440, 0x53e58130, 0x53e61040, + 0x53ee0130, 0x53fa8240, 0x55a98101, 0x55b85020, + 0x7d8001b2, 0x7d8081b2, 0x7d8101b2, 0x7d8181da, + 0x7d8201da, 0x7d8281b3, 0x7d8301b3, 0x7d8981bb, + 0x7d8a01bb, 0x7d8a81bb, 0x7d8b01bc, 0x7d8b81bb, + 0x7f909a31, 0x7fa09a01, 0x82002831, 0x82142801, + 0x82582431, 0x826c2401, 0x82b80b31, 0x82be0f31, + 0x82c60731, 0x82ca0231, 0x82cb8b01, 0x82d18f01, + 0x82d98701, 0x82dd8201, 0x86403331, 0x86603301, + 0x86a81631, 0x86b81601, 0x8c502031, 0x8c602001, + 0xb7202031, 0xb7302001, 0xb7501931, 0xb75d9901, 0xf4802231, 0xf4912201, }; @@ -106,7 +106,7 @@ static const uint8_t case_conv_table2[378] = { 0x10, 0x00, 0x8f, 0x0b, 0x00, 0x00, 0x11, 0x00, 0x08, 0x00, 0x53, 0x4b, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x3b, 0x55, 0x56, 0x00, 0x58, 0x5a, - 0x40, 0x5f, 0x5e, 0x00, 0x47, 0x52, 0x63, 0x65, + 0x40, 0x5f, 0x5e, 0x00, 0x47, 0x50, 0x63, 0x65, 0x43, 0x66, 0x00, 0x68, 0x00, 0x6a, 0x00, 0x6c, 0x00, 0x6e, 0x00, 0x70, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x93, 0x00, 0x00, @@ -123,7 +123,7 @@ static const uint8_t case_conv_table2[378] = { 0x95, 0x77, 0x33, 0x95, 0x00, 0x90, 0x00, 0x76, 0x9b, 0x9a, 0x99, 0x98, 0x00, 0x00, 0xa0, 0x00, 0x9e, 0x00, 0xa3, 0xa2, 0x15, 0x31, 0x32, 0x33, - 0xb7, 0xb8, 0x55, 0xac, 0xab, 0x12, 0x14, 0x1e, + 0xb7, 0xb8, 0x53, 0xac, 0xab, 0x12, 0x14, 0x1e, 0x21, 0x22, 0x22, 0x2a, 0x34, 0x35, 0x00, 0xa8, 0xa9, 0x39, 0x22, 0x4c, 0x00, 0x00, 0x97, 0x01, 0x5a, 0xda, 0x1d, 0x36, 0x05, 0x00, 0xc7, 0xc6, @@ -143,11 +143,11 @@ static const uint8_t case_conv_table2[378] = { 0x00, 0xa5, 0xa6, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x5c, 0x00, 0x4a, 0x00, 0x5d, 0x57, 0x59, 0x62, 0x60, 0x72, 0x6b, 0x71, - 0x54, 0x00, 0x3e, 0x69, 0xbb, 0x00, 0x5b, 0x00, - 0x00, 0x00, 0x25, 0x00, 0x48, 0xaa, 0x8a, 0x8b, - 0x8c, 0xab, 0xac, 0x58, 0x58, 0xaf, 0x94, 0xb0, - 0x6f, 0xb2, 0x63, 0x62, 0x65, 0x64, 0x67, 0x66, - 0x6c, 0x6d, 0x6e, 0x6f, 0x68, 0x69, 0x6a, 0x6b, + 0x52, 0x00, 0x3e, 0x69, 0xbb, 0x00, 0x5b, 0x00, + 0x25, 0x00, 0x48, 0xaa, 0x8a, 0x8b, 0x8c, 0xab, + 0xac, 0x58, 0x58, 0xaf, 0x94, 0xb0, 0x6f, 0xb2, + 0x61, 0x60, 0x63, 0x62, 0x65, 0x64, 0x6a, 0x6b, + 0x6c, 0x6d, 0x66, 0x67, 0x68, 0x69, 0x6f, 0x6e, 0x71, 0x70, 0x73, 0x72, 0x75, 0x74, 0x77, 0x76, 0x79, 0x78, }; @@ -163,12 +163,12 @@ static const uint16_t case_conv_ext[58] = { 0x006b, 0x00e5, }; -static const uint8_t unicode_prop_Cased1_table[193] = { +static const uint8_t unicode_prop_Cased1_table[190] = { 0x40, 0xa9, 0x80, 0x8e, 0x80, 0xfc, 0x80, 0xd3, 0x80, 0x9b, 0x81, 0x8d, 0x02, 0x80, 0xe1, 0x80, 0x91, 0x85, 0x9a, 0x01, 0x00, 0x01, 0x11, 0x03, 0x04, 0x08, 0x01, 0x08, 0x30, 0x08, 0x01, 0x15, - 0x20, 0x00, 0x39, 0x99, 0x31, 0x9d, 0x84, 0x40, + 0x20, 0x01, 0x31, 0x99, 0x31, 0x9d, 0x84, 0x40, 0x94, 0x80, 0xd6, 0x82, 0xa6, 0x80, 0x41, 0x62, 0x80, 0xa6, 0x80, 0x4b, 0x72, 0x80, 0x4c, 0x02, 0xf8, 0x02, 0x80, 0x8f, 0x80, 0xb0, 0x40, 0xdb, @@ -177,27 +177,26 @@ static const uint8_t unicode_prop_Cased1_table[193] = { 0x10, 0x11, 0x02, 0x01, 0x18, 0x0b, 0x24, 0x4b, 0x26, 0x01, 0x01, 0x86, 0xe5, 0x80, 0x60, 0x79, 0xb6, 0x81, 0x40, 0x91, 0x81, 0xbd, 0x88, 0x94, - 0x05, 0x80, 0x98, 0x80, 0xa2, 0x00, 0x80, 0x9b, - 0x12, 0x82, 0x43, 0x34, 0xa2, 0x06, 0x80, 0x8d, - 0x60, 0x5c, 0x15, 0x01, 0x10, 0xa9, 0x80, 0x88, - 0x60, 0xcc, 0x44, 0xd4, 0x80, 0xc6, 0x01, 0x08, - 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, - 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, - 0x16, 0x80, 0x41, 0x53, 0x81, 0x98, 0x80, 0x98, - 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, - 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, - 0x07, 0x47, 0x33, 0x89, 0x80, 0x93, 0x2d, 0x41, - 0x04, 0xbd, 0x50, 0xc1, 0x99, 0x85, 0x99, 0x85, - 0x99, + 0x05, 0x80, 0x98, 0x80, 0xc0, 0x1a, 0x82, 0x43, + 0x34, 0xa2, 0x06, 0x80, 0x8d, 0x60, 0x5c, 0x15, + 0x01, 0x10, 0xa9, 0x80, 0x88, 0x60, 0xcc, 0x44, + 0xd4, 0x80, 0xc6, 0x01, 0x08, 0x09, 0x0b, 0x80, + 0x8b, 0x00, 0x06, 0x80, 0xc0, 0x03, 0x0f, 0x06, + 0x80, 0x9b, 0x03, 0x04, 0x00, 0x16, 0x80, 0x41, + 0x53, 0x81, 0x98, 0x80, 0x98, 0x80, 0x9e, 0x80, + 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, + 0x98, 0x80, 0x9e, 0x80, 0x98, 0x07, 0x47, 0x33, + 0x89, 0x80, 0x93, 0x2d, 0x41, 0x04, 0xbd, 0x50, + 0xc1, 0x99, 0x85, 0x99, 0x85, 0x99, }; static const uint8_t unicode_prop_Cased1_index[18] = { 0xb9, 0x02, 0x80, 0xa0, 0x1e, 0x40, 0x9e, 0xa6, - 0x40, 0xbb, 0x07, 0x01, 0xdb, 0xd6, 0x01, 0x8a, + 0x40, 0x55, 0xd4, 0x21, 0x15, 0xd7, 0x21, 0x8a, 0xf1, 0x01, }; -static const uint8_t unicode_prop_Case_Ignorable_table[764] = { +static const uint8_t unicode_prop_Case_Ignorable_table[785] = { 0xa6, 0x05, 0x80, 0x8a, 0x80, 0xa2, 0x00, 0x80, 0xc6, 0x03, 0x00, 0x03, 0x01, 0x81, 0x41, 0xf6, 0x40, 0xbf, 0x19, 0x18, 0x88, 0x08, 0x80, 0x40, @@ -230,85 +229,89 @@ static const uint8_t unicode_prop_Case_Ignorable_table[764] = { 0xc0, 0x81, 0xa1, 0x80, 0xf5, 0x13, 0x81, 0x88, 0x05, 0x82, 0x40, 0xda, 0x09, 0x80, 0xb9, 0x00, 0x30, 0x00, 0x01, 0x3d, 0x89, 0x08, 0xa6, 0x07, - 0x9e, 0xb0, 0x83, 0xaf, 0x00, 0x20, 0x04, 0x80, - 0xa7, 0x88, 0x8b, 0x81, 0x9f, 0x19, 0x08, 0x82, - 0xb7, 0x00, 0x0a, 0x00, 0x82, 0xb9, 0x39, 0x81, - 0xbf, 0x85, 0xd1, 0x10, 0x8c, 0x06, 0x18, 0x28, - 0x11, 0xb1, 0xbe, 0x8c, 0x80, 0xa1, 0xe4, 0x41, - 0xbc, 0x00, 0x82, 0x8a, 0x82, 0x8c, 0x82, 0x8c, - 0x82, 0x8c, 0x81, 0x8b, 0x27, 0x81, 0x89, 0x01, - 0x01, 0x84, 0xb0, 0x20, 0x89, 0x00, 0x8c, 0x80, - 0x8f, 0x8c, 0xb2, 0xa0, 0x4b, 0x8a, 0x81, 0xf0, - 0x82, 0xfc, 0x80, 0x8e, 0x80, 0xdf, 0x9f, 0xae, - 0x80, 0x41, 0xd4, 0x80, 0xa3, 0x1a, 0x24, 0x80, - 0xdc, 0x85, 0xdc, 0x82, 0x60, 0x6f, 0x15, 0x80, - 0x44, 0xe1, 0x85, 0x41, 0x0d, 0x80, 0xe1, 0x18, - 0x89, 0x00, 0x9b, 0x83, 0xcf, 0x81, 0x8d, 0xa1, - 0xcd, 0x80, 0x96, 0x82, 0xe6, 0x12, 0x0f, 0x02, - 0x03, 0x80, 0x98, 0x0c, 0x80, 0x40, 0x96, 0x81, - 0x99, 0x91, 0x8c, 0x80, 0xa5, 0x87, 0x98, 0x8a, - 0xad, 0x82, 0xaf, 0x01, 0x19, 0x81, 0x90, 0x80, - 0x94, 0x81, 0xc1, 0x29, 0x09, 0x81, 0x8b, 0x07, - 0x80, 0xa2, 0x80, 0x8a, 0x80, 0xb2, 0x00, 0x11, - 0x0c, 0x08, 0x80, 0x9a, 0x80, 0x8d, 0x0c, 0x08, - 0x80, 0xe3, 0x84, 0x88, 0x82, 0xf8, 0x01, 0x03, - 0x80, 0x60, 0x4f, 0x2f, 0x80, 0x40, 0x92, 0x90, - 0x42, 0x3c, 0x8f, 0x10, 0x8b, 0x8f, 0xa1, 0x01, - 0x80, 0x40, 0xa8, 0x06, 0x05, 0x80, 0x8a, 0x80, - 0xa2, 0x00, 0x80, 0xae, 0x80, 0xac, 0x81, 0xc2, - 0x80, 0x94, 0x82, 0x42, 0x00, 0x80, 0x40, 0xe1, - 0x80, 0x40, 0x94, 0x84, 0x44, 0x04, 0x28, 0xa9, - 0x80, 0x88, 0x42, 0x45, 0x10, 0x0c, 0x83, 0xa7, - 0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x83, - 0xa5, 0x80, 0x99, 0x20, 0x80, 0x41, 0x3a, 0x81, - 0xce, 0x83, 0xc5, 0x8a, 0xb0, 0x83, 0xfa, 0x80, - 0xb5, 0x8e, 0xa8, 0x01, 0x81, 0x89, 0x82, 0xb0, - 0x19, 0x09, 0x03, 0x80, 0x89, 0x80, 0xb1, 0x82, - 0xa3, 0x20, 0x87, 0xbd, 0x80, 0x8b, 0x81, 0xb3, - 0x88, 0x89, 0x19, 0x80, 0xde, 0x11, 0x00, 0x0d, - 0x01, 0x80, 0x40, 0x9c, 0x02, 0x87, 0x94, 0x81, - 0xb8, 0x0a, 0x80, 0xa4, 0x32, 0x84, 0xc5, 0x85, - 0x8c, 0x00, 0x00, 0x80, 0x8d, 0x81, 0xd4, 0x39, - 0x10, 0x80, 0x96, 0x80, 0xd3, 0x28, 0x03, 0x08, - 0x81, 0x40, 0xed, 0x1d, 0x08, 0x81, 0x9a, 0x81, - 0xd4, 0x39, 0x00, 0x81, 0xe9, 0x00, 0x01, 0x28, - 0x80, 0xe4, 0x00, 0x01, 0x18, 0x84, 0x41, 0x02, - 0x88, 0x01, 0x40, 0xff, 0x08, 0x03, 0x80, 0x40, - 0x8f, 0x19, 0x0b, 0x80, 0x9f, 0x89, 0xa7, 0x29, - 0x1f, 0x80, 0x88, 0x29, 0x82, 0xad, 0x8c, 0x01, - 0x41, 0x95, 0x30, 0x28, 0x80, 0xd1, 0x95, 0x0e, - 0x01, 0x01, 0xf9, 0x2a, 0x00, 0x08, 0x30, 0x80, - 0xc7, 0x0a, 0x00, 0x80, 0x41, 0x5a, 0x81, 0x8a, - 0x81, 0xb3, 0x24, 0x00, 0x80, 0x96, 0x80, 0x54, - 0xd4, 0x90, 0x85, 0x8e, 0x60, 0x2c, 0xc7, 0x8b, - 0x12, 0x49, 0xbf, 0x84, 0xba, 0x86, 0x88, 0x83, - 0x41, 0xfb, 0x82, 0xa7, 0x81, 0x41, 0xe1, 0x80, - 0xbe, 0x90, 0xbf, 0x08, 0x81, 0x60, 0x40, 0x0a, - 0x18, 0x30, 0x81, 0x4c, 0x9d, 0x08, 0x83, 0x52, - 0x5b, 0xad, 0x81, 0x96, 0x42, 0x1f, 0x82, 0x88, - 0x8f, 0x0e, 0x9d, 0x83, 0x40, 0x93, 0x82, 0x47, - 0xba, 0xb6, 0x83, 0xb1, 0x38, 0x8d, 0x80, 0x95, - 0x20, 0x8e, 0x45, 0x4f, 0x30, 0x90, 0x0e, 0x01, - 0x04, 0x84, 0xbd, 0xa0, 0x80, 0x40, 0x9f, 0x8d, - 0x41, 0x6f, 0x80, 0xbc, 0x83, 0x41, 0xfa, 0x84, - 0x40, 0xfd, 0x81, 0x42, 0xdf, 0x86, 0xec, 0x87, - 0x4a, 0xae, 0x84, 0x6c, 0x0c, 0x00, 0x80, 0x9d, - 0xdf, 0xff, 0x40, 0xef, + 0xad, 0x81, 0x8b, 0x93, 0x83, 0xaf, 0x00, 0x20, + 0x04, 0x80, 0xa7, 0x88, 0x8b, 0x81, 0x9f, 0x19, + 0x08, 0x82, 0xb7, 0x00, 0x0a, 0x00, 0x82, 0xb9, + 0x39, 0x81, 0xbf, 0x85, 0xd1, 0x10, 0x8c, 0x06, + 0x18, 0x28, 0x11, 0xb1, 0xbe, 0x8c, 0x80, 0xa1, + 0xe4, 0x41, 0xbc, 0x00, 0x82, 0x8a, 0x82, 0x8c, + 0x82, 0x8c, 0x82, 0x8c, 0x81, 0x8b, 0x27, 0x81, + 0x89, 0x01, 0x01, 0x84, 0xb0, 0x20, 0x89, 0x00, + 0x8c, 0x80, 0x8f, 0x8c, 0xb2, 0xa0, 0x4b, 0x8a, + 0x81, 0xf0, 0x82, 0xfc, 0x80, 0x8e, 0x80, 0xdf, + 0x9f, 0xae, 0x80, 0x41, 0xd4, 0x80, 0xa3, 0x1a, + 0x24, 0x80, 0xdc, 0x85, 0xdc, 0x82, 0x60, 0x6f, + 0x15, 0x80, 0x44, 0xe1, 0x85, 0x41, 0x0d, 0x80, + 0xe1, 0x18, 0x89, 0x00, 0x9b, 0x83, 0xcf, 0x81, + 0x8d, 0xa1, 0xcd, 0x80, 0x96, 0x82, 0xe5, 0x1a, + 0x0f, 0x02, 0x03, 0x80, 0x98, 0x0c, 0x80, 0x40, + 0x96, 0x81, 0x99, 0x91, 0x8c, 0x80, 0xa5, 0x87, + 0x98, 0x8a, 0xad, 0x82, 0xaf, 0x01, 0x19, 0x81, + 0x90, 0x80, 0x94, 0x81, 0xc1, 0x29, 0x09, 0x81, + 0x8b, 0x07, 0x80, 0xa2, 0x80, 0x8a, 0x80, 0xb2, + 0x00, 0x11, 0x0c, 0x08, 0x80, 0x9a, 0x80, 0x8d, + 0x0c, 0x08, 0x80, 0xe3, 0x84, 0x88, 0x82, 0xf8, + 0x01, 0x03, 0x80, 0x60, 0x4f, 0x2f, 0x80, 0x40, + 0x92, 0x90, 0x42, 0x3c, 0x8f, 0x10, 0x8b, 0x8f, + 0xa1, 0x01, 0x80, 0x40, 0xa8, 0x06, 0x05, 0x80, + 0x8a, 0x80, 0xa2, 0x00, 0x80, 0xae, 0x80, 0xac, + 0x81, 0xc2, 0x80, 0x94, 0x82, 0x42, 0x00, 0x80, + 0x40, 0xe1, 0x80, 0x40, 0x94, 0x84, 0x44, 0x04, + 0x28, 0xa9, 0x80, 0x88, 0x42, 0x45, 0x10, 0x0c, + 0x83, 0xa7, 0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, + 0x3c, 0x83, 0xa5, 0x80, 0x99, 0x20, 0x80, 0x41, + 0x3a, 0x81, 0x97, 0x80, 0xb3, 0x85, 0xc5, 0x8a, + 0xb0, 0x83, 0xfa, 0x80, 0xb5, 0x8e, 0xa8, 0x01, + 0x81, 0x89, 0x82, 0xb0, 0x19, 0x09, 0x03, 0x80, + 0x89, 0x80, 0xb1, 0x82, 0xa3, 0x20, 0x87, 0xbd, + 0x80, 0x8b, 0x81, 0xb3, 0x88, 0x89, 0x19, 0x80, + 0xde, 0x11, 0x00, 0x0d, 0x01, 0x80, 0x40, 0x9c, + 0x02, 0x87, 0x94, 0x81, 0xb8, 0x0a, 0x80, 0xa4, + 0x32, 0x84, 0xc5, 0x85, 0x8c, 0x00, 0x00, 0x80, + 0x8d, 0x81, 0xd4, 0x39, 0x10, 0x80, 0x96, 0x80, + 0xd3, 0x28, 0x03, 0x08, 0x81, 0x40, 0xed, 0x1d, + 0x08, 0x81, 0x9a, 0x81, 0xd4, 0x39, 0x00, 0x81, + 0xe9, 0x00, 0x01, 0x28, 0x80, 0xe4, 0x00, 0x01, + 0x18, 0x84, 0x41, 0x02, 0x88, 0x01, 0x40, 0xff, + 0x08, 0x03, 0x80, 0x40, 0x8f, 0x19, 0x0b, 0x80, + 0x9f, 0x89, 0xa7, 0x29, 0x1f, 0x80, 0x88, 0x29, + 0x82, 0xad, 0x8c, 0x01, 0x40, 0xc5, 0x00, 0x10, + 0x80, 0x40, 0xc8, 0x30, 0x28, 0x80, 0xd1, 0x95, + 0x0e, 0x01, 0x01, 0xf9, 0x2a, 0x00, 0x08, 0x30, + 0x80, 0xc7, 0x0a, 0x00, 0x80, 0xc0, 0x80, 0x41, + 0x18, 0x81, 0x8a, 0x81, 0xb3, 0x24, 0x00, 0x80, + 0x96, 0x80, 0x54, 0xd4, 0x90, 0x85, 0x8e, 0x60, + 0x2c, 0xc7, 0x8b, 0x12, 0x49, 0xbf, 0x84, 0xba, + 0x86, 0x88, 0x83, 0x41, 0xfb, 0x82, 0xa7, 0x81, + 0x41, 0xe1, 0x80, 0xbe, 0x90, 0xbf, 0x08, 0x81, + 0x8c, 0x81, 0x60, 0x3f, 0xfb, 0x18, 0x30, 0x81, + 0x4c, 0x9d, 0x08, 0x83, 0x52, 0x5b, 0xad, 0x81, + 0x96, 0x42, 0x1f, 0x82, 0x88, 0x8f, 0x0e, 0x9d, + 0x83, 0x40, 0x93, 0x82, 0x47, 0xba, 0xb6, 0x83, + 0xb1, 0x38, 0x8d, 0x80, 0x95, 0x20, 0x8e, 0x45, + 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04, 0x84, 0xbd, + 0xa0, 0x80, 0x40, 0x9f, 0x8d, 0x41, 0x6f, 0x80, + 0xbc, 0x83, 0x41, 0xfa, 0x84, 0x40, 0xfd, 0x81, + 0x40, 0xf2, 0x01, 0x06, 0x0c, 0x80, 0x88, 0x80, + 0x41, 0xcf, 0x86, 0xec, 0x87, 0x4a, 0xae, 0x84, + 0x6c, 0x0c, 0x00, 0x80, 0x9d, 0xdf, 0xff, 0x40, + 0xef, }; -static const uint8_t unicode_prop_Case_Ignorable_index[72] = { +static const uint8_t unicode_prop_Case_Ignorable_index[75] = { 0xbe, 0x05, 0x00, 0xfe, 0x07, 0x00, 0x52, 0x0a, 0xa0, 0xc1, 0x0b, 0x00, 0x82, 0x0d, 0x00, 0x3f, - 0x10, 0x80, 0xd4, 0x17, 0x40, 0xcf, 0x1a, 0x20, - 0xf5, 0x1c, 0x00, 0x80, 0x20, 0x00, 0x16, 0xa0, - 0x00, 0xc6, 0xa8, 0x00, 0xc2, 0xaa, 0x60, 0x56, - 0xfe, 0x20, 0xb1, 0x07, 0x01, 0x02, 0x10, 0x01, - 0x42, 0x12, 0x41, 0xc4, 0x14, 0x21, 0xe1, 0x19, - 0x81, 0x48, 0x1d, 0x01, 0x44, 0x6b, 0x01, 0x83, - 0xd1, 0x21, 0x3e, 0xe1, 0x01, 0xf0, 0x01, 0x0e, + 0x10, 0x80, 0xd4, 0x17, 0x40, 0xde, 0x1a, 0x20, + 0xe9, 0x1c, 0x00, 0x72, 0x20, 0x00, 0x16, 0xa0, + 0x40, 0xc6, 0xa8, 0x40, 0xc2, 0xaa, 0xa0, 0x30, + 0xfe, 0x00, 0xb1, 0x07, 0x41, 0x51, 0x0f, 0x01, + 0xd0, 0x11, 0x01, 0x5f, 0x14, 0x01, 0x44, 0x19, + 0x61, 0xa8, 0x1c, 0x01, 0x2a, 0x61, 0x61, 0xff, + 0xaf, 0x01, 0x19, 0xe0, 0x61, 0x00, 0xe7, 0x01, + 0xf0, 0x01, 0x0e, }; -static const uint8_t unicode_prop_ID_Start_table[1133] = { +static const uint8_t unicode_prop_ID_Start_table[1146] = { 0xc0, 0x99, 0x85, 0x99, 0xae, 0x80, 0x89, 0x03, 0x04, 0x96, 0x80, 0x9e, 0x80, 0x41, 0xc9, 0x83, 0x8b, 0x8d, 0x26, 0x00, 0x80, 0x40, 0x80, 0x20, @@ -319,7 +322,7 @@ static const uint8_t unicode_prop_ID_Start_table[1133] = { 0x89, 0x11, 0x80, 0x8f, 0x00, 0x9d, 0x9c, 0xd8, 0x8a, 0x80, 0x97, 0xa0, 0x88, 0x0b, 0x04, 0x95, 0x18, 0x88, 0x02, 0x80, 0x96, 0x98, 0x86, 0x8a, - 0x84, 0x97, 0x05, 0x90, 0xa9, 0xb9, 0xb5, 0x10, + 0x84, 0x97, 0x06, 0x8f, 0xa9, 0xb9, 0xb5, 0x10, 0x91, 0x06, 0x89, 0x8e, 0x8f, 0x1f, 0x09, 0x81, 0x95, 0x06, 0x00, 0x13, 0x10, 0x8f, 0x80, 0x8c, 0x08, 0x82, 0x8d, 0x81, 0x89, 0x07, 0x2b, 0x09, @@ -330,9 +333,9 @@ static const uint8_t unicode_prop_ID_Start_table[1133] = { 0x10, 0x9d, 0x08, 0x82, 0x8e, 0x80, 0x90, 0x00, 0x2a, 0x10, 0x1a, 0x08, 0x00, 0x0a, 0x0a, 0x12, 0x8b, 0x95, 0x80, 0xb3, 0x38, 0x10, 0x96, 0x80, - 0x8f, 0x10, 0x99, 0x11, 0x01, 0x81, 0x9d, 0x03, - 0x38, 0x10, 0x96, 0x80, 0x89, 0x04, 0x10, 0x9e, - 0x08, 0x81, 0x8e, 0x81, 0x90, 0x88, 0x02, 0x80, + 0x8f, 0x10, 0x99, 0x10, 0x09, 0x81, 0x9d, 0x03, + 0x38, 0x10, 0x96, 0x80, 0x89, 0x04, 0x10, 0x9d, + 0x10, 0x81, 0x8e, 0x81, 0x90, 0x88, 0x02, 0x80, 0xa8, 0x08, 0x8f, 0x04, 0x17, 0x82, 0x97, 0x2c, 0x91, 0x82, 0x97, 0x80, 0x88, 0x00, 0x0e, 0xb9, 0xaf, 0x01, 0x8b, 0x86, 0xb9, 0x08, 0x00, 0x20, @@ -368,89 +371,91 @@ static const uint8_t unicode_prop_ID_Start_table[1133] = { 0x41, 0xff, 0x59, 0xbf, 0xbf, 0x60, 0x56, 0x8c, 0xc2, 0xad, 0x81, 0x41, 0x0c, 0x82, 0x8f, 0x89, 0x81, 0x93, 0xae, 0x8f, 0x9e, 0x81, 0xcf, 0xa6, - 0x88, 0x81, 0xe6, 0x81, 0xc2, 0x09, 0x00, 0x07, - 0x94, 0x8f, 0x02, 0x03, 0x80, 0x96, 0x9c, 0xb3, - 0x8d, 0xb1, 0xbd, 0x2a, 0x00, 0x81, 0x8a, 0x9b, - 0x89, 0x96, 0x98, 0x9c, 0x86, 0xae, 0x9b, 0x80, - 0x8f, 0x20, 0x89, 0x89, 0x20, 0xa8, 0x96, 0x10, - 0x87, 0x93, 0x96, 0x10, 0x82, 0xb1, 0x00, 0x11, - 0x0c, 0x08, 0x00, 0x97, 0x11, 0x8a, 0x32, 0x8b, - 0x29, 0x29, 0x85, 0x88, 0x30, 0x30, 0xaa, 0x80, - 0x8d, 0x85, 0xf2, 0x9c, 0x60, 0x2b, 0xa3, 0x8b, - 0x96, 0x83, 0xb0, 0x60, 0x21, 0x03, 0x41, 0x6d, - 0x81, 0xe9, 0xa5, 0x86, 0x8b, 0x24, 0x00, 0x89, - 0x80, 0x8c, 0x04, 0x00, 0x01, 0x01, 0x80, 0xeb, - 0xa0, 0x41, 0x6a, 0x91, 0xbf, 0x81, 0xb5, 0xa7, - 0x8b, 0xf3, 0x20, 0x40, 0x86, 0xa3, 0x99, 0x85, - 0x99, 0x8a, 0xd8, 0x15, 0x0d, 0x0d, 0x0a, 0xa2, - 0x8b, 0x80, 0x99, 0x80, 0x92, 0x01, 0x80, 0x8e, - 0x81, 0x8d, 0xa1, 0xfa, 0xc4, 0xb4, 0x41, 0x0a, - 0x9c, 0x82, 0xb0, 0xae, 0x9f, 0x8c, 0x9d, 0x84, - 0xa5, 0x89, 0x9d, 0x81, 0xa3, 0x1f, 0x04, 0xa9, - 0x40, 0x9d, 0x91, 0xa3, 0x83, 0xa3, 0x83, 0xa7, - 0x87, 0xb3, 0x8b, 0x8a, 0x80, 0x8e, 0x06, 0x01, - 0x80, 0x8a, 0x80, 0x8e, 0x06, 0x01, 0x82, 0xb3, - 0x8b, 0x41, 0x36, 0x88, 0x95, 0x89, 0x87, 0x97, - 0x28, 0xa9, 0x80, 0x88, 0xc4, 0x29, 0x00, 0xab, - 0x01, 0x10, 0x81, 0x96, 0x89, 0x96, 0x88, 0x9e, - 0xc0, 0x92, 0x01, 0x89, 0x95, 0x89, 0x99, 0xc5, - 0xb7, 0x29, 0xbf, 0x80, 0x8e, 0x18, 0x10, 0x9c, - 0xa9, 0x9c, 0x82, 0x9c, 0xa2, 0x38, 0x9b, 0x9a, - 0xb5, 0x89, 0x95, 0x89, 0x92, 0x8c, 0x91, 0xed, - 0xc8, 0xb6, 0xb2, 0x8c, 0xb2, 0x8c, 0xa3, 0xa5, - 0x9b, 0x88, 0x96, 0x40, 0xf9, 0xa9, 0x29, 0x8f, - 0x82, 0xba, 0x9c, 0x89, 0x07, 0x95, 0xa9, 0x91, - 0xad, 0x94, 0x9a, 0x96, 0x8b, 0xb4, 0xb8, 0x09, - 0x80, 0x8c, 0xac, 0x9f, 0x98, 0x99, 0xa3, 0x9c, - 0x01, 0x07, 0xa2, 0x10, 0x8b, 0xaf, 0x8d, 0x83, - 0x94, 0x00, 0x80, 0xa2, 0x91, 0x80, 0x98, 0x92, - 0x81, 0xbe, 0x30, 0x00, 0x18, 0x8e, 0x80, 0x89, - 0x86, 0xae, 0xa5, 0x39, 0x09, 0x95, 0x06, 0x01, - 0x04, 0x10, 0x91, 0x80, 0x8b, 0x84, 0x9d, 0x89, - 0x00, 0x08, 0x80, 0xa5, 0x00, 0x98, 0x00, 0x80, - 0xab, 0xb4, 0x91, 0x83, 0x93, 0x82, 0x9d, 0xaf, - 0x93, 0x08, 0x80, 0x40, 0xb7, 0xae, 0xa8, 0x83, - 0xa3, 0xaf, 0x93, 0x80, 0xba, 0xaa, 0x8c, 0x80, - 0xc6, 0x9a, 0xa4, 0x86, 0x40, 0xb8, 0xab, 0xf3, - 0xbf, 0x9e, 0x39, 0x01, 0x38, 0x08, 0x97, 0x8e, - 0x00, 0x80, 0xdd, 0x39, 0xa6, 0x8f, 0x00, 0x80, - 0x9b, 0x80, 0x89, 0xa7, 0x30, 0x94, 0x80, 0x8a, - 0xad, 0x92, 0x80, 0x91, 0xc8, 0x40, 0xc6, 0xa0, - 0x9e, 0x88, 0x80, 0xa4, 0x90, 0x80, 0xb0, 0x9d, - 0xef, 0x30, 0x08, 0xa5, 0x94, 0x80, 0x98, 0x28, - 0x08, 0x9f, 0x8d, 0x80, 0x41, 0x46, 0x92, 0x8e, - 0x00, 0x8c, 0x80, 0xa1, 0xfb, 0x80, 0xce, 0x43, - 0x99, 0xe5, 0xee, 0x90, 0x40, 0xc3, 0x4a, 0x4b, - 0xe0, 0x8e, 0x44, 0x2f, 0x90, 0x85, 0x98, 0x4f, - 0x9a, 0x84, 0x42, 0x46, 0x5a, 0xb8, 0x9d, 0x46, - 0xe1, 0x42, 0x38, 0x86, 0x9e, 0x90, 0xce, 0x90, - 0x9d, 0x91, 0xaf, 0x8f, 0x83, 0x9e, 0x94, 0x84, - 0x92, 0x41, 0xaf, 0xac, 0x40, 0xd2, 0xbf, 0xff, - 0xca, 0x20, 0xc1, 0x8c, 0xbf, 0x08, 0x80, 0x9b, - 0x57, 0xf7, 0x87, 0x44, 0xd5, 0xa8, 0x89, 0x60, - 0x22, 0xe6, 0x18, 0x30, 0x08, 0x41, 0x22, 0x8e, - 0x80, 0x9c, 0x11, 0x80, 0x8d, 0x1f, 0x41, 0x8b, - 0x49, 0x03, 0xea, 0x84, 0x8c, 0x82, 0x88, 0x86, - 0x89, 0x57, 0x65, 0xd4, 0x80, 0xc6, 0x01, 0x08, - 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, - 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, - 0x16, 0x80, 0x41, 0x53, 0x81, 0x98, 0x80, 0x98, - 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, - 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, - 0x07, 0x47, 0x33, 0x9e, 0x2d, 0x41, 0x04, 0xbd, - 0x40, 0x91, 0xac, 0x89, 0x86, 0x8f, 0x80, 0x41, - 0x40, 0x9d, 0x91, 0xab, 0x41, 0xe3, 0x9b, 0x40, - 0xe3, 0x9d, 0x08, 0x41, 0xee, 0x30, 0x18, 0x08, - 0x8e, 0x80, 0x40, 0xc4, 0xba, 0xc3, 0x30, 0x44, - 0xb3, 0x18, 0x9a, 0x01, 0x00, 0x08, 0x80, 0x89, - 0x03, 0x00, 0x00, 0x28, 0x18, 0x00, 0x00, 0x02, - 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00, 0x80, 0x89, - 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, 0x51, 0x43, - 0x60, 0xa6, 0xdf, 0x9f, 0x50, 0x39, 0x85, 0x40, - 0xdd, 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x8e, - 0x42, 0x6d, 0x49, 0xa1, 0x42, 0x1d, 0x45, 0xe1, - 0x53, 0x4a, 0x84, 0x50, 0x5f, + 0x88, 0x81, 0xe6, 0x81, 0xd1, 0x93, 0x90, 0x02, + 0x03, 0x80, 0x96, 0x9c, 0xb3, 0x8d, 0xb1, 0xbd, + 0x2a, 0x00, 0x81, 0x8a, 0x9b, 0x89, 0x96, 0x98, + 0x9c, 0x86, 0xae, 0x9b, 0x80, 0x8f, 0x20, 0x89, + 0x89, 0x20, 0xa8, 0x96, 0x10, 0x87, 0x93, 0x96, + 0x10, 0x82, 0xb1, 0x00, 0x11, 0x0c, 0x08, 0x00, + 0x97, 0x11, 0x8a, 0x32, 0x8b, 0x29, 0x29, 0x85, + 0x88, 0x30, 0x30, 0xaa, 0x80, 0x8d, 0x85, 0xf2, + 0x9c, 0x60, 0x2b, 0xa3, 0x8b, 0x96, 0x83, 0xb0, + 0x60, 0x21, 0x03, 0x41, 0x6d, 0x81, 0xe9, 0xa5, + 0x86, 0x8b, 0x24, 0x00, 0x89, 0x80, 0x8c, 0x04, + 0x00, 0x01, 0x01, 0x80, 0xeb, 0xa0, 0x41, 0x6a, + 0x91, 0xbf, 0x81, 0xb5, 0xa7, 0x8b, 0xf3, 0x20, + 0x40, 0x86, 0xa3, 0x99, 0x85, 0x99, 0x8a, 0xd8, + 0x15, 0x0d, 0x0d, 0x0a, 0xa2, 0x8b, 0x80, 0x99, + 0x80, 0x92, 0x01, 0x80, 0x8e, 0x81, 0x8d, 0xa1, + 0xfa, 0xc4, 0xb4, 0x41, 0x0a, 0x9c, 0x82, 0xb0, + 0xae, 0x9f, 0x8c, 0x9d, 0x84, 0xa5, 0x89, 0x9d, + 0x81, 0xa3, 0x1f, 0x04, 0xa9, 0x40, 0x9d, 0x91, + 0xa3, 0x83, 0xa3, 0x83, 0xa7, 0x87, 0xb3, 0x8b, + 0x8a, 0x80, 0x8e, 0x06, 0x01, 0x80, 0x8a, 0x80, + 0x8e, 0x06, 0x01, 0x82, 0xb3, 0x8b, 0x41, 0x36, + 0x88, 0x95, 0x89, 0x87, 0x97, 0x28, 0xa9, 0x80, + 0x88, 0xc4, 0x29, 0x00, 0xab, 0x01, 0x10, 0x81, + 0x96, 0x89, 0x96, 0x88, 0x9e, 0xc0, 0x92, 0x01, + 0x89, 0x95, 0x89, 0x99, 0x85, 0x99, 0xa5, 0xb7, + 0x29, 0xbf, 0x80, 0x8e, 0x18, 0x10, 0x9c, 0xa9, + 0x9c, 0x82, 0x9c, 0xa2, 0x38, 0x9b, 0x9a, 0xb5, + 0x89, 0x95, 0x89, 0x92, 0x8c, 0x91, 0xed, 0xc8, + 0xb6, 0xb2, 0x8c, 0xb2, 0x8c, 0xa3, 0xa5, 0x9b, + 0x88, 0x96, 0x40, 0xf9, 0xa9, 0x29, 0x8f, 0x85, + 0xb7, 0x9c, 0x89, 0x07, 0x95, 0xa9, 0x91, 0xad, + 0x94, 0x9a, 0x96, 0x8b, 0xb4, 0xb8, 0x09, 0x80, + 0x8c, 0xac, 0x9f, 0x98, 0x99, 0xa3, 0x9c, 0x01, + 0x07, 0xa2, 0x10, 0x8b, 0xaf, 0x8d, 0x83, 0x94, + 0x00, 0x80, 0xa2, 0x91, 0x80, 0x98, 0x92, 0x81, + 0xbe, 0x30, 0x00, 0x18, 0x8e, 0x80, 0x89, 0x86, + 0xae, 0xa5, 0x39, 0x09, 0x95, 0x06, 0x01, 0x04, + 0x10, 0x91, 0x80, 0x8b, 0x84, 0x9d, 0x89, 0x00, + 0x08, 0x80, 0xa5, 0x00, 0x98, 0x00, 0x80, 0xab, + 0xb4, 0x91, 0x83, 0x93, 0x82, 0x9d, 0xaf, 0x93, + 0x08, 0x80, 0x40, 0xb7, 0xae, 0xa8, 0x83, 0xa3, + 0xaf, 0x93, 0x80, 0xba, 0xaa, 0x8c, 0x80, 0xc6, + 0x9a, 0xa4, 0x86, 0x40, 0xb8, 0xab, 0xf3, 0xbf, + 0x9e, 0x39, 0x01, 0x38, 0x08, 0x97, 0x8e, 0x00, + 0x80, 0xdd, 0x39, 0xa6, 0x8f, 0x00, 0x80, 0x9b, + 0x80, 0x89, 0xa7, 0x30, 0x94, 0x80, 0x8a, 0xad, + 0x92, 0x80, 0x91, 0xc8, 0x40, 0xc6, 0xa0, 0x9e, + 0x88, 0x80, 0xa4, 0x90, 0x80, 0xb0, 0x9d, 0xef, + 0x30, 0x08, 0xa5, 0x94, 0x80, 0x98, 0x28, 0x08, + 0x9f, 0x8d, 0x80, 0x96, 0xab, 0x41, 0x03, 0x92, + 0x8e, 0x00, 0x8c, 0x80, 0xa1, 0xfb, 0x80, 0xce, + 0x43, 0x99, 0xe5, 0xee, 0x90, 0x40, 0xc3, 0x4a, + 0x4b, 0xe0, 0x8e, 0x44, 0x2f, 0x90, 0x85, 0x98, + 0x4f, 0x9a, 0x84, 0x42, 0x46, 0x5a, 0xb8, 0x9d, + 0x46, 0xe1, 0x42, 0x38, 0x86, 0x9e, 0x90, 0xce, + 0x90, 0x9d, 0x91, 0xaf, 0x8f, 0x83, 0x9e, 0x94, + 0x84, 0x92, 0x41, 0xaf, 0xac, 0x40, 0xd2, 0xbf, + 0x9f, 0x98, 0x81, 0x98, 0xab, 0xca, 0x20, 0xc1, + 0x8c, 0xbf, 0x08, 0x80, 0x8d, 0x84, 0x88, 0x5c, + 0xd5, 0xa8, 0x9f, 0xe0, 0xf2, 0x60, 0x21, 0xfc, + 0x18, 0x30, 0x08, 0x41, 0x22, 0x8e, 0x80, 0x9c, + 0x11, 0x80, 0x8d, 0x1f, 0x41, 0x8b, 0x49, 0x03, + 0xea, 0x84, 0x8c, 0x82, 0x88, 0x86, 0x89, 0x57, + 0x65, 0xd4, 0x80, 0xc6, 0x01, 0x08, 0x09, 0x0b, + 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, 0x03, 0x0f, + 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, 0x16, 0x80, + 0x41, 0x53, 0x81, 0x98, 0x80, 0x98, 0x80, 0x9e, + 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, + 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x07, 0x47, + 0x33, 0x9e, 0x2d, 0x41, 0x04, 0xbd, 0x40, 0x91, + 0xac, 0x89, 0x86, 0x8f, 0x80, 0x41, 0x40, 0x9d, + 0x91, 0xab, 0x41, 0xe3, 0x9b, 0x40, 0xe3, 0x9d, + 0x08, 0x40, 0xce, 0x9e, 0x02, 0x01, 0x06, 0x0c, + 0x88, 0x81, 0x40, 0xdf, 0x30, 0x18, 0x08, 0x8e, + 0x80, 0x40, 0xc4, 0xba, 0xc3, 0x30, 0x44, 0xb3, + 0x18, 0x9a, 0x01, 0x00, 0x08, 0x80, 0x89, 0x03, + 0x00, 0x00, 0x28, 0x18, 0x00, 0x00, 0x02, 0x01, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x0b, 0x06, 0x03, 0x03, 0x00, 0x80, 0x89, 0x80, + 0x90, 0x22, 0x04, 0x80, 0x90, 0x51, 0x43, 0x60, + 0xa6, 0xdf, 0x9f, 0x51, 0x1d, 0x81, 0x56, 0x8d, + 0x81, 0x5d, 0x30, 0x8e, 0x42, 0x6d, 0x49, 0xa1, + 0x42, 0x1d, 0x45, 0xe1, 0x53, 0x4a, 0x84, 0x60, + 0x21, 0x29, }; static const uint8_t unicode_prop_ID_Start_index[108] = { @@ -459,18 +464,18 @@ static const uint8_t unicode_prop_ID_Start_index[108] = { 0x0d, 0x20, 0xc7, 0x0e, 0x20, 0x49, 0x12, 0x00, 0x9b, 0x16, 0x00, 0xac, 0x19, 0x00, 0xc0, 0x1d, 0x80, 0x80, 0x20, 0x20, 0x70, 0x2d, 0x00, 0x00, - 0x32, 0x00, 0xdd, 0xa7, 0x00, 0x4c, 0xaa, 0x20, - 0xc7, 0xd7, 0x20, 0xfc, 0xfd, 0x20, 0x9d, 0x02, - 0x21, 0x96, 0x05, 0x01, 0x9f, 0x08, 0x01, 0x49, - 0x0c, 0x21, 0x76, 0x10, 0x21, 0xa9, 0x12, 0x01, - 0xb0, 0x14, 0x01, 0x42, 0x19, 0x41, 0x90, 0x1c, - 0x01, 0xf1, 0x2f, 0x21, 0x90, 0x6b, 0x21, 0x33, - 0xb1, 0x21, 0x06, 0xd5, 0x01, 0xc3, 0xd7, 0x01, - 0xff, 0xe7, 0x21, 0x63, 0xee, 0x01, 0x5e, 0xee, - 0x42, 0xb0, 0x23, 0x03, + 0x32, 0x00, 0x06, 0xa8, 0x00, 0x77, 0xaa, 0x00, + 0xfc, 0xd7, 0x00, 0xfd, 0xfe, 0x40, 0xd1, 0x02, + 0x01, 0xb2, 0x05, 0x21, 0xf6, 0x08, 0x01, 0x49, + 0x0c, 0x01, 0x76, 0x10, 0x01, 0xdf, 0x12, 0x21, + 0xc8, 0x14, 0x41, 0x42, 0x19, 0x21, 0x31, 0x1d, + 0x61, 0xf1, 0x2f, 0x41, 0x78, 0x6b, 0x01, 0x23, + 0xb1, 0xa1, 0xad, 0xd4, 0x01, 0x6f, 0xd7, 0x01, + 0xee, 0xe5, 0x01, 0x38, 0xee, 0x01, 0xe0, 0xa6, + 0x42, 0x7a, 0x34, 0x03, }; -static const uint8_t unicode_prop_ID_Continue1_table[695] = { +static const uint8_t unicode_prop_ID_Continue1_table[708] = { 0xaf, 0x89, 0xa4, 0x80, 0xd6, 0x80, 0x42, 0x47, 0xef, 0x96, 0x80, 0x40, 0xfa, 0x84, 0x41, 0x08, 0xac, 0x00, 0x01, 0x01, 0x00, 0xc7, 0x8a, 0xaf, @@ -502,73 +507,75 @@ static const uint8_t unicode_prop_ID_Continue1_table[695] = { 0x01, 0x89, 0xa0, 0x10, 0x8a, 0x40, 0x8e, 0x80, 0xf5, 0x8b, 0x83, 0x8b, 0x89, 0x89, 0xff, 0x8a, 0xbb, 0x84, 0xb8, 0x89, 0x80, 0x9c, 0x81, 0x8a, - 0x85, 0x89, 0x95, 0x8d, 0x80, 0x8f, 0xb0, 0x84, - 0xae, 0x90, 0x8a, 0x89, 0x90, 0x88, 0x8b, 0x82, - 0x9d, 0x8c, 0x81, 0x89, 0xab, 0x8d, 0xaf, 0x93, - 0x87, 0x89, 0x85, 0x89, 0xf5, 0x10, 0x94, 0x18, - 0x28, 0x0a, 0x40, 0xc5, 0xbf, 0x42, 0x0b, 0x81, - 0xb0, 0x81, 0x92, 0x80, 0xfa, 0x8c, 0x18, 0x82, - 0x8b, 0x4b, 0xfd, 0x82, 0x40, 0x8c, 0x80, 0xdf, - 0x9f, 0x42, 0x29, 0x85, 0xe8, 0x81, 0xdf, 0x80, - 0x60, 0x75, 0x23, 0x89, 0xc4, 0x03, 0x89, 0x9f, - 0x81, 0xcf, 0x81, 0x41, 0x0f, 0x02, 0x03, 0x80, - 0x96, 0x23, 0x80, 0xd2, 0x81, 0xb1, 0x91, 0x89, - 0x89, 0x85, 0x91, 0x8c, 0x8a, 0x9b, 0x87, 0x98, - 0x8c, 0xab, 0x83, 0xae, 0x8d, 0x8e, 0x89, 0x8a, - 0x80, 0x89, 0x89, 0xae, 0x8d, 0x8b, 0x07, 0x09, - 0x89, 0xa0, 0x82, 0xb1, 0x00, 0x11, 0x0c, 0x08, - 0x80, 0xa8, 0x24, 0x81, 0x40, 0xeb, 0x38, 0x09, - 0x89, 0x60, 0x4f, 0x23, 0x80, 0x42, 0xe0, 0x8f, - 0x8f, 0x8f, 0x11, 0x97, 0x82, 0x40, 0xbf, 0x89, - 0xa4, 0x80, 0xa4, 0x80, 0x42, 0x96, 0x80, 0x40, - 0xe1, 0x80, 0x40, 0x94, 0x84, 0x41, 0x24, 0x89, - 0x45, 0x56, 0x10, 0x0c, 0x83, 0xa7, 0x13, 0x80, - 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x1f, 0x89, 0x85, - 0x89, 0x9e, 0x84, 0x41, 0x3c, 0x81, 0xce, 0x83, - 0xc5, 0x8a, 0xb0, 0x83, 0xf9, 0x82, 0xb4, 0x8e, - 0x9e, 0x8a, 0x09, 0x89, 0x83, 0xac, 0x8a, 0x30, - 0xac, 0x89, 0x2a, 0xa3, 0x8d, 0x80, 0x89, 0x21, - 0xab, 0x80, 0x8b, 0x82, 0xaf, 0x8d, 0x3b, 0x80, - 0x8b, 0xd1, 0x8b, 0x28, 0x08, 0x40, 0x9c, 0x8b, - 0x84, 0x89, 0x2b, 0xb6, 0x08, 0x31, 0x09, 0x82, - 0x88, 0x80, 0x89, 0x09, 0x32, 0x84, 0xc2, 0x88, - 0x00, 0x08, 0x03, 0x04, 0x00, 0x8d, 0x81, 0xd1, - 0x91, 0x88, 0x89, 0x18, 0xd0, 0x93, 0x8b, 0x89, - 0x40, 0xd4, 0x31, 0x88, 0x9a, 0x81, 0xd1, 0x90, - 0x8e, 0x89, 0xd0, 0x8c, 0x87, 0x89, 0x85, 0x93, - 0xb8, 0x8e, 0x83, 0x89, 0x40, 0xf1, 0x8e, 0x40, - 0xa4, 0x89, 0xc5, 0x28, 0x09, 0x18, 0x00, 0x81, - 0x8b, 0x89, 0xf6, 0x31, 0x32, 0x80, 0x9b, 0x89, - 0xa7, 0x30, 0x1f, 0x80, 0x88, 0x8a, 0xad, 0x8f, - 0x41, 0x55, 0x89, 0xb4, 0x38, 0x87, 0x8f, 0x89, - 0xb7, 0x95, 0x80, 0x8d, 0xf9, 0x2a, 0x00, 0x08, - 0x30, 0x07, 0x89, 0xaf, 0x20, 0x08, 0x27, 0x89, - 0x41, 0x48, 0x83, 0x88, 0x08, 0x80, 0xaf, 0x32, - 0x84, 0x8c, 0x8a, 0x54, 0xe4, 0x05, 0x8e, 0x60, - 0x2c, 0xc7, 0x9b, 0x49, 0x25, 0x89, 0xd5, 0x89, - 0xa5, 0x84, 0xba, 0x86, 0x98, 0x89, 0x42, 0x15, - 0x89, 0x41, 0xd4, 0x00, 0xb6, 0x33, 0xd0, 0x80, - 0x8a, 0x81, 0x60, 0x4c, 0xaa, 0x81, 0x50, 0x50, - 0x89, 0x42, 0x05, 0xad, 0x81, 0x96, 0x42, 0x1d, - 0x22, 0x2f, 0x39, 0x86, 0x9d, 0x83, 0x40, 0x93, - 0x82, 0x45, 0x88, 0xb1, 0x41, 0xff, 0xb6, 0x83, - 0xb1, 0x38, 0x8d, 0x80, 0x95, 0x20, 0x8e, 0x45, - 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04, 0xe3, 0x80, - 0x40, 0x9f, 0x86, 0x88, 0x89, 0x41, 0x63, 0x80, - 0xbc, 0x8d, 0x41, 0xf1, 0x8d, 0x40, 0xf3, 0x08, - 0x89, 0x42, 0xd4, 0x86, 0xec, 0x34, 0x89, 0x52, - 0x95, 0x89, 0x6c, 0x05, 0x05, 0x40, 0xef, + 0x85, 0x89, 0x95, 0x8d, 0x80, 0x9e, 0x81, 0x8b, + 0x93, 0x84, 0xae, 0x90, 0x8a, 0x89, 0x90, 0x88, + 0x8b, 0x82, 0x9d, 0x8c, 0x81, 0x89, 0xab, 0x8d, + 0xaf, 0x93, 0x87, 0x89, 0x85, 0x89, 0xf5, 0x10, + 0x94, 0x18, 0x28, 0x0a, 0x40, 0xc5, 0xbf, 0x42, + 0x0b, 0x81, 0xb0, 0x81, 0x92, 0x80, 0xfa, 0x8c, + 0x18, 0x82, 0x8b, 0x4b, 0xfd, 0x82, 0x40, 0x8c, + 0x80, 0xdf, 0x9f, 0x42, 0x29, 0x85, 0xe8, 0x81, + 0xdf, 0x80, 0x60, 0x75, 0x23, 0x89, 0xc4, 0x03, + 0x89, 0x9f, 0x81, 0xcf, 0x81, 0x41, 0x0f, 0x02, + 0x03, 0x80, 0x96, 0x23, 0x80, 0xd2, 0x81, 0xb1, + 0x91, 0x89, 0x89, 0x85, 0x91, 0x8c, 0x8a, 0x9b, + 0x87, 0x98, 0x8c, 0xab, 0x83, 0xae, 0x8d, 0x8e, + 0x89, 0x8a, 0x80, 0x89, 0x89, 0xae, 0x8d, 0x8b, + 0x07, 0x09, 0x89, 0xa0, 0x82, 0xb1, 0x00, 0x11, + 0x0c, 0x08, 0x80, 0xa8, 0x24, 0x81, 0x40, 0xeb, + 0x38, 0x09, 0x89, 0x60, 0x4f, 0x23, 0x80, 0x42, + 0xe0, 0x8f, 0x8f, 0x8f, 0x11, 0x97, 0x82, 0x40, + 0xbf, 0x89, 0xa4, 0x80, 0xa4, 0x80, 0x42, 0x96, + 0x80, 0x40, 0xe1, 0x80, 0x40, 0x94, 0x84, 0x41, + 0x24, 0x89, 0x45, 0x56, 0x10, 0x0c, 0x83, 0xa7, + 0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x1f, + 0x89, 0x85, 0x89, 0x9e, 0x84, 0x41, 0x3c, 0x81, + 0xcc, 0x85, 0xc5, 0x8a, 0xb0, 0x83, 0xf9, 0x82, + 0xb4, 0x8e, 0x9e, 0x8a, 0x09, 0x89, 0x83, 0xac, + 0x8a, 0x30, 0xac, 0x89, 0x2a, 0xa3, 0x8d, 0x80, + 0x89, 0x21, 0xab, 0x80, 0x8b, 0x82, 0xaf, 0x8d, + 0x3b, 0x80, 0x8b, 0xd1, 0x8b, 0x28, 0x08, 0x40, + 0x9c, 0x8b, 0x84, 0x89, 0x2b, 0xb6, 0x08, 0x31, + 0x09, 0x82, 0x88, 0x80, 0x89, 0x09, 0x32, 0x84, + 0xc2, 0x88, 0x00, 0x08, 0x03, 0x04, 0x00, 0x8d, + 0x81, 0xd1, 0x91, 0x88, 0x89, 0x18, 0xd0, 0x93, + 0x8b, 0x89, 0x40, 0xd4, 0x31, 0x88, 0x9a, 0x81, + 0xd1, 0x90, 0x8e, 0x89, 0xd0, 0x8c, 0x87, 0x89, + 0x85, 0x93, 0xb8, 0x8e, 0x83, 0x89, 0x40, 0xf1, + 0x8e, 0x40, 0xa4, 0x89, 0xc5, 0x28, 0x09, 0x18, + 0x00, 0x81, 0x8b, 0x89, 0xf6, 0x31, 0x32, 0x80, + 0x9b, 0x89, 0xa7, 0x30, 0x1f, 0x80, 0x88, 0x8a, + 0xad, 0x8f, 0x40, 0xc5, 0x87, 0x40, 0x87, 0x89, + 0xb4, 0x38, 0x87, 0x8f, 0x89, 0xb7, 0x95, 0x80, + 0x8d, 0xf9, 0x2a, 0x00, 0x08, 0x30, 0x07, 0x89, + 0xaf, 0x20, 0x08, 0x27, 0x89, 0xb5, 0x89, 0x41, + 0x08, 0x83, 0x88, 0x08, 0x80, 0xaf, 0x32, 0x84, + 0x8c, 0x8a, 0x54, 0xe4, 0x05, 0x8e, 0x60, 0x2c, + 0xc7, 0x9b, 0x49, 0x25, 0x89, 0xd5, 0x89, 0xa5, + 0x84, 0xba, 0x86, 0x98, 0x89, 0x42, 0x15, 0x89, + 0x41, 0xd4, 0x00, 0xb6, 0x33, 0xd0, 0x80, 0x8a, + 0x81, 0x60, 0x4c, 0xaa, 0x81, 0x50, 0x50, 0x89, + 0x42, 0x05, 0xad, 0x81, 0x96, 0x42, 0x1d, 0x22, + 0x2f, 0x39, 0x86, 0x9d, 0x83, 0x40, 0x93, 0x82, + 0x45, 0x88, 0xb1, 0x41, 0xff, 0xb6, 0x83, 0xb1, + 0x38, 0x8d, 0x80, 0x95, 0x20, 0x8e, 0x45, 0x4f, + 0x30, 0x90, 0x0e, 0x01, 0x04, 0xe3, 0x80, 0x40, + 0x9f, 0x86, 0x88, 0x89, 0x41, 0x63, 0x80, 0xbc, + 0x8d, 0x41, 0xf1, 0x8d, 0x40, 0xf3, 0x08, 0x89, + 0x40, 0xe7, 0x01, 0x06, 0x0c, 0x80, 0x41, 0xd9, + 0x86, 0xec, 0x34, 0x89, 0x52, 0x95, 0x89, 0x6c, + 0x05, 0x05, 0x40, 0xef, }; static const uint8_t unicode_prop_ID_Continue1_index[66] = { 0xfa, 0x06, 0x00, 0x70, 0x09, 0x00, 0xf0, 0x0a, 0x40, 0x57, 0x0c, 0x00, 0xf0, 0x0d, 0x60, 0xc7, - 0x0f, 0x20, 0xea, 0x17, 0x40, 0x05, 0x1b, 0x00, - 0x0e, 0x20, 0x00, 0xa0, 0xa6, 0x20, 0xe6, 0xa9, - 0x20, 0x10, 0xfe, 0x00, 0x40, 0x0a, 0x01, 0xc3, - 0x10, 0x01, 0x4e, 0x13, 0x01, 0x41, 0x16, 0x01, - 0x0b, 0x1a, 0x01, 0xaa, 0x1d, 0x01, 0x7a, 0x6d, - 0x21, 0x45, 0xd2, 0x21, 0xaf, 0xe2, 0x01, 0xf0, + 0x0f, 0x20, 0xea, 0x17, 0x40, 0xec, 0x1a, 0x00, + 0x0e, 0x20, 0x40, 0x7e, 0xa6, 0x20, 0xda, 0xa9, + 0x20, 0x10, 0xfe, 0x40, 0x40, 0x0a, 0x41, 0xbb, + 0x10, 0x21, 0x4e, 0x13, 0x41, 0xde, 0x15, 0x01, + 0xe5, 0x19, 0x01, 0x5a, 0x1d, 0x01, 0xf5, 0x6a, + 0x21, 0x8c, 0xd1, 0x61, 0x37, 0xe1, 0x41, 0xf0, 0x01, 0x0e, }; @@ -582,7 +589,7 @@ static const uint8_t unicode_prop_White_Space_index[3] = { 0x01, 0x30, 0x00, }; -static const uint8_t unicode_cc_table[916] = { +static const uint8_t unicode_cc_table[937] = { 0xb2, 0xcf, 0xd4, 0x00, 0xe8, 0x03, 0xdc, 0x00, 0xe8, 0x00, 0xd8, 0x04, 0xdc, 0x01, 0xca, 0x03, 0xdc, 0x01, 0xca, 0x0a, 0xdc, 0x04, 0x01, 0x03, @@ -635,83 +642,87 @@ static const uint8_t unicode_cc_table[916] = { 0xb0, 0x16, 0x00, 0x09, 0x93, 0xc7, 0x81, 0x00, 0xdc, 0xaf, 0xc4, 0x05, 0xdc, 0xc1, 0x00, 0xdc, 0x80, 0x01, 0xdc, 0xc1, 0x01, 0xdc, 0xc4, 0x00, - 0xdc, 0xc3, 0xb0, 0x34, 0x00, 0x07, 0x8e, 0x00, - 0x09, 0xa5, 0xc0, 0x00, 0xdc, 0xc6, 0xb0, 0x05, - 0x01, 0x09, 0xb0, 0x09, 0x00, 0x07, 0x8a, 0x01, - 0x09, 0xb0, 0x12, 0x00, 0x07, 0xb0, 0x67, 0xc2, - 0x41, 0x00, 0x04, 0xdc, 0xc1, 0x03, 0xdc, 0xc0, - 0x41, 0x00, 0x05, 0x01, 0x83, 0x00, 0xdc, 0x85, - 0xc0, 0x82, 0xc1, 0xb0, 0x95, 0xc1, 0x00, 0xdc, - 0xc6, 0x00, 0xdc, 0xc1, 0x00, 0xea, 0x00, 0xd6, - 0x00, 0xdc, 0x00, 0xca, 0xe4, 0x00, 0xe8, 0x01, - 0xe4, 0x00, 0xdc, 0x00, 0xda, 0xc0, 0x00, 0xe9, - 0x00, 0xdc, 0xc0, 0x00, 0xdc, 0xb2, 0x9f, 0xc1, - 0x01, 0x01, 0xc3, 0x02, 0x01, 0xc1, 0x83, 0xc0, - 0x82, 0x01, 0x01, 0xc0, 0x00, 0xdc, 0xc0, 0x01, - 0x01, 0x03, 0xdc, 0xc0, 0xb8, 0x03, 0xcd, 0xc2, - 0xb0, 0x5c, 0x00, 0x09, 0xb0, 0x2f, 0xdf, 0xb1, - 0xf9, 0x00, 0xda, 0x00, 0xe4, 0x00, 0xe8, 0x00, - 0xde, 0x01, 0xe0, 0xb0, 0x38, 0x01, 0x08, 0xb8, - 0x6d, 0xa3, 0xc0, 0x83, 0xc9, 0x9f, 0xc1, 0xb0, - 0x1f, 0xc1, 0xb0, 0xe3, 0x00, 0x09, 0xa4, 0x00, - 0x09, 0xb0, 0x66, 0x00, 0x09, 0x9a, 0xd1, 0xb0, - 0x08, 0x02, 0xdc, 0xa4, 0x00, 0x09, 0xb0, 0x2e, - 0x00, 0x07, 0x8b, 0x00, 0x09, 0xb0, 0xbe, 0xc0, - 0x80, 0xc1, 0x00, 0xdc, 0x81, 0xc1, 0x84, 0xc1, - 0x80, 0xc0, 0xb0, 0x03, 0x00, 0x09, 0xb0, 0xc5, - 0x00, 0x09, 0xb8, 0x46, 0xff, 0x00, 0x1a, 0xb2, - 0xd0, 0xc6, 0x06, 0xdc, 0xc1, 0xb3, 0x9c, 0x00, - 0xdc, 0xb0, 0xb1, 0x00, 0xdc, 0xb0, 0x64, 0xc4, - 0xb6, 0x61, 0x00, 0xdc, 0x80, 0xc0, 0xa7, 0xc0, - 0x00, 0x01, 0x00, 0xdc, 0x83, 0x00, 0x09, 0xb0, - 0x74, 0xc0, 0x00, 0xdc, 0xb2, 0x0c, 0xc3, 0xb0, - 0x10, 0xc4, 0xb1, 0x0c, 0xc1, 0xb0, 0x1f, 0x02, - 0xdc, 0xb0, 0x15, 0x01, 0xdc, 0xc2, 0x00, 0xdc, - 0xc0, 0x03, 0xdc, 0xb0, 0x00, 0xc0, 0x00, 0xdc, - 0xc0, 0x00, 0xdc, 0xb0, 0x8f, 0x00, 0x09, 0xa8, - 0x00, 0x09, 0x8d, 0x00, 0x09, 0xb0, 0x08, 0x00, - 0x09, 0x00, 0x07, 0xb0, 0x14, 0xc2, 0xaf, 0x01, - 0x09, 0xb0, 0x0d, 0x00, 0x07, 0xb0, 0x1b, 0x00, - 0x09, 0x88, 0x00, 0x07, 0xb0, 0x39, 0x00, 0x09, - 0x00, 0x07, 0xb0, 0x81, 0x00, 0x07, 0x00, 0x09, - 0xb0, 0x1f, 0x01, 0x07, 0x8f, 0x00, 0x09, 0x97, - 0xc6, 0x82, 0xc4, 0xb0, 0x28, 0x02, 0x09, 0xb0, - 0x40, 0x00, 0x09, 0x82, 0x00, 0x07, 0x96, 0xc0, - 0xb0, 0x32, 0x00, 0x09, 0x00, 0x07, 0xb0, 0xca, - 0x00, 0x09, 0x00, 0x07, 0xb0, 0x4d, 0x00, 0x09, - 0xb0, 0x45, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x42, - 0x00, 0x09, 0xb0, 0xdc, 0x00, 0x09, 0x00, 0x07, - 0xb0, 0xd1, 0x01, 0x09, 0x83, 0x00, 0x07, 0xb0, - 0x6b, 0x00, 0x09, 0xb0, 0x22, 0x00, 0x09, 0x91, - 0x00, 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb1, 0x74, - 0x00, 0x09, 0xb0, 0xd1, 0x00, 0x07, 0x80, 0x01, - 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb1, 0x78, 0x01, - 0x09, 0xb8, 0x39, 0xbb, 0x00, 0x09, 0xb8, 0x01, - 0x8f, 0x04, 0x01, 0xb0, 0x0a, 0xc6, 0xb4, 0x88, - 0x01, 0x06, 0xb8, 0x44, 0x7b, 0x00, 0x01, 0xb8, - 0x0c, 0x95, 0x01, 0xd8, 0x02, 0x01, 0x82, 0x00, - 0xe2, 0x04, 0xd8, 0x87, 0x07, 0xdc, 0x81, 0xc4, - 0x01, 0xdc, 0x9d, 0xc3, 0xb0, 0x63, 0xc2, 0xb8, - 0x05, 0x8a, 0xc6, 0x80, 0xd0, 0x81, 0xc6, 0x80, - 0xc1, 0x80, 0xc4, 0xb0, 0x33, 0xc0, 0xb0, 0x6f, - 0xc6, 0xb1, 0x46, 0xc0, 0xb0, 0x0c, 0xc3, 0xb1, - 0xcb, 0x01, 0xe8, 0x00, 0xdc, 0xc0, 0xb0, 0xcd, - 0xc0, 0x00, 0xdc, 0xb2, 0xaf, 0x06, 0xdc, 0xb0, - 0x3c, 0xc5, 0x00, 0x07, + 0xdc, 0xd1, 0x00, 0xdc, 0x81, 0xc5, 0x00, 0xdc, + 0xc3, 0x00, 0xea, 0xb0, 0x17, 0x00, 0x07, 0x8e, + 0x00, 0x09, 0xa5, 0xc0, 0x00, 0xdc, 0xc6, 0xb0, + 0x05, 0x01, 0x09, 0xb0, 0x09, 0x00, 0x07, 0x8a, + 0x01, 0x09, 0xb0, 0x12, 0x00, 0x07, 0xb0, 0x67, + 0xc2, 0x41, 0x00, 0x04, 0xdc, 0xc1, 0x03, 0xdc, + 0xc0, 0x41, 0x00, 0x05, 0x01, 0x83, 0x00, 0xdc, + 0x85, 0xc0, 0x82, 0xc1, 0xb0, 0x95, 0xc1, 0x00, + 0xdc, 0xc6, 0x00, 0xdc, 0xc1, 0x00, 0xea, 0x00, + 0xd6, 0x00, 0xdc, 0x00, 0xca, 0xe4, 0x00, 0xe8, + 0x01, 0xe4, 0x00, 0xdc, 0x00, 0xda, 0xc0, 0x00, + 0xe9, 0x00, 0xdc, 0xc0, 0x00, 0xdc, 0xb2, 0x9f, + 0xc1, 0x01, 0x01, 0xc3, 0x02, 0x01, 0xc1, 0x83, + 0xc0, 0x82, 0x01, 0x01, 0xc0, 0x00, 0xdc, 0xc0, + 0x01, 0x01, 0x03, 0xdc, 0xc0, 0xb8, 0x03, 0xcd, + 0xc2, 0xb0, 0x5c, 0x00, 0x09, 0xb0, 0x2f, 0xdf, + 0xb1, 0xf9, 0x00, 0xda, 0x00, 0xe4, 0x00, 0xe8, + 0x00, 0xde, 0x01, 0xe0, 0xb0, 0x38, 0x01, 0x08, + 0xb8, 0x6d, 0xa3, 0xc0, 0x83, 0xc9, 0x9f, 0xc1, + 0xb0, 0x1f, 0xc1, 0xb0, 0xe3, 0x00, 0x09, 0xa4, + 0x00, 0x09, 0xb0, 0x66, 0x00, 0x09, 0x9a, 0xd1, + 0xb0, 0x08, 0x02, 0xdc, 0xa4, 0x00, 0x09, 0xb0, + 0x2e, 0x00, 0x07, 0x8b, 0x00, 0x09, 0xb0, 0xbe, + 0xc0, 0x80, 0xc1, 0x00, 0xdc, 0x81, 0xc1, 0x84, + 0xc1, 0x80, 0xc0, 0xb0, 0x03, 0x00, 0x09, 0xb0, + 0xc5, 0x00, 0x09, 0xb8, 0x46, 0xff, 0x00, 0x1a, + 0xb2, 0xd0, 0xc6, 0x06, 0xdc, 0xc1, 0xb3, 0x9c, + 0x00, 0xdc, 0xb0, 0xb1, 0x00, 0xdc, 0xb0, 0x64, + 0xc4, 0xb6, 0x61, 0x00, 0xdc, 0x80, 0xc0, 0xa7, + 0xc0, 0x00, 0x01, 0x00, 0xdc, 0x83, 0x00, 0x09, + 0xb0, 0x74, 0xc0, 0x00, 0xdc, 0xb2, 0x0c, 0xc3, + 0xb0, 0x10, 0xc4, 0xb1, 0x0c, 0xc1, 0xb0, 0x1c, + 0x01, 0xdc, 0x80, 0x02, 0xdc, 0xb0, 0x15, 0x01, + 0xdc, 0xc2, 0x00, 0xdc, 0xc0, 0x03, 0xdc, 0xb0, + 0x00, 0xc0, 0x00, 0xdc, 0xc0, 0x00, 0xdc, 0xb0, + 0x8f, 0x00, 0x09, 0xa8, 0x00, 0x09, 0x8d, 0x00, + 0x09, 0xb0, 0x08, 0x00, 0x09, 0x00, 0x07, 0xb0, + 0x14, 0xc2, 0xaf, 0x01, 0x09, 0xb0, 0x0d, 0x00, + 0x07, 0xb0, 0x1b, 0x00, 0x09, 0x88, 0x00, 0x07, + 0xb0, 0x39, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x81, + 0x00, 0x07, 0x00, 0x09, 0xb0, 0x1f, 0x01, 0x07, + 0x8f, 0x00, 0x09, 0x97, 0xc6, 0x82, 0xc4, 0xb0, + 0x28, 0x02, 0x09, 0xb0, 0x40, 0x00, 0x09, 0x82, + 0x00, 0x07, 0x96, 0xc0, 0xb0, 0x32, 0x00, 0x09, + 0x00, 0x07, 0xb0, 0xca, 0x00, 0x09, 0x00, 0x07, + 0xb0, 0x4d, 0x00, 0x09, 0xb0, 0x45, 0x00, 0x09, + 0x00, 0x07, 0xb0, 0x42, 0x00, 0x09, 0xb0, 0xdc, + 0x00, 0x09, 0x00, 0x07, 0xb0, 0xd1, 0x01, 0x09, + 0x83, 0x00, 0x07, 0xb0, 0x6b, 0x00, 0x09, 0xb0, + 0x22, 0x00, 0x09, 0x91, 0x00, 0x09, 0xb0, 0x20, + 0x00, 0x09, 0xb1, 0x74, 0x00, 0x09, 0xb0, 0xd1, + 0x00, 0x07, 0x80, 0x01, 0x09, 0xb0, 0x20, 0x00, + 0x09, 0xb1, 0x78, 0x01, 0x09, 0xb8, 0x39, 0xbb, + 0x00, 0x09, 0xb8, 0x01, 0x8f, 0x04, 0x01, 0xb0, + 0x0a, 0xc6, 0xb4, 0x88, 0x01, 0x06, 0xb8, 0x44, + 0x7b, 0x00, 0x01, 0xb8, 0x0c, 0x95, 0x01, 0xd8, + 0x02, 0x01, 0x82, 0x00, 0xe2, 0x04, 0xd8, 0x87, + 0x07, 0xdc, 0x81, 0xc4, 0x01, 0xdc, 0x9d, 0xc3, + 0xb0, 0x63, 0xc2, 0xb8, 0x05, 0x8a, 0xc6, 0x80, + 0xd0, 0x81, 0xc6, 0x80, 0xc1, 0x80, 0xc4, 0xb0, + 0x33, 0xc0, 0xb0, 0x6f, 0xc6, 0xb1, 0x46, 0xc0, + 0xb0, 0x0c, 0xc3, 0xb1, 0xcb, 0x01, 0xe8, 0x00, + 0xdc, 0xc0, 0xb0, 0xcd, 0xc0, 0x00, 0xdc, 0xb0, + 0xc2, 0xc0, 0x81, 0xc0, 0x86, 0xc1, 0x84, 0xc0, + 0xb1, 0xa9, 0x06, 0xdc, 0xb0, 0x3c, 0xc5, 0x00, + 0x07, }; -static const uint8_t unicode_cc_index[87] = { +static const uint8_t unicode_cc_index[90] = { 0x4d, 0x03, 0x00, 0x97, 0x05, 0x20, 0xc6, 0x05, 0x00, 0xe7, 0x06, 0x00, 0x45, 0x07, 0x00, 0x9c, 0x08, 0x00, 0x4d, 0x09, 0x00, 0x3c, 0x0b, 0x00, 0x3d, 0x0d, 0x00, 0x36, 0x0f, 0x00, 0x38, 0x10, - 0x20, 0x3a, 0x19, 0x00, 0xcb, 0x1a, 0x20, 0xd3, - 0x1c, 0x00, 0xcf, 0x1d, 0x00, 0xe2, 0x20, 0x00, - 0x2e, 0x30, 0x20, 0x2b, 0xa9, 0x20, 0xed, 0xab, - 0x00, 0x39, 0x0a, 0x01, 0x4c, 0x0f, 0x01, 0x35, - 0x11, 0x21, 0x66, 0x13, 0x01, 0x40, 0x16, 0x01, - 0x47, 0x1a, 0x01, 0xf0, 0x6a, 0x21, 0x8a, 0xd1, - 0x01, 0xec, 0xe4, 0x21, 0x4b, 0xe9, 0x01, + 0x20, 0x3a, 0x19, 0x00, 0xcb, 0x1a, 0x20, 0xf2, + 0x1b, 0x00, 0xc3, 0x1d, 0x20, 0xd0, 0x20, 0x00, + 0x00, 0x2e, 0x00, 0x2c, 0xa8, 0x00, 0xbe, 0xaa, + 0x00, 0x76, 0x03, 0x01, 0xfa, 0x0e, 0x01, 0x80, + 0x10, 0x21, 0xe9, 0x12, 0x01, 0xc3, 0x14, 0x01, + 0x3f, 0x19, 0x01, 0x98, 0x1d, 0x21, 0x67, 0xd1, + 0x01, 0x8f, 0xe0, 0x21, 0xf6, 0xe6, 0x01, 0x4b, + 0xe9, 0x01, }; static const uint32_t unicode_decomp_table1[709] = { @@ -841,7 +852,7 @@ static const uint32_t unicode_decomp_table1[709] = { 0x0cf54119, 0x0cf5c097, 0x0cf6009b, 0x0cf64099, 0x0cf68217, 0x0cf78119, 0x0cf804a1, 0x0cfa4525, 0x0cfcc525, 0x0cff4125, 0x0cffc099, 0x29a70103, - 0x29dc0081, 0x29fc8195, 0x29fe0103, 0x2ad70203, + 0x29dc0081, 0x29fc4215, 0x29fe0103, 0x2ad70203, 0x2ada4081, 0x3e401482, 0x3e4a7f82, 0x3e6a3f82, 0x3e8aa102, 0x3e9b0110, 0x3e9c2f82, 0x3eb3c590, 0x3ec00197, 0x3ec0c119, 0x3ec1413f, 0x3ec4c2af, @@ -959,35 +970,35 @@ static const uint16_t unicode_decomp_table2[709] = { 0x10f4, 0x1100, 0x1105, 0x1111, 0x1141, 0x1149, 0x114d, 0x1153, 0x1157, 0x115a, 0x116e, 0x1171, 0x1175, 0x117b, 0x117d, 0x1181, 0x1184, 0x118c, 0x1192, 0x1196, 0x119c, 0x11a2, 0x11a8, 0x11ab, - 0xa76f, 0x11af, 0x11b2, 0x11b6, 0x028d, 0x11be, 0x1210, 0x130e, - 0x140c, 0x1490, 0x1495, 0x1553, 0x156c, 0x1572, 0x1578, 0x157e, - 0x158a, 0x1596, 0x002b, 0x15a1, 0x15b9, 0x15bd, 0x15c1, 0x15c5, - 0x15c9, 0x15cd, 0x15e1, 0x15e5, 0x1649, 0x1662, 0x1688, 0x168e, - 0x174c, 0x1752, 0x1757, 0x1777, 0x1877, 0x187d, 0x1911, 0x19d3, - 0x1a77, 0x1a7f, 0x1a9d, 0x1aa2, 0x1ab6, 0x1ac0, 0x1ac6, 0x1ada, - 0x1adf, 0x1ae5, 0x1af3, 0x1b23, 0x1b30, 0x1b38, 0x1b3c, 0x1b52, - 0x1bc9, 0x1bdb, 0x1bdd, 0x1bdf, 0x3164, 0x1c20, 0x1c22, 0x1c24, - 0x1c26, 0x1c28, 0x1c2a, 0x1c48, 0x1c4d, 0x1c52, 0x1c88, 0x1cce, - 0x1cdc, 0x1ce1, 0x1cea, 0x1cf3, 0x1d01, 0x1d06, 0x1d0b, 0x1d1d, - 0x1d2f, 0x1d38, 0x1d3d, 0x1d61, 0x1d6f, 0x1d71, 0x1d73, 0x1d93, - 0x1dae, 0x1db0, 0x1db2, 0x1db4, 0x1db6, 0x1db8, 0x1dba, 0x1dbc, - 0x1ddc, 0x1dde, 0x1de0, 0x1de2, 0x1de4, 0x1deb, 0x1ded, 0x1def, - 0x1df1, 0x1e00, 0x1e02, 0x1e04, 0x1e06, 0x1e08, 0x1e0a, 0x1e0c, - 0x1e0e, 0x1e10, 0x1e12, 0x1e14, 0x1e16, 0x1e18, 0x1e1a, 0x1e1c, - 0x1e20, 0x03f4, 0x1e22, 0x2207, 0x1e24, 0x2202, 0x1e26, 0x1e2e, - 0x03f4, 0x1e30, 0x2207, 0x1e32, 0x2202, 0x1e34, 0x1e3c, 0x03f4, - 0x1e3e, 0x2207, 0x1e40, 0x2202, 0x1e42, 0x1e4a, 0x03f4, 0x1e4c, - 0x2207, 0x1e4e, 0x2202, 0x1e50, 0x1e58, 0x03f4, 0x1e5a, 0x2207, - 0x1e5c, 0x2202, 0x1e5e, 0x1e68, 0x1e6a, 0x1e6c, 0x1e6e, 0x1e70, - 0x1e72, 0x1e74, 0x1e76, 0x1e78, 0x1e80, 0x1ea3, 0x1ea7, 0x1ead, - 0x1eca, 0x062d, 0x1ed2, 0x1ede, 0x062c, 0x1eee, 0x1f5e, 0x1f6a, - 0x1f7d, 0x1f8f, 0x1fa2, 0x1fa4, 0x1fa8, 0x1fae, 0x1fb4, 0x1fb6, - 0x1fba, 0x1fbc, 0x1fc4, 0x1fc7, 0x1fc9, 0x1fcf, 0x1fd1, 0x30b5, - 0x1fd7, 0x202f, 0x2045, 0x2049, 0x204b, 0x2050, 0x209d, 0x20ae, - 0x21af, 0x21bf, 0x21c5, 0x22bf, 0x23dd, + 0xa76f, 0x11af, 0x11b3, 0x11b7, 0x028d, 0x11bf, 0x1211, 0x130f, + 0x140d, 0x1491, 0x1496, 0x1554, 0x156d, 0x1573, 0x1579, 0x157f, + 0x158b, 0x1597, 0x002b, 0x15a2, 0x15ba, 0x15be, 0x15c2, 0x15c6, + 0x15ca, 0x15ce, 0x15e2, 0x15e6, 0x164a, 0x1663, 0x1689, 0x168f, + 0x174d, 0x1753, 0x1758, 0x1778, 0x1878, 0x187e, 0x1912, 0x19d4, + 0x1a78, 0x1a80, 0x1a9e, 0x1aa3, 0x1ab7, 0x1ac1, 0x1ac7, 0x1adb, + 0x1ae0, 0x1ae6, 0x1af4, 0x1b24, 0x1b31, 0x1b39, 0x1b3d, 0x1b53, + 0x1bca, 0x1bdc, 0x1bde, 0x1be0, 0x3164, 0x1c21, 0x1c23, 0x1c25, + 0x1c27, 0x1c29, 0x1c2b, 0x1c49, 0x1c4e, 0x1c53, 0x1c89, 0x1ccf, + 0x1cdd, 0x1ce2, 0x1ceb, 0x1cf4, 0x1d02, 0x1d07, 0x1d0c, 0x1d1e, + 0x1d30, 0x1d39, 0x1d3e, 0x1d62, 0x1d70, 0x1d72, 0x1d74, 0x1d94, + 0x1daf, 0x1db1, 0x1db3, 0x1db5, 0x1db7, 0x1db9, 0x1dbb, 0x1dbd, + 0x1ddd, 0x1ddf, 0x1de1, 0x1de3, 0x1de5, 0x1dec, 0x1dee, 0x1df0, + 0x1df2, 0x1e01, 0x1e03, 0x1e05, 0x1e07, 0x1e09, 0x1e0b, 0x1e0d, + 0x1e0f, 0x1e11, 0x1e13, 0x1e15, 0x1e17, 0x1e19, 0x1e1b, 0x1e1d, + 0x1e21, 0x03f4, 0x1e23, 0x2207, 0x1e25, 0x2202, 0x1e27, 0x1e2f, + 0x03f4, 0x1e31, 0x2207, 0x1e33, 0x2202, 0x1e35, 0x1e3d, 0x03f4, + 0x1e3f, 0x2207, 0x1e41, 0x2202, 0x1e43, 0x1e4b, 0x03f4, 0x1e4d, + 0x2207, 0x1e4f, 0x2202, 0x1e51, 0x1e59, 0x03f4, 0x1e5b, 0x2207, + 0x1e5d, 0x2202, 0x1e5f, 0x1e69, 0x1e6b, 0x1e6d, 0x1e6f, 0x1e71, + 0x1e73, 0x1e75, 0x1e77, 0x1e79, 0x1e81, 0x1ea4, 0x1ea8, 0x1eae, + 0x1ecb, 0x062d, 0x1ed3, 0x1edf, 0x062c, 0x1eef, 0x1f5f, 0x1f6b, + 0x1f7e, 0x1f90, 0x1fa3, 0x1fa5, 0x1fa9, 0x1faf, 0x1fb5, 0x1fb7, + 0x1fbb, 0x1fbd, 0x1fc5, 0x1fc8, 0x1fca, 0x1fd0, 0x1fd2, 0x30b5, + 0x1fd8, 0x2030, 0x2046, 0x204a, 0x204c, 0x2051, 0x209e, 0x20af, + 0x21b0, 0x21c0, 0x21c6, 0x22c0, 0x23de, }; -static const uint8_t unicode_decomp_data[9451] = { +static const uint8_t unicode_decomp_data[9452] = { 0x20, 0x88, 0x20, 0x84, 0x32, 0x33, 0x20, 0x81, 0x20, 0xa7, 0x31, 0x6f, 0x31, 0xd0, 0x34, 0x31, 0xd0, 0x32, 0x33, 0xd0, 0x34, 0x41, 0x80, 0x41, @@ -1553,623 +1564,623 @@ static const uint8_t unicode_decomp_data[9451] = { 0xd1, 0x6d, 0x31, 0x00, 0xe5, 0x65, 0x31, 0x00, 0x30, 0x00, 0xe5, 0x65, 0x32, 0x00, 0x30, 0x00, 0xe5, 0x65, 0x33, 0x00, 0x30, 0x00, 0xe5, 0x65, - 0x67, 0x61, 0x6c, 0x4a, 0x04, 0x4c, 0x04, 0x43, - 0x46, 0x51, 0x26, 0x01, 0x53, 0x01, 0x27, 0xa7, - 0x37, 0xab, 0x6b, 0x02, 0x52, 0xab, 0x48, 0x8c, - 0xf4, 0x66, 0xca, 0x8e, 0xc8, 0x8c, 0xd1, 0x6e, - 0x32, 0x4e, 0xe5, 0x53, 0x9c, 0x9f, 0x9c, 0x9f, - 0x51, 0x59, 0xd1, 0x91, 0x87, 0x55, 0x48, 0x59, - 0xf6, 0x61, 0x69, 0x76, 0x85, 0x7f, 0x3f, 0x86, - 0xba, 0x87, 0xf8, 0x88, 0x8f, 0x90, 0x02, 0x6a, - 0x1b, 0x6d, 0xd9, 0x70, 0xde, 0x73, 0x3d, 0x84, - 0x6a, 0x91, 0xf1, 0x99, 0x82, 0x4e, 0x75, 0x53, - 0x04, 0x6b, 0x1b, 0x72, 0x2d, 0x86, 0x1e, 0x9e, - 0x50, 0x5d, 0xeb, 0x6f, 0xcd, 0x85, 0x64, 0x89, - 0xc9, 0x62, 0xd8, 0x81, 0x1f, 0x88, 0xca, 0x5e, - 0x17, 0x67, 0x6a, 0x6d, 0xfc, 0x72, 0xce, 0x90, - 0x86, 0x4f, 0xb7, 0x51, 0xde, 0x52, 0xc4, 0x64, - 0xd3, 0x6a, 0x10, 0x72, 0xe7, 0x76, 0x01, 0x80, - 0x06, 0x86, 0x5c, 0x86, 0xef, 0x8d, 0x32, 0x97, - 0x6f, 0x9b, 0xfa, 0x9d, 0x8c, 0x78, 0x7f, 0x79, - 0xa0, 0x7d, 0xc9, 0x83, 0x04, 0x93, 0x7f, 0x9e, - 0xd6, 0x8a, 0xdf, 0x58, 0x04, 0x5f, 0x60, 0x7c, - 0x7e, 0x80, 0x62, 0x72, 0xca, 0x78, 0xc2, 0x8c, - 0xf7, 0x96, 0xd8, 0x58, 0x62, 0x5c, 0x13, 0x6a, - 0xda, 0x6d, 0x0f, 0x6f, 0x2f, 0x7d, 0x37, 0x7e, - 0x4b, 0x96, 0xd2, 0x52, 0x8b, 0x80, 0xdc, 0x51, - 0xcc, 0x51, 0x1c, 0x7a, 0xbe, 0x7d, 0xf1, 0x83, - 0x75, 0x96, 0x80, 0x8b, 0xcf, 0x62, 0x02, 0x6a, - 0xfe, 0x8a, 0x39, 0x4e, 0xe7, 0x5b, 0x12, 0x60, - 0x87, 0x73, 0x70, 0x75, 0x17, 0x53, 0xfb, 0x78, - 0xbf, 0x4f, 0xa9, 0x5f, 0x0d, 0x4e, 0xcc, 0x6c, - 0x78, 0x65, 0x22, 0x7d, 0xc3, 0x53, 0x5e, 0x58, - 0x01, 0x77, 0x49, 0x84, 0xaa, 0x8a, 0xba, 0x6b, - 0xb0, 0x8f, 0x88, 0x6c, 0xfe, 0x62, 0xe5, 0x82, - 0xa0, 0x63, 0x65, 0x75, 0xae, 0x4e, 0x69, 0x51, - 0xc9, 0x51, 0x81, 0x68, 0xe7, 0x7c, 0x6f, 0x82, - 0xd2, 0x8a, 0xcf, 0x91, 0xf5, 0x52, 0x42, 0x54, - 0x73, 0x59, 0xec, 0x5e, 0xc5, 0x65, 0xfe, 0x6f, - 0x2a, 0x79, 0xad, 0x95, 0x6a, 0x9a, 0x97, 0x9e, - 0xce, 0x9e, 0x9b, 0x52, 0xc6, 0x66, 0x77, 0x6b, - 0x62, 0x8f, 0x74, 0x5e, 0x90, 0x61, 0x00, 0x62, - 0x9a, 0x64, 0x23, 0x6f, 0x49, 0x71, 0x89, 0x74, - 0xca, 0x79, 0xf4, 0x7d, 0x6f, 0x80, 0x26, 0x8f, - 0xee, 0x84, 0x23, 0x90, 0x4a, 0x93, 0x17, 0x52, - 0xa3, 0x52, 0xbd, 0x54, 0xc8, 0x70, 0xc2, 0x88, - 0xaa, 0x8a, 0xc9, 0x5e, 0xf5, 0x5f, 0x7b, 0x63, - 0xae, 0x6b, 0x3e, 0x7c, 0x75, 0x73, 0xe4, 0x4e, - 0xf9, 0x56, 0xe7, 0x5b, 0xba, 0x5d, 0x1c, 0x60, - 0xb2, 0x73, 0x69, 0x74, 0x9a, 0x7f, 0x46, 0x80, - 0x34, 0x92, 0xf6, 0x96, 0x48, 0x97, 0x18, 0x98, - 0x8b, 0x4f, 0xae, 0x79, 0xb4, 0x91, 0xb8, 0x96, - 0xe1, 0x60, 0x86, 0x4e, 0xda, 0x50, 0xee, 0x5b, - 0x3f, 0x5c, 0x99, 0x65, 0x02, 0x6a, 0xce, 0x71, - 0x42, 0x76, 0xfc, 0x84, 0x7c, 0x90, 0x8d, 0x9f, - 0x88, 0x66, 0x2e, 0x96, 0x89, 0x52, 0x7b, 0x67, - 0xf3, 0x67, 0x41, 0x6d, 0x9c, 0x6e, 0x09, 0x74, - 0x59, 0x75, 0x6b, 0x78, 0x10, 0x7d, 0x5e, 0x98, - 0x6d, 0x51, 0x2e, 0x62, 0x78, 0x96, 0x2b, 0x50, - 0x19, 0x5d, 0xea, 0x6d, 0x2a, 0x8f, 0x8b, 0x5f, - 0x44, 0x61, 0x17, 0x68, 0x87, 0x73, 0x86, 0x96, - 0x29, 0x52, 0x0f, 0x54, 0x65, 0x5c, 0x13, 0x66, - 0x4e, 0x67, 0xa8, 0x68, 0xe5, 0x6c, 0x06, 0x74, - 0xe2, 0x75, 0x79, 0x7f, 0xcf, 0x88, 0xe1, 0x88, - 0xcc, 0x91, 0xe2, 0x96, 0x3f, 0x53, 0xba, 0x6e, - 0x1d, 0x54, 0xd0, 0x71, 0x98, 0x74, 0xfa, 0x85, - 0xa3, 0x96, 0x57, 0x9c, 0x9f, 0x9e, 0x97, 0x67, - 0xcb, 0x6d, 0xe8, 0x81, 0xcb, 0x7a, 0x20, 0x7b, - 0x92, 0x7c, 0xc0, 0x72, 0x99, 0x70, 0x58, 0x8b, - 0xc0, 0x4e, 0x36, 0x83, 0x3a, 0x52, 0x07, 0x52, - 0xa6, 0x5e, 0xd3, 0x62, 0xd6, 0x7c, 0x85, 0x5b, - 0x1e, 0x6d, 0xb4, 0x66, 0x3b, 0x8f, 0x4c, 0x88, - 0x4d, 0x96, 0x8b, 0x89, 0xd3, 0x5e, 0x40, 0x51, - 0xc0, 0x55, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x58, - 0x00, 0x00, 0x74, 0x66, 0x00, 0x00, 0x00, 0x00, - 0xde, 0x51, 0x2a, 0x73, 0xca, 0x76, 0x3c, 0x79, - 0x5e, 0x79, 0x65, 0x79, 0x8f, 0x79, 0x56, 0x97, - 0xbe, 0x7c, 0xbd, 0x7f, 0x00, 0x00, 0x12, 0x86, - 0x00, 0x00, 0xf8, 0x8a, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x90, 0xfd, 0x90, 0xef, 0x98, 0xfc, 0x98, - 0x28, 0x99, 0xb4, 0x9d, 0xde, 0x90, 0xb7, 0x96, - 0xae, 0x4f, 0xe7, 0x50, 0x4d, 0x51, 0xc9, 0x52, - 0xe4, 0x52, 0x51, 0x53, 0x9d, 0x55, 0x06, 0x56, - 0x68, 0x56, 0x40, 0x58, 0xa8, 0x58, 0x64, 0x5c, - 0x6e, 0x5c, 0x94, 0x60, 0x68, 0x61, 0x8e, 0x61, - 0xf2, 0x61, 0x4f, 0x65, 0xe2, 0x65, 0x91, 0x66, - 0x85, 0x68, 0x77, 0x6d, 0x1a, 0x6e, 0x22, 0x6f, - 0x6e, 0x71, 0x2b, 0x72, 0x22, 0x74, 0x91, 0x78, - 0x3e, 0x79, 0x49, 0x79, 0x48, 0x79, 0x50, 0x79, - 0x56, 0x79, 0x5d, 0x79, 0x8d, 0x79, 0x8e, 0x79, - 0x40, 0x7a, 0x81, 0x7a, 0xc0, 0x7b, 0xf4, 0x7d, - 0x09, 0x7e, 0x41, 0x7e, 0x72, 0x7f, 0x05, 0x80, - 0xed, 0x81, 0x79, 0x82, 0x79, 0x82, 0x57, 0x84, - 0x10, 0x89, 0x96, 0x89, 0x01, 0x8b, 0x39, 0x8b, - 0xd3, 0x8c, 0x08, 0x8d, 0xb6, 0x8f, 0x38, 0x90, - 0xe3, 0x96, 0xff, 0x97, 0x3b, 0x98, 0x75, 0x60, - 0xee, 0x42, 0x18, 0x82, 0x02, 0x26, 0x4e, 0xb5, - 0x51, 0x68, 0x51, 0x80, 0x4f, 0x45, 0x51, 0x80, - 0x51, 0xc7, 0x52, 0xfa, 0x52, 0x9d, 0x55, 0x55, - 0x55, 0x99, 0x55, 0xe2, 0x55, 0x5a, 0x58, 0xb3, - 0x58, 0x44, 0x59, 0x54, 0x59, 0x62, 0x5a, 0x28, - 0x5b, 0xd2, 0x5e, 0xd9, 0x5e, 0x69, 0x5f, 0xad, - 0x5f, 0xd8, 0x60, 0x4e, 0x61, 0x08, 0x61, 0x8e, - 0x61, 0x60, 0x61, 0xf2, 0x61, 0x34, 0x62, 0xc4, - 0x63, 0x1c, 0x64, 0x52, 0x64, 0x56, 0x65, 0x74, - 0x66, 0x17, 0x67, 0x1b, 0x67, 0x56, 0x67, 0x79, - 0x6b, 0xba, 0x6b, 0x41, 0x6d, 0xdb, 0x6e, 0xcb, - 0x6e, 0x22, 0x6f, 0x1e, 0x70, 0x6e, 0x71, 0xa7, - 0x77, 0x35, 0x72, 0xaf, 0x72, 0x2a, 0x73, 0x71, - 0x74, 0x06, 0x75, 0x3b, 0x75, 0x1d, 0x76, 0x1f, - 0x76, 0xca, 0x76, 0xdb, 0x76, 0xf4, 0x76, 0x4a, - 0x77, 0x40, 0x77, 0xcc, 0x78, 0xb1, 0x7a, 0xc0, - 0x7b, 0x7b, 0x7c, 0x5b, 0x7d, 0xf4, 0x7d, 0x3e, - 0x7f, 0x05, 0x80, 0x52, 0x83, 0xef, 0x83, 0x79, - 0x87, 0x41, 0x89, 0x86, 0x89, 0x96, 0x89, 0xbf, - 0x8a, 0xf8, 0x8a, 0xcb, 0x8a, 0x01, 0x8b, 0xfe, - 0x8a, 0xed, 0x8a, 0x39, 0x8b, 0x8a, 0x8b, 0x08, - 0x8d, 0x38, 0x8f, 0x72, 0x90, 0x99, 0x91, 0x76, - 0x92, 0x7c, 0x96, 0xe3, 0x96, 0x56, 0x97, 0xdb, - 0x97, 0xff, 0x97, 0x0b, 0x98, 0x3b, 0x98, 0x12, - 0x9b, 0x9c, 0x9f, 0x4a, 0x28, 0x44, 0x28, 0xd5, - 0x33, 0x9d, 0x3b, 0x18, 0x40, 0x39, 0x40, 0x49, - 0x52, 0xd0, 0x5c, 0xd3, 0x7e, 0x43, 0x9f, 0x8e, - 0x9f, 0x2a, 0xa0, 0x02, 0x66, 0x66, 0x66, 0x69, - 0x66, 0x6c, 0x66, 0x66, 0x69, 0x66, 0x66, 0x6c, - 0x7f, 0x01, 0x74, 0x73, 0x00, 0x74, 0x65, 0x05, - 0x0f, 0x11, 0x0f, 0x00, 0x0f, 0x06, 0x19, 0x11, - 0x0f, 0x08, 0xd9, 0x05, 0xb4, 0x05, 0x00, 0x00, - 0x00, 0x00, 0xf2, 0x05, 0xb7, 0x05, 0xd0, 0x05, - 0x12, 0x00, 0x03, 0x04, 0x0b, 0x0c, 0x0d, 0x18, - 0x1a, 0xe9, 0x05, 0xc1, 0x05, 0xe9, 0x05, 0xc2, - 0x05, 0x49, 0xfb, 0xc1, 0x05, 0x49, 0xfb, 0xc2, - 0x05, 0xd0, 0x05, 0xb7, 0x05, 0xd0, 0x05, 0xb8, - 0x05, 0xd0, 0x05, 0xbc, 0x05, 0xd8, 0x05, 0xbc, - 0x05, 0xde, 0x05, 0xbc, 0x05, 0xe0, 0x05, 0xbc, - 0x05, 0xe3, 0x05, 0xbc, 0x05, 0xb9, 0x05, 0x2d, - 0x03, 0x2e, 0x03, 0x2f, 0x03, 0x30, 0x03, 0x31, - 0x03, 0x1c, 0x00, 0x18, 0x06, 0x22, 0x06, 0x2b, - 0x06, 0xd0, 0x05, 0xdc, 0x05, 0x71, 0x06, 0x00, - 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0f, 0x0f, 0x0f, 0x0f, 0x09, 0x09, 0x09, - 0x09, 0x0e, 0x0e, 0x0e, 0x0e, 0x08, 0x08, 0x08, - 0x08, 0x33, 0x33, 0x33, 0x33, 0x35, 0x35, 0x35, - 0x35, 0x13, 0x13, 0x13, 0x13, 0x12, 0x12, 0x12, - 0x12, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, - 0x16, 0x1c, 0x1c, 0x1b, 0x1b, 0x1d, 0x1d, 0x17, - 0x17, 0x27, 0x27, 0x20, 0x20, 0x38, 0x38, 0x38, - 0x38, 0x3e, 0x3e, 0x3e, 0x3e, 0x42, 0x42, 0x42, - 0x42, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x4a, - 0x4a, 0x4a, 0x4a, 0x4f, 0x4f, 0x50, 0x50, 0x50, - 0x50, 0x4d, 0x4d, 0x4d, 0x4d, 0x61, 0x61, 0x62, - 0x62, 0x49, 0x06, 0x64, 0x64, 0x64, 0x64, 0x7e, - 0x7e, 0x7d, 0x7d, 0x7f, 0x7f, 0x2e, 0x82, 0x82, - 0x7c, 0x7c, 0x80, 0x80, 0x87, 0x87, 0x87, 0x87, - 0x00, 0x00, 0x26, 0x06, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xaf, 0x00, 0xaf, 0x00, 0x22, 0x00, 0x22, - 0x00, 0xa1, 0x00, 0xa1, 0x00, 0xa0, 0x00, 0xa0, - 0x00, 0xa2, 0x00, 0xa2, 0x00, 0xaa, 0x00, 0xaa, - 0x00, 0xaa, 0x00, 0x23, 0x00, 0x23, 0x00, 0x23, - 0xcc, 0x06, 0x00, 0x00, 0x00, 0x00, 0x26, 0x06, - 0x00, 0x06, 0x00, 0x07, 0x00, 0x1f, 0x00, 0x23, - 0x00, 0x24, 0x02, 0x06, 0x02, 0x07, 0x02, 0x08, - 0x02, 0x1f, 0x02, 0x23, 0x02, 0x24, 0x04, 0x06, - 0x04, 0x07, 0x04, 0x08, 0x04, 0x1f, 0x04, 0x23, - 0x04, 0x24, 0x05, 0x06, 0x05, 0x1f, 0x05, 0x23, - 0x05, 0x24, 0x06, 0x07, 0x06, 0x1f, 0x07, 0x06, - 0x07, 0x1f, 0x08, 0x06, 0x08, 0x07, 0x08, 0x1f, - 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x08, 0x0d, 0x1f, - 0x0f, 0x07, 0x0f, 0x1f, 0x10, 0x06, 0x10, 0x07, - 0x10, 0x08, 0x10, 0x1f, 0x11, 0x07, 0x11, 0x1f, - 0x12, 0x1f, 0x13, 0x06, 0x13, 0x1f, 0x14, 0x06, - 0x14, 0x1f, 0x1b, 0x06, 0x1b, 0x07, 0x1b, 0x08, - 0x1b, 0x1f, 0x1b, 0x23, 0x1b, 0x24, 0x1c, 0x07, - 0x1c, 0x1f, 0x1c, 0x23, 0x1c, 0x24, 0x1d, 0x01, - 0x1d, 0x06, 0x1d, 0x07, 0x1d, 0x08, 0x1d, 0x1e, - 0x1d, 0x1f, 0x1d, 0x23, 0x1d, 0x24, 0x1e, 0x06, - 0x1e, 0x07, 0x1e, 0x08, 0x1e, 0x1f, 0x1e, 0x23, - 0x1e, 0x24, 0x1f, 0x06, 0x1f, 0x07, 0x1f, 0x08, - 0x1f, 0x1f, 0x1f, 0x23, 0x1f, 0x24, 0x20, 0x06, - 0x20, 0x07, 0x20, 0x08, 0x20, 0x1f, 0x20, 0x23, - 0x20, 0x24, 0x21, 0x06, 0x21, 0x1f, 0x21, 0x23, - 0x21, 0x24, 0x24, 0x06, 0x24, 0x07, 0x24, 0x08, - 0x24, 0x1f, 0x24, 0x23, 0x24, 0x24, 0x0a, 0x4a, - 0x0b, 0x4a, 0x23, 0x4a, 0x20, 0x00, 0x4c, 0x06, - 0x51, 0x06, 0x51, 0x06, 0xff, 0x00, 0x1f, 0x26, - 0x06, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x1f, 0x00, - 0x20, 0x00, 0x23, 0x00, 0x24, 0x02, 0x0b, 0x02, - 0x0c, 0x02, 0x1f, 0x02, 0x20, 0x02, 0x23, 0x02, - 0x24, 0x04, 0x0b, 0x04, 0x0c, 0x04, 0x1f, 0x26, - 0x06, 0x04, 0x20, 0x04, 0x23, 0x04, 0x24, 0x05, - 0x0b, 0x05, 0x0c, 0x05, 0x1f, 0x05, 0x20, 0x05, - 0x23, 0x05, 0x24, 0x1b, 0x23, 0x1b, 0x24, 0x1c, - 0x23, 0x1c, 0x24, 0x1d, 0x01, 0x1d, 0x1e, 0x1d, - 0x1f, 0x1d, 0x23, 0x1d, 0x24, 0x1e, 0x1f, 0x1e, - 0x23, 0x1e, 0x24, 0x1f, 0x01, 0x1f, 0x1f, 0x20, - 0x0b, 0x20, 0x0c, 0x20, 0x1f, 0x20, 0x20, 0x20, - 0x23, 0x20, 0x24, 0x23, 0x4a, 0x24, 0x0b, 0x24, - 0x0c, 0x24, 0x1f, 0x24, 0x20, 0x24, 0x23, 0x24, - 0x24, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, - 0x1f, 0x00, 0x21, 0x02, 0x06, 0x02, 0x07, 0x02, - 0x08, 0x02, 0x1f, 0x02, 0x21, 0x04, 0x06, 0x04, - 0x07, 0x04, 0x08, 0x04, 0x1f, 0x04, 0x21, 0x05, - 0x1f, 0x06, 0x07, 0x06, 0x1f, 0x07, 0x06, 0x07, - 0x1f, 0x08, 0x06, 0x08, 0x1f, 0x0d, 0x06, 0x0d, - 0x07, 0x0d, 0x08, 0x0d, 0x1f, 0x0f, 0x07, 0x0f, - 0x08, 0x0f, 0x1f, 0x10, 0x06, 0x10, 0x07, 0x10, - 0x08, 0x10, 0x1f, 0x11, 0x07, 0x12, 0x1f, 0x13, - 0x06, 0x13, 0x1f, 0x14, 0x06, 0x14, 0x1f, 0x1b, - 0x06, 0x1b, 0x07, 0x1b, 0x08, 0x1b, 0x1f, 0x1c, - 0x07, 0x1c, 0x1f, 0x1d, 0x06, 0x1d, 0x07, 0x1d, - 0x08, 0x1d, 0x1e, 0x1d, 0x1f, 0x1e, 0x06, 0x1e, - 0x07, 0x1e, 0x08, 0x1e, 0x1f, 0x1e, 0x21, 0x1f, - 0x06, 0x1f, 0x07, 0x1f, 0x08, 0x1f, 0x1f, 0x20, + 0x67, 0x61, 0x6c, 0x4a, 0x04, 0x4c, 0x04, 0x53, + 0x43, 0x46, 0x51, 0x26, 0x01, 0x53, 0x01, 0x27, + 0xa7, 0x37, 0xab, 0x6b, 0x02, 0x52, 0xab, 0x48, + 0x8c, 0xf4, 0x66, 0xca, 0x8e, 0xc8, 0x8c, 0xd1, + 0x6e, 0x32, 0x4e, 0xe5, 0x53, 0x9c, 0x9f, 0x9c, + 0x9f, 0x51, 0x59, 0xd1, 0x91, 0x87, 0x55, 0x48, + 0x59, 0xf6, 0x61, 0x69, 0x76, 0x85, 0x7f, 0x3f, + 0x86, 0xba, 0x87, 0xf8, 0x88, 0x8f, 0x90, 0x02, + 0x6a, 0x1b, 0x6d, 0xd9, 0x70, 0xde, 0x73, 0x3d, + 0x84, 0x6a, 0x91, 0xf1, 0x99, 0x82, 0x4e, 0x75, + 0x53, 0x04, 0x6b, 0x1b, 0x72, 0x2d, 0x86, 0x1e, + 0x9e, 0x50, 0x5d, 0xeb, 0x6f, 0xcd, 0x85, 0x64, + 0x89, 0xc9, 0x62, 0xd8, 0x81, 0x1f, 0x88, 0xca, + 0x5e, 0x17, 0x67, 0x6a, 0x6d, 0xfc, 0x72, 0xce, + 0x90, 0x86, 0x4f, 0xb7, 0x51, 0xde, 0x52, 0xc4, + 0x64, 0xd3, 0x6a, 0x10, 0x72, 0xe7, 0x76, 0x01, + 0x80, 0x06, 0x86, 0x5c, 0x86, 0xef, 0x8d, 0x32, + 0x97, 0x6f, 0x9b, 0xfa, 0x9d, 0x8c, 0x78, 0x7f, + 0x79, 0xa0, 0x7d, 0xc9, 0x83, 0x04, 0x93, 0x7f, + 0x9e, 0xd6, 0x8a, 0xdf, 0x58, 0x04, 0x5f, 0x60, + 0x7c, 0x7e, 0x80, 0x62, 0x72, 0xca, 0x78, 0xc2, + 0x8c, 0xf7, 0x96, 0xd8, 0x58, 0x62, 0x5c, 0x13, + 0x6a, 0xda, 0x6d, 0x0f, 0x6f, 0x2f, 0x7d, 0x37, + 0x7e, 0x4b, 0x96, 0xd2, 0x52, 0x8b, 0x80, 0xdc, + 0x51, 0xcc, 0x51, 0x1c, 0x7a, 0xbe, 0x7d, 0xf1, + 0x83, 0x75, 0x96, 0x80, 0x8b, 0xcf, 0x62, 0x02, + 0x6a, 0xfe, 0x8a, 0x39, 0x4e, 0xe7, 0x5b, 0x12, + 0x60, 0x87, 0x73, 0x70, 0x75, 0x17, 0x53, 0xfb, + 0x78, 0xbf, 0x4f, 0xa9, 0x5f, 0x0d, 0x4e, 0xcc, + 0x6c, 0x78, 0x65, 0x22, 0x7d, 0xc3, 0x53, 0x5e, + 0x58, 0x01, 0x77, 0x49, 0x84, 0xaa, 0x8a, 0xba, + 0x6b, 0xb0, 0x8f, 0x88, 0x6c, 0xfe, 0x62, 0xe5, + 0x82, 0xa0, 0x63, 0x65, 0x75, 0xae, 0x4e, 0x69, + 0x51, 0xc9, 0x51, 0x81, 0x68, 0xe7, 0x7c, 0x6f, + 0x82, 0xd2, 0x8a, 0xcf, 0x91, 0xf5, 0x52, 0x42, + 0x54, 0x73, 0x59, 0xec, 0x5e, 0xc5, 0x65, 0xfe, + 0x6f, 0x2a, 0x79, 0xad, 0x95, 0x6a, 0x9a, 0x97, + 0x9e, 0xce, 0x9e, 0x9b, 0x52, 0xc6, 0x66, 0x77, + 0x6b, 0x62, 0x8f, 0x74, 0x5e, 0x90, 0x61, 0x00, + 0x62, 0x9a, 0x64, 0x23, 0x6f, 0x49, 0x71, 0x89, + 0x74, 0xca, 0x79, 0xf4, 0x7d, 0x6f, 0x80, 0x26, + 0x8f, 0xee, 0x84, 0x23, 0x90, 0x4a, 0x93, 0x17, + 0x52, 0xa3, 0x52, 0xbd, 0x54, 0xc8, 0x70, 0xc2, + 0x88, 0xaa, 0x8a, 0xc9, 0x5e, 0xf5, 0x5f, 0x7b, + 0x63, 0xae, 0x6b, 0x3e, 0x7c, 0x75, 0x73, 0xe4, + 0x4e, 0xf9, 0x56, 0xe7, 0x5b, 0xba, 0x5d, 0x1c, + 0x60, 0xb2, 0x73, 0x69, 0x74, 0x9a, 0x7f, 0x46, + 0x80, 0x34, 0x92, 0xf6, 0x96, 0x48, 0x97, 0x18, + 0x98, 0x8b, 0x4f, 0xae, 0x79, 0xb4, 0x91, 0xb8, + 0x96, 0xe1, 0x60, 0x86, 0x4e, 0xda, 0x50, 0xee, + 0x5b, 0x3f, 0x5c, 0x99, 0x65, 0x02, 0x6a, 0xce, + 0x71, 0x42, 0x76, 0xfc, 0x84, 0x7c, 0x90, 0x8d, + 0x9f, 0x88, 0x66, 0x2e, 0x96, 0x89, 0x52, 0x7b, + 0x67, 0xf3, 0x67, 0x41, 0x6d, 0x9c, 0x6e, 0x09, + 0x74, 0x59, 0x75, 0x6b, 0x78, 0x10, 0x7d, 0x5e, + 0x98, 0x6d, 0x51, 0x2e, 0x62, 0x78, 0x96, 0x2b, + 0x50, 0x19, 0x5d, 0xea, 0x6d, 0x2a, 0x8f, 0x8b, + 0x5f, 0x44, 0x61, 0x17, 0x68, 0x87, 0x73, 0x86, + 0x96, 0x29, 0x52, 0x0f, 0x54, 0x65, 0x5c, 0x13, + 0x66, 0x4e, 0x67, 0xa8, 0x68, 0xe5, 0x6c, 0x06, + 0x74, 0xe2, 0x75, 0x79, 0x7f, 0xcf, 0x88, 0xe1, + 0x88, 0xcc, 0x91, 0xe2, 0x96, 0x3f, 0x53, 0xba, + 0x6e, 0x1d, 0x54, 0xd0, 0x71, 0x98, 0x74, 0xfa, + 0x85, 0xa3, 0x96, 0x57, 0x9c, 0x9f, 0x9e, 0x97, + 0x67, 0xcb, 0x6d, 0xe8, 0x81, 0xcb, 0x7a, 0x20, + 0x7b, 0x92, 0x7c, 0xc0, 0x72, 0x99, 0x70, 0x58, + 0x8b, 0xc0, 0x4e, 0x36, 0x83, 0x3a, 0x52, 0x07, + 0x52, 0xa6, 0x5e, 0xd3, 0x62, 0xd6, 0x7c, 0x85, + 0x5b, 0x1e, 0x6d, 0xb4, 0x66, 0x3b, 0x8f, 0x4c, + 0x88, 0x4d, 0x96, 0x8b, 0x89, 0xd3, 0x5e, 0x40, + 0x51, 0xc0, 0x55, 0x00, 0x00, 0x00, 0x00, 0x5a, + 0x58, 0x00, 0x00, 0x74, 0x66, 0x00, 0x00, 0x00, + 0x00, 0xde, 0x51, 0x2a, 0x73, 0xca, 0x76, 0x3c, + 0x79, 0x5e, 0x79, 0x65, 0x79, 0x8f, 0x79, 0x56, + 0x97, 0xbe, 0x7c, 0xbd, 0x7f, 0x00, 0x00, 0x12, + 0x86, 0x00, 0x00, 0xf8, 0x8a, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x90, 0xfd, 0x90, 0xef, 0x98, 0xfc, + 0x98, 0x28, 0x99, 0xb4, 0x9d, 0xde, 0x90, 0xb7, + 0x96, 0xae, 0x4f, 0xe7, 0x50, 0x4d, 0x51, 0xc9, + 0x52, 0xe4, 0x52, 0x51, 0x53, 0x9d, 0x55, 0x06, + 0x56, 0x68, 0x56, 0x40, 0x58, 0xa8, 0x58, 0x64, + 0x5c, 0x6e, 0x5c, 0x94, 0x60, 0x68, 0x61, 0x8e, + 0x61, 0xf2, 0x61, 0x4f, 0x65, 0xe2, 0x65, 0x91, + 0x66, 0x85, 0x68, 0x77, 0x6d, 0x1a, 0x6e, 0x22, + 0x6f, 0x6e, 0x71, 0x2b, 0x72, 0x22, 0x74, 0x91, + 0x78, 0x3e, 0x79, 0x49, 0x79, 0x48, 0x79, 0x50, + 0x79, 0x56, 0x79, 0x5d, 0x79, 0x8d, 0x79, 0x8e, + 0x79, 0x40, 0x7a, 0x81, 0x7a, 0xc0, 0x7b, 0xf4, + 0x7d, 0x09, 0x7e, 0x41, 0x7e, 0x72, 0x7f, 0x05, + 0x80, 0xed, 0x81, 0x79, 0x82, 0x79, 0x82, 0x57, + 0x84, 0x10, 0x89, 0x96, 0x89, 0x01, 0x8b, 0x39, + 0x8b, 0xd3, 0x8c, 0x08, 0x8d, 0xb6, 0x8f, 0x38, + 0x90, 0xe3, 0x96, 0xff, 0x97, 0x3b, 0x98, 0x75, + 0x60, 0xee, 0x42, 0x18, 0x82, 0x02, 0x26, 0x4e, + 0xb5, 0x51, 0x68, 0x51, 0x80, 0x4f, 0x45, 0x51, + 0x80, 0x51, 0xc7, 0x52, 0xfa, 0x52, 0x9d, 0x55, + 0x55, 0x55, 0x99, 0x55, 0xe2, 0x55, 0x5a, 0x58, + 0xb3, 0x58, 0x44, 0x59, 0x54, 0x59, 0x62, 0x5a, + 0x28, 0x5b, 0xd2, 0x5e, 0xd9, 0x5e, 0x69, 0x5f, + 0xad, 0x5f, 0xd8, 0x60, 0x4e, 0x61, 0x08, 0x61, + 0x8e, 0x61, 0x60, 0x61, 0xf2, 0x61, 0x34, 0x62, + 0xc4, 0x63, 0x1c, 0x64, 0x52, 0x64, 0x56, 0x65, + 0x74, 0x66, 0x17, 0x67, 0x1b, 0x67, 0x56, 0x67, + 0x79, 0x6b, 0xba, 0x6b, 0x41, 0x6d, 0xdb, 0x6e, + 0xcb, 0x6e, 0x22, 0x6f, 0x1e, 0x70, 0x6e, 0x71, + 0xa7, 0x77, 0x35, 0x72, 0xaf, 0x72, 0x2a, 0x73, + 0x71, 0x74, 0x06, 0x75, 0x3b, 0x75, 0x1d, 0x76, + 0x1f, 0x76, 0xca, 0x76, 0xdb, 0x76, 0xf4, 0x76, + 0x4a, 0x77, 0x40, 0x77, 0xcc, 0x78, 0xb1, 0x7a, + 0xc0, 0x7b, 0x7b, 0x7c, 0x5b, 0x7d, 0xf4, 0x7d, + 0x3e, 0x7f, 0x05, 0x80, 0x52, 0x83, 0xef, 0x83, + 0x79, 0x87, 0x41, 0x89, 0x86, 0x89, 0x96, 0x89, + 0xbf, 0x8a, 0xf8, 0x8a, 0xcb, 0x8a, 0x01, 0x8b, + 0xfe, 0x8a, 0xed, 0x8a, 0x39, 0x8b, 0x8a, 0x8b, + 0x08, 0x8d, 0x38, 0x8f, 0x72, 0x90, 0x99, 0x91, + 0x76, 0x92, 0x7c, 0x96, 0xe3, 0x96, 0x56, 0x97, + 0xdb, 0x97, 0xff, 0x97, 0x0b, 0x98, 0x3b, 0x98, + 0x12, 0x9b, 0x9c, 0x9f, 0x4a, 0x28, 0x44, 0x28, + 0xd5, 0x33, 0x9d, 0x3b, 0x18, 0x40, 0x39, 0x40, + 0x49, 0x52, 0xd0, 0x5c, 0xd3, 0x7e, 0x43, 0x9f, + 0x8e, 0x9f, 0x2a, 0xa0, 0x02, 0x66, 0x66, 0x66, + 0x69, 0x66, 0x6c, 0x66, 0x66, 0x69, 0x66, 0x66, + 0x6c, 0x7f, 0x01, 0x74, 0x73, 0x00, 0x74, 0x65, + 0x05, 0x0f, 0x11, 0x0f, 0x00, 0x0f, 0x06, 0x19, + 0x11, 0x0f, 0x08, 0xd9, 0x05, 0xb4, 0x05, 0x00, + 0x00, 0x00, 0x00, 0xf2, 0x05, 0xb7, 0x05, 0xd0, + 0x05, 0x12, 0x00, 0x03, 0x04, 0x0b, 0x0c, 0x0d, + 0x18, 0x1a, 0xe9, 0x05, 0xc1, 0x05, 0xe9, 0x05, + 0xc2, 0x05, 0x49, 0xfb, 0xc1, 0x05, 0x49, 0xfb, + 0xc2, 0x05, 0xd0, 0x05, 0xb7, 0x05, 0xd0, 0x05, + 0xb8, 0x05, 0xd0, 0x05, 0xbc, 0x05, 0xd8, 0x05, + 0xbc, 0x05, 0xde, 0x05, 0xbc, 0x05, 0xe0, 0x05, + 0xbc, 0x05, 0xe3, 0x05, 0xbc, 0x05, 0xb9, 0x05, + 0x2d, 0x03, 0x2e, 0x03, 0x2f, 0x03, 0x30, 0x03, + 0x31, 0x03, 0x1c, 0x00, 0x18, 0x06, 0x22, 0x06, + 0x2b, 0x06, 0xd0, 0x05, 0xdc, 0x05, 0x71, 0x06, + 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0f, 0x0f, 0x0f, 0x0f, 0x09, 0x09, + 0x09, 0x09, 0x0e, 0x0e, 0x0e, 0x0e, 0x08, 0x08, + 0x08, 0x08, 0x33, 0x33, 0x33, 0x33, 0x35, 0x35, + 0x35, 0x35, 0x13, 0x13, 0x13, 0x13, 0x12, 0x12, + 0x12, 0x12, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, + 0x16, 0x16, 0x1c, 0x1c, 0x1b, 0x1b, 0x1d, 0x1d, + 0x17, 0x17, 0x27, 0x27, 0x20, 0x20, 0x38, 0x38, + 0x38, 0x38, 0x3e, 0x3e, 0x3e, 0x3e, 0x42, 0x42, + 0x42, 0x42, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, + 0x4a, 0x4a, 0x4a, 0x4a, 0x4f, 0x4f, 0x50, 0x50, + 0x50, 0x50, 0x4d, 0x4d, 0x4d, 0x4d, 0x61, 0x61, + 0x62, 0x62, 0x49, 0x06, 0x64, 0x64, 0x64, 0x64, + 0x7e, 0x7e, 0x7d, 0x7d, 0x7f, 0x7f, 0x2e, 0x82, + 0x82, 0x7c, 0x7c, 0x80, 0x80, 0x87, 0x87, 0x87, + 0x87, 0x00, 0x00, 0x26, 0x06, 0x00, 0x01, 0x00, + 0x01, 0x00, 0xaf, 0x00, 0xaf, 0x00, 0x22, 0x00, + 0x22, 0x00, 0xa1, 0x00, 0xa1, 0x00, 0xa0, 0x00, + 0xa0, 0x00, 0xa2, 0x00, 0xa2, 0x00, 0xaa, 0x00, + 0xaa, 0x00, 0xaa, 0x00, 0x23, 0x00, 0x23, 0x00, + 0x23, 0xcc, 0x06, 0x00, 0x00, 0x00, 0x00, 0x26, + 0x06, 0x00, 0x06, 0x00, 0x07, 0x00, 0x1f, 0x00, + 0x23, 0x00, 0x24, 0x02, 0x06, 0x02, 0x07, 0x02, + 0x08, 0x02, 0x1f, 0x02, 0x23, 0x02, 0x24, 0x04, + 0x06, 0x04, 0x07, 0x04, 0x08, 0x04, 0x1f, 0x04, + 0x23, 0x04, 0x24, 0x05, 0x06, 0x05, 0x1f, 0x05, + 0x23, 0x05, 0x24, 0x06, 0x07, 0x06, 0x1f, 0x07, + 0x06, 0x07, 0x1f, 0x08, 0x06, 0x08, 0x07, 0x08, + 0x1f, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x08, 0x0d, + 0x1f, 0x0f, 0x07, 0x0f, 0x1f, 0x10, 0x06, 0x10, + 0x07, 0x10, 0x08, 0x10, 0x1f, 0x11, 0x07, 0x11, + 0x1f, 0x12, 0x1f, 0x13, 0x06, 0x13, 0x1f, 0x14, + 0x06, 0x14, 0x1f, 0x1b, 0x06, 0x1b, 0x07, 0x1b, + 0x08, 0x1b, 0x1f, 0x1b, 0x23, 0x1b, 0x24, 0x1c, + 0x07, 0x1c, 0x1f, 0x1c, 0x23, 0x1c, 0x24, 0x1d, + 0x01, 0x1d, 0x06, 0x1d, 0x07, 0x1d, 0x08, 0x1d, + 0x1e, 0x1d, 0x1f, 0x1d, 0x23, 0x1d, 0x24, 0x1e, + 0x06, 0x1e, 0x07, 0x1e, 0x08, 0x1e, 0x1f, 0x1e, + 0x23, 0x1e, 0x24, 0x1f, 0x06, 0x1f, 0x07, 0x1f, + 0x08, 0x1f, 0x1f, 0x1f, 0x23, 0x1f, 0x24, 0x20, 0x06, 0x20, 0x07, 0x20, 0x08, 0x20, 0x1f, 0x20, - 0x21, 0x21, 0x06, 0x21, 0x1f, 0x21, 0x4a, 0x24, - 0x06, 0x24, 0x07, 0x24, 0x08, 0x24, 0x1f, 0x24, - 0x21, 0x00, 0x1f, 0x00, 0x21, 0x02, 0x1f, 0x02, - 0x21, 0x04, 0x1f, 0x04, 0x21, 0x05, 0x1f, 0x05, - 0x21, 0x0d, 0x1f, 0x0d, 0x21, 0x0e, 0x1f, 0x0e, - 0x21, 0x1d, 0x1e, 0x1d, 0x1f, 0x1e, 0x1f, 0x20, - 0x1f, 0x20, 0x21, 0x24, 0x1f, 0x24, 0x21, 0x40, - 0x06, 0x4e, 0x06, 0x51, 0x06, 0x27, 0x06, 0x10, - 0x22, 0x10, 0x23, 0x12, 0x22, 0x12, 0x23, 0x13, - 0x22, 0x13, 0x23, 0x0c, 0x22, 0x0c, 0x23, 0x0d, - 0x22, 0x0d, 0x23, 0x06, 0x22, 0x06, 0x23, 0x05, - 0x22, 0x05, 0x23, 0x07, 0x22, 0x07, 0x23, 0x0e, - 0x22, 0x0e, 0x23, 0x0f, 0x22, 0x0f, 0x23, 0x0d, - 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x1e, 0x0d, - 0x0a, 0x0c, 0x0a, 0x0e, 0x0a, 0x0f, 0x0a, 0x10, - 0x22, 0x10, 0x23, 0x12, 0x22, 0x12, 0x23, 0x13, - 0x22, 0x13, 0x23, 0x0c, 0x22, 0x0c, 0x23, 0x0d, - 0x22, 0x0d, 0x23, 0x06, 0x22, 0x06, 0x23, 0x05, - 0x22, 0x05, 0x23, 0x07, 0x22, 0x07, 0x23, 0x0e, - 0x22, 0x0e, 0x23, 0x0f, 0x22, 0x0f, 0x23, 0x0d, - 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x1e, 0x0d, - 0x0a, 0x0c, 0x0a, 0x0e, 0x0a, 0x0f, 0x0a, 0x0d, - 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x1e, 0x0c, - 0x20, 0x0d, 0x20, 0x10, 0x1e, 0x0c, 0x05, 0x0c, - 0x06, 0x0c, 0x07, 0x0d, 0x05, 0x0d, 0x06, 0x0d, - 0x07, 0x10, 0x1e, 0x11, 0x1e, 0x00, 0x24, 0x00, - 0x24, 0x2a, 0x06, 0x00, 0x02, 0x1b, 0x00, 0x03, - 0x02, 0x00, 0x03, 0x02, 0x00, 0x03, 0x1b, 0x00, - 0x04, 0x1b, 0x00, 0x1b, 0x02, 0x00, 0x1b, 0x03, - 0x00, 0x1b, 0x04, 0x02, 0x1b, 0x03, 0x02, 0x1b, - 0x03, 0x03, 0x1b, 0x20, 0x03, 0x1b, 0x1f, 0x09, - 0x03, 0x02, 0x09, 0x02, 0x03, 0x09, 0x02, 0x1f, - 0x09, 0x1b, 0x03, 0x09, 0x1b, 0x03, 0x09, 0x1b, - 0x02, 0x09, 0x1b, 0x1b, 0x09, 0x1b, 0x1b, 0x0b, - 0x03, 0x03, 0x0b, 0x03, 0x03, 0x0b, 0x1b, 0x1b, - 0x0a, 0x03, 0x1b, 0x0a, 0x03, 0x1b, 0x0a, 0x02, - 0x20, 0x0a, 0x1b, 0x04, 0x0a, 0x1b, 0x04, 0x0a, - 0x1b, 0x1b, 0x0a, 0x1b, 0x1b, 0x0c, 0x03, 0x1f, - 0x0c, 0x04, 0x1b, 0x0c, 0x04, 0x1b, 0x0d, 0x1b, - 0x03, 0x0d, 0x1b, 0x03, 0x0d, 0x1b, 0x1b, 0x0d, - 0x1b, 0x20, 0x0f, 0x02, 0x1b, 0x0f, 0x1b, 0x1b, - 0x0f, 0x1b, 0x1b, 0x0f, 0x1b, 0x1f, 0x10, 0x1b, - 0x1b, 0x10, 0x1b, 0x20, 0x10, 0x1b, 0x1f, 0x17, - 0x04, 0x1b, 0x17, 0x04, 0x1b, 0x18, 0x1b, 0x03, - 0x18, 0x1b, 0x1b, 0x1a, 0x03, 0x1b, 0x1a, 0x03, - 0x20, 0x1a, 0x03, 0x1f, 0x1a, 0x02, 0x02, 0x1a, - 0x02, 0x02, 0x1a, 0x04, 0x1b, 0x1a, 0x04, 0x1b, - 0x1a, 0x1b, 0x03, 0x1a, 0x1b, 0x03, 0x1b, 0x03, - 0x02, 0x1b, 0x03, 0x1b, 0x1b, 0x03, 0x20, 0x1b, - 0x02, 0x03, 0x1b, 0x02, 0x1b, 0x1b, 0x04, 0x02, - 0x1b, 0x04, 0x1b, 0x28, 0x06, 0x1d, 0x04, 0x06, - 0x1f, 0x1d, 0x04, 0x1f, 0x1d, 0x1d, 0x1e, 0x05, - 0x1d, 0x1e, 0x05, 0x21, 0x1e, 0x04, 0x1d, 0x1e, - 0x04, 0x1d, 0x1e, 0x04, 0x21, 0x1e, 0x1d, 0x22, - 0x1e, 0x1d, 0x21, 0x22, 0x1d, 0x1d, 0x22, 0x1d, - 0x1d, 0x00, 0x06, 0x22, 0x02, 0x04, 0x22, 0x02, - 0x04, 0x21, 0x02, 0x06, 0x22, 0x02, 0x06, 0x21, - 0x02, 0x1d, 0x22, 0x02, 0x1d, 0x21, 0x04, 0x1d, - 0x22, 0x04, 0x05, 0x21, 0x04, 0x1d, 0x21, 0x0b, - 0x06, 0x21, 0x0d, 0x05, 0x22, 0x0c, 0x05, 0x22, - 0x0e, 0x05, 0x22, 0x1c, 0x04, 0x22, 0x1c, 0x1d, - 0x22, 0x22, 0x05, 0x22, 0x22, 0x04, 0x22, 0x22, - 0x1d, 0x22, 0x1d, 0x1d, 0x22, 0x1a, 0x1d, 0x22, - 0x1e, 0x05, 0x22, 0x1a, 0x1d, 0x05, 0x1c, 0x05, - 0x1d, 0x11, 0x1d, 0x22, 0x1b, 0x1d, 0x22, 0x1e, - 0x04, 0x05, 0x1d, 0x06, 0x22, 0x1c, 0x04, 0x1d, - 0x1b, 0x1d, 0x1d, 0x1c, 0x04, 0x1d, 0x1e, 0x04, - 0x05, 0x04, 0x05, 0x22, 0x05, 0x04, 0x22, 0x1d, - 0x04, 0x22, 0x19, 0x1d, 0x22, 0x00, 0x05, 0x22, - 0x1b, 0x1d, 0x1d, 0x11, 0x04, 0x1d, 0x0d, 0x1d, - 0x1d, 0x0b, 0x06, 0x22, 0x1e, 0x04, 0x22, 0x35, - 0x06, 0x00, 0x0f, 0x9d, 0x0d, 0x0f, 0x9d, 0x27, - 0x06, 0x00, 0x1d, 0x1d, 0x20, 0x00, 0x1c, 0x01, - 0x0a, 0x1e, 0x06, 0x1e, 0x08, 0x0e, 0x1d, 0x12, - 0x1e, 0x0a, 0x0c, 0x21, 0x1d, 0x12, 0x1d, 0x23, - 0x20, 0x21, 0x0c, 0x1d, 0x1e, 0x35, 0x06, 0x00, - 0x0f, 0x14, 0x27, 0x06, 0x0e, 0x1d, 0x22, 0xff, - 0x00, 0x1d, 0x1d, 0x20, 0xff, 0x12, 0x1d, 0x23, - 0x20, 0xff, 0x21, 0x0c, 0x1d, 0x1e, 0x27, 0x06, - 0x05, 0x1d, 0xff, 0x05, 0x1d, 0x00, 0x1d, 0x20, - 0x27, 0x06, 0x0a, 0xa5, 0x00, 0x1d, 0x2c, 0x00, - 0x01, 0x30, 0x02, 0x30, 0x3a, 0x00, 0x3b, 0x00, - 0x21, 0x00, 0x3f, 0x00, 0x16, 0x30, 0x17, 0x30, - 0x26, 0x20, 0x13, 0x20, 0x12, 0x01, 0x00, 0x5f, - 0x5f, 0x28, 0x29, 0x7b, 0x7d, 0x08, 0x30, 0x0c, - 0x0d, 0x08, 0x09, 0x02, 0x03, 0x00, 0x01, 0x04, - 0x05, 0x06, 0x07, 0x5b, 0x00, 0x5d, 0x00, 0x3e, - 0x20, 0x3e, 0x20, 0x3e, 0x20, 0x3e, 0x20, 0x5f, - 0x00, 0x5f, 0x00, 0x5f, 0x00, 0x2c, 0x00, 0x01, - 0x30, 0x2e, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x3a, - 0x00, 0x3f, 0x00, 0x21, 0x00, 0x14, 0x20, 0x28, - 0x00, 0x29, 0x00, 0x7b, 0x00, 0x7d, 0x00, 0x14, - 0x30, 0x15, 0x30, 0x23, 0x26, 0x2a, 0x2b, 0x2d, - 0x3c, 0x3e, 0x3d, 0x00, 0x5c, 0x24, 0x25, 0x40, - 0x40, 0x06, 0xff, 0x0b, 0x00, 0x0b, 0xff, 0x0c, - 0x20, 0x00, 0x4d, 0x06, 0x40, 0x06, 0xff, 0x0e, - 0x00, 0x0e, 0xff, 0x0f, 0x00, 0x0f, 0xff, 0x10, - 0x00, 0x10, 0xff, 0x11, 0x00, 0x11, 0xff, 0x12, - 0x00, 0x12, 0x21, 0x06, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x05, - 0x05, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, - 0x08, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, - 0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x12, - 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, - 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, - 0x16, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, - 0x18, 0x19, 0x19, 0x19, 0x19, 0x20, 0x20, 0x20, - 0x20, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, - 0x22, 0x23, 0x23, 0x23, 0x23, 0x24, 0x24, 0x24, - 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26, - 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x29, - 0x29, 0x22, 0x06, 0x22, 0x00, 0x22, 0x00, 0x22, - 0x01, 0x22, 0x01, 0x22, 0x03, 0x22, 0x03, 0x22, - 0x05, 0x22, 0x05, 0x21, 0x00, 0x85, 0x29, 0x01, - 0x30, 0x01, 0x0b, 0x0c, 0x00, 0xfa, 0xf1, 0xa0, - 0xa2, 0xa4, 0xa6, 0xa8, 0xe2, 0xe4, 0xe6, 0xc2, - 0xfb, 0xa1, 0xa3, 0xa5, 0xa7, 0xa9, 0xaa, 0xac, - 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, - 0xbe, 0xc0, 0xc3, 0xc5, 0xc7, 0xc9, 0xca, 0xcb, - 0xcc, 0xcd, 0xce, 0xd1, 0xd4, 0xd7, 0xda, 0xdd, - 0xde, 0xdf, 0xe0, 0xe1, 0xe3, 0xe5, 0xe7, 0xe8, - 0xe9, 0xea, 0xeb, 0xec, 0xee, 0xf2, 0x98, 0x99, - 0x31, 0x31, 0x4f, 0x31, 0x55, 0x31, 0x5b, 0x31, - 0x61, 0x31, 0xa2, 0x00, 0xa3, 0x00, 0xac, 0x00, - 0xaf, 0x00, 0xa6, 0x00, 0xa5, 0x00, 0xa9, 0x20, - 0x00, 0x00, 0x02, 0x25, 0x90, 0x21, 0x91, 0x21, - 0x92, 0x21, 0x93, 0x21, 0xa0, 0x25, 0xcb, 0x25, - 0xd2, 0x05, 0x07, 0x03, 0x01, 0xda, 0x05, 0x07, - 0x03, 0x01, 0xd0, 0x02, 0xd1, 0x02, 0xe6, 0x00, - 0x99, 0x02, 0x53, 0x02, 0x00, 0x00, 0xa3, 0x02, - 0x66, 0xab, 0xa5, 0x02, 0xa4, 0x02, 0x56, 0x02, - 0x57, 0x02, 0x91, 0x1d, 0x58, 0x02, 0x5e, 0x02, - 0xa9, 0x02, 0x64, 0x02, 0x62, 0x02, 0x60, 0x02, - 0x9b, 0x02, 0x27, 0x01, 0x9c, 0x02, 0x67, 0x02, - 0x84, 0x02, 0xaa, 0x02, 0xab, 0x02, 0x6c, 0x02, - 0x04, 0xdf, 0x8e, 0xa7, 0x6e, 0x02, 0x05, 0xdf, - 0x8e, 0x02, 0x06, 0xdf, 0xf8, 0x00, 0x76, 0x02, - 0x77, 0x02, 0x71, 0x00, 0x7a, 0x02, 0x08, 0xdf, - 0x7d, 0x02, 0x7e, 0x02, 0x80, 0x02, 0xa8, 0x02, - 0xa6, 0x02, 0x67, 0xab, 0xa7, 0x02, 0x88, 0x02, - 0x71, 0x2c, 0x00, 0x00, 0x8f, 0x02, 0xa1, 0x02, - 0xa2, 0x02, 0x98, 0x02, 0xc0, 0x01, 0xc1, 0x01, - 0xc2, 0x01, 0x0a, 0xdf, 0x1e, 0xdf, 0x41, 0x04, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x14, 0x99, 0x10, - 0xba, 0x10, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x10, - 0xba, 0x10, 0x05, 0x05, 0xa5, 0x10, 0xba, 0x10, - 0x05, 0x31, 0x11, 0x27, 0x11, 0x32, 0x11, 0x27, - 0x11, 0x55, 0x47, 0x13, 0x3e, 0x13, 0x47, 0x13, - 0x57, 0x13, 0x55, 0x82, 0x13, 0xc9, 0x13, 0x00, - 0x00, 0x00, 0x00, 0x84, 0x13, 0xbb, 0x13, 0x05, - 0x05, 0x8b, 0x13, 0xc2, 0x13, 0x05, 0x90, 0x13, - 0xc9, 0x13, 0x05, 0xc2, 0x13, 0xc2, 0x13, 0x00, - 0x00, 0x00, 0x00, 0xc2, 0x13, 0xb8, 0x13, 0xc2, - 0x13, 0xc9, 0x13, 0x05, 0x55, 0xb9, 0x14, 0xba, - 0x14, 0xb9, 0x14, 0xb0, 0x14, 0x00, 0x00, 0x00, - 0x00, 0xb9, 0x14, 0xbd, 0x14, 0x55, 0x50, 0xb8, - 0x15, 0xaf, 0x15, 0xb9, 0x15, 0xaf, 0x15, 0x55, - 0x35, 0x19, 0x30, 0x19, 0x05, 0x1e, 0x61, 0x1e, - 0x61, 0x1e, 0x61, 0x29, 0x61, 0x1e, 0x61, 0x1f, - 0x61, 0x29, 0x61, 0x1f, 0x61, 0x1e, 0x61, 0x20, - 0x61, 0x21, 0x61, 0x1f, 0x61, 0x22, 0x61, 0x1f, - 0x61, 0x21, 0x61, 0x20, 0x61, 0x55, 0x55, 0x55, - 0x55, 0x67, 0x6d, 0x67, 0x6d, 0x63, 0x6d, 0x67, - 0x6d, 0x69, 0x6d, 0x67, 0x6d, 0x55, 0x05, 0x41, - 0x00, 0x30, 0x00, 0x57, 0xd1, 0x65, 0xd1, 0x58, - 0xd1, 0x65, 0xd1, 0x5f, 0xd1, 0x6e, 0xd1, 0x5f, - 0xd1, 0x6f, 0xd1, 0x5f, 0xd1, 0x70, 0xd1, 0x5f, - 0xd1, 0x71, 0xd1, 0x5f, 0xd1, 0x72, 0xd1, 0x55, - 0x55, 0x55, 0x05, 0xb9, 0xd1, 0x65, 0xd1, 0xba, - 0xd1, 0x65, 0xd1, 0xbb, 0xd1, 0x6e, 0xd1, 0xbc, - 0xd1, 0x6e, 0xd1, 0xbb, 0xd1, 0x6f, 0xd1, 0xbc, - 0xd1, 0x6f, 0xd1, 0x55, 0x55, 0x55, 0x41, 0x00, - 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x69, 0x00, - 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x43, 0x44, - 0x00, 0x00, 0x47, 0x00, 0x00, 0x4a, 0x4b, 0x00, - 0x00, 0x4e, 0x4f, 0x50, 0x51, 0x00, 0x53, 0x54, - 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, - 0x63, 0x64, 0x00, 0x66, 0x68, 0x00, 0x70, 0x00, - 0x41, 0x00, 0x61, 0x00, 0x41, 0x42, 0x00, 0x44, - 0x45, 0x46, 0x47, 0x4a, 0x00, 0x53, 0x00, 0x61, - 0x00, 0x41, 0x42, 0x00, 0x44, 0x45, 0x46, 0x47, - 0x00, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x00, 0x4f, - 0x53, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, - 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, - 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, - 0x41, 0x00, 0x61, 0x00, 0x31, 0x01, 0x37, 0x02, - 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, - 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, - 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, - 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, - 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, - 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, - 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, - 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, - 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x0b, 0x0c, - 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, - 0x30, 0x00, 0x30, 0x04, 0x3a, 0x04, 0x3e, 0x04, - 0x4b, 0x04, 0x4d, 0x04, 0x4e, 0x04, 0x89, 0xa6, - 0x30, 0x04, 0xa9, 0x26, 0x28, 0xb9, 0x7f, 0x9f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x0a, 0x0b, 0x0e, 0x0f, 0x11, 0x13, 0x14, - 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x61, 0x26, - 0x25, 0x2f, 0x7b, 0x51, 0xa6, 0xb1, 0x04, 0x27, - 0x06, 0x00, 0x01, 0x05, 0x08, 0x2a, 0x06, 0x1e, - 0x08, 0x03, 0x0d, 0x20, 0x19, 0x1a, 0x1b, 0x1c, + 0x23, 0x20, 0x24, 0x21, 0x06, 0x21, 0x1f, 0x21, + 0x23, 0x21, 0x24, 0x24, 0x06, 0x24, 0x07, 0x24, + 0x08, 0x24, 0x1f, 0x24, 0x23, 0x24, 0x24, 0x0a, + 0x4a, 0x0b, 0x4a, 0x23, 0x4a, 0x20, 0x00, 0x4c, + 0x06, 0x51, 0x06, 0x51, 0x06, 0xff, 0x00, 0x1f, + 0x26, 0x06, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x1f, + 0x00, 0x20, 0x00, 0x23, 0x00, 0x24, 0x02, 0x0b, + 0x02, 0x0c, 0x02, 0x1f, 0x02, 0x20, 0x02, 0x23, + 0x02, 0x24, 0x04, 0x0b, 0x04, 0x0c, 0x04, 0x1f, + 0x26, 0x06, 0x04, 0x20, 0x04, 0x23, 0x04, 0x24, + 0x05, 0x0b, 0x05, 0x0c, 0x05, 0x1f, 0x05, 0x20, + 0x05, 0x23, 0x05, 0x24, 0x1b, 0x23, 0x1b, 0x24, + 0x1c, 0x23, 0x1c, 0x24, 0x1d, 0x01, 0x1d, 0x1e, + 0x1d, 0x1f, 0x1d, 0x23, 0x1d, 0x24, 0x1e, 0x1f, + 0x1e, 0x23, 0x1e, 0x24, 0x1f, 0x01, 0x1f, 0x1f, + 0x20, 0x0b, 0x20, 0x0c, 0x20, 0x1f, 0x20, 0x20, + 0x20, 0x23, 0x20, 0x24, 0x23, 0x4a, 0x24, 0x0b, + 0x24, 0x0c, 0x24, 0x1f, 0x24, 0x20, 0x24, 0x23, + 0x24, 0x24, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, + 0x00, 0x1f, 0x00, 0x21, 0x02, 0x06, 0x02, 0x07, + 0x02, 0x08, 0x02, 0x1f, 0x02, 0x21, 0x04, 0x06, + 0x04, 0x07, 0x04, 0x08, 0x04, 0x1f, 0x04, 0x21, + 0x05, 0x1f, 0x06, 0x07, 0x06, 0x1f, 0x07, 0x06, + 0x07, 0x1f, 0x08, 0x06, 0x08, 0x1f, 0x0d, 0x06, + 0x0d, 0x07, 0x0d, 0x08, 0x0d, 0x1f, 0x0f, 0x07, + 0x0f, 0x08, 0x0f, 0x1f, 0x10, 0x06, 0x10, 0x07, + 0x10, 0x08, 0x10, 0x1f, 0x11, 0x07, 0x12, 0x1f, + 0x13, 0x06, 0x13, 0x1f, 0x14, 0x06, 0x14, 0x1f, + 0x1b, 0x06, 0x1b, 0x07, 0x1b, 0x08, 0x1b, 0x1f, + 0x1c, 0x07, 0x1c, 0x1f, 0x1d, 0x06, 0x1d, 0x07, + 0x1d, 0x08, 0x1d, 0x1e, 0x1d, 0x1f, 0x1e, 0x06, + 0x1e, 0x07, 0x1e, 0x08, 0x1e, 0x1f, 0x1e, 0x21, + 0x1f, 0x06, 0x1f, 0x07, 0x1f, 0x08, 0x1f, 0x1f, + 0x20, 0x06, 0x20, 0x07, 0x20, 0x08, 0x20, 0x1f, + 0x20, 0x21, 0x21, 0x06, 0x21, 0x1f, 0x21, 0x4a, + 0x24, 0x06, 0x24, 0x07, 0x24, 0x08, 0x24, 0x1f, + 0x24, 0x21, 0x00, 0x1f, 0x00, 0x21, 0x02, 0x1f, + 0x02, 0x21, 0x04, 0x1f, 0x04, 0x21, 0x05, 0x1f, + 0x05, 0x21, 0x0d, 0x1f, 0x0d, 0x21, 0x0e, 0x1f, + 0x0e, 0x21, 0x1d, 0x1e, 0x1d, 0x1f, 0x1e, 0x1f, + 0x20, 0x1f, 0x20, 0x21, 0x24, 0x1f, 0x24, 0x21, + 0x40, 0x06, 0x4e, 0x06, 0x51, 0x06, 0x27, 0x06, + 0x10, 0x22, 0x10, 0x23, 0x12, 0x22, 0x12, 0x23, + 0x13, 0x22, 0x13, 0x23, 0x0c, 0x22, 0x0c, 0x23, + 0x0d, 0x22, 0x0d, 0x23, 0x06, 0x22, 0x06, 0x23, + 0x05, 0x22, 0x05, 0x23, 0x07, 0x22, 0x07, 0x23, + 0x0e, 0x22, 0x0e, 0x23, 0x0f, 0x22, 0x0f, 0x23, + 0x0d, 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x1e, + 0x0d, 0x0a, 0x0c, 0x0a, 0x0e, 0x0a, 0x0f, 0x0a, + 0x10, 0x22, 0x10, 0x23, 0x12, 0x22, 0x12, 0x23, + 0x13, 0x22, 0x13, 0x23, 0x0c, 0x22, 0x0c, 0x23, + 0x0d, 0x22, 0x0d, 0x23, 0x06, 0x22, 0x06, 0x23, + 0x05, 0x22, 0x05, 0x23, 0x07, 0x22, 0x07, 0x23, + 0x0e, 0x22, 0x0e, 0x23, 0x0f, 0x22, 0x0f, 0x23, + 0x0d, 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x1e, + 0x0d, 0x0a, 0x0c, 0x0a, 0x0e, 0x0a, 0x0f, 0x0a, + 0x0d, 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x1e, + 0x0c, 0x20, 0x0d, 0x20, 0x10, 0x1e, 0x0c, 0x05, + 0x0c, 0x06, 0x0c, 0x07, 0x0d, 0x05, 0x0d, 0x06, + 0x0d, 0x07, 0x10, 0x1e, 0x11, 0x1e, 0x00, 0x24, + 0x00, 0x24, 0x2a, 0x06, 0x00, 0x02, 0x1b, 0x00, + 0x03, 0x02, 0x00, 0x03, 0x02, 0x00, 0x03, 0x1b, + 0x00, 0x04, 0x1b, 0x00, 0x1b, 0x02, 0x00, 0x1b, + 0x03, 0x00, 0x1b, 0x04, 0x02, 0x1b, 0x03, 0x02, + 0x1b, 0x03, 0x03, 0x1b, 0x20, 0x03, 0x1b, 0x1f, + 0x09, 0x03, 0x02, 0x09, 0x02, 0x03, 0x09, 0x02, + 0x1f, 0x09, 0x1b, 0x03, 0x09, 0x1b, 0x03, 0x09, + 0x1b, 0x02, 0x09, 0x1b, 0x1b, 0x09, 0x1b, 0x1b, + 0x0b, 0x03, 0x03, 0x0b, 0x03, 0x03, 0x0b, 0x1b, + 0x1b, 0x0a, 0x03, 0x1b, 0x0a, 0x03, 0x1b, 0x0a, + 0x02, 0x20, 0x0a, 0x1b, 0x04, 0x0a, 0x1b, 0x04, + 0x0a, 0x1b, 0x1b, 0x0a, 0x1b, 0x1b, 0x0c, 0x03, + 0x1f, 0x0c, 0x04, 0x1b, 0x0c, 0x04, 0x1b, 0x0d, + 0x1b, 0x03, 0x0d, 0x1b, 0x03, 0x0d, 0x1b, 0x1b, + 0x0d, 0x1b, 0x20, 0x0f, 0x02, 0x1b, 0x0f, 0x1b, + 0x1b, 0x0f, 0x1b, 0x1b, 0x0f, 0x1b, 0x1f, 0x10, + 0x1b, 0x1b, 0x10, 0x1b, 0x20, 0x10, 0x1b, 0x1f, + 0x17, 0x04, 0x1b, 0x17, 0x04, 0x1b, 0x18, 0x1b, + 0x03, 0x18, 0x1b, 0x1b, 0x1a, 0x03, 0x1b, 0x1a, + 0x03, 0x20, 0x1a, 0x03, 0x1f, 0x1a, 0x02, 0x02, + 0x1a, 0x02, 0x02, 0x1a, 0x04, 0x1b, 0x1a, 0x04, + 0x1b, 0x1a, 0x1b, 0x03, 0x1a, 0x1b, 0x03, 0x1b, + 0x03, 0x02, 0x1b, 0x03, 0x1b, 0x1b, 0x03, 0x20, + 0x1b, 0x02, 0x03, 0x1b, 0x02, 0x1b, 0x1b, 0x04, + 0x02, 0x1b, 0x04, 0x1b, 0x28, 0x06, 0x1d, 0x04, + 0x06, 0x1f, 0x1d, 0x04, 0x1f, 0x1d, 0x1d, 0x1e, + 0x05, 0x1d, 0x1e, 0x05, 0x21, 0x1e, 0x04, 0x1d, + 0x1e, 0x04, 0x1d, 0x1e, 0x04, 0x21, 0x1e, 0x1d, + 0x22, 0x1e, 0x1d, 0x21, 0x22, 0x1d, 0x1d, 0x22, + 0x1d, 0x1d, 0x00, 0x06, 0x22, 0x02, 0x04, 0x22, + 0x02, 0x04, 0x21, 0x02, 0x06, 0x22, 0x02, 0x06, + 0x21, 0x02, 0x1d, 0x22, 0x02, 0x1d, 0x21, 0x04, + 0x1d, 0x22, 0x04, 0x05, 0x21, 0x04, 0x1d, 0x21, + 0x0b, 0x06, 0x21, 0x0d, 0x05, 0x22, 0x0c, 0x05, + 0x22, 0x0e, 0x05, 0x22, 0x1c, 0x04, 0x22, 0x1c, + 0x1d, 0x22, 0x22, 0x05, 0x22, 0x22, 0x04, 0x22, + 0x22, 0x1d, 0x22, 0x1d, 0x1d, 0x22, 0x1a, 0x1d, + 0x22, 0x1e, 0x05, 0x22, 0x1a, 0x1d, 0x05, 0x1c, + 0x05, 0x1d, 0x11, 0x1d, 0x22, 0x1b, 0x1d, 0x22, + 0x1e, 0x04, 0x05, 0x1d, 0x06, 0x22, 0x1c, 0x04, + 0x1d, 0x1b, 0x1d, 0x1d, 0x1c, 0x04, 0x1d, 0x1e, + 0x04, 0x05, 0x04, 0x05, 0x22, 0x05, 0x04, 0x22, + 0x1d, 0x04, 0x22, 0x19, 0x1d, 0x22, 0x00, 0x05, + 0x22, 0x1b, 0x1d, 0x1d, 0x11, 0x04, 0x1d, 0x0d, + 0x1d, 0x1d, 0x0b, 0x06, 0x22, 0x1e, 0x04, 0x22, + 0x35, 0x06, 0x00, 0x0f, 0x9d, 0x0d, 0x0f, 0x9d, + 0x27, 0x06, 0x00, 0x1d, 0x1d, 0x20, 0x00, 0x1c, + 0x01, 0x0a, 0x1e, 0x06, 0x1e, 0x08, 0x0e, 0x1d, + 0x12, 0x1e, 0x0a, 0x0c, 0x21, 0x1d, 0x12, 0x1d, + 0x23, 0x20, 0x21, 0x0c, 0x1d, 0x1e, 0x35, 0x06, + 0x00, 0x0f, 0x14, 0x27, 0x06, 0x0e, 0x1d, 0x22, + 0xff, 0x00, 0x1d, 0x1d, 0x20, 0xff, 0x12, 0x1d, + 0x23, 0x20, 0xff, 0x21, 0x0c, 0x1d, 0x1e, 0x27, + 0x06, 0x05, 0x1d, 0xff, 0x05, 0x1d, 0x00, 0x1d, + 0x20, 0x27, 0x06, 0x0a, 0xa5, 0x00, 0x1d, 0x2c, + 0x00, 0x01, 0x30, 0x02, 0x30, 0x3a, 0x00, 0x3b, + 0x00, 0x21, 0x00, 0x3f, 0x00, 0x16, 0x30, 0x17, + 0x30, 0x26, 0x20, 0x13, 0x20, 0x12, 0x01, 0x00, + 0x5f, 0x5f, 0x28, 0x29, 0x7b, 0x7d, 0x08, 0x30, + 0x0c, 0x0d, 0x08, 0x09, 0x02, 0x03, 0x00, 0x01, + 0x04, 0x05, 0x06, 0x07, 0x5b, 0x00, 0x5d, 0x00, + 0x3e, 0x20, 0x3e, 0x20, 0x3e, 0x20, 0x3e, 0x20, + 0x5f, 0x00, 0x5f, 0x00, 0x5f, 0x00, 0x2c, 0x00, + 0x01, 0x30, 0x2e, 0x00, 0x00, 0x00, 0x3b, 0x00, + 0x3a, 0x00, 0x3f, 0x00, 0x21, 0x00, 0x14, 0x20, + 0x28, 0x00, 0x29, 0x00, 0x7b, 0x00, 0x7d, 0x00, + 0x14, 0x30, 0x15, 0x30, 0x23, 0x26, 0x2a, 0x2b, + 0x2d, 0x3c, 0x3e, 0x3d, 0x00, 0x5c, 0x24, 0x25, + 0x40, 0x40, 0x06, 0xff, 0x0b, 0x00, 0x0b, 0xff, + 0x0c, 0x20, 0x00, 0x4d, 0x06, 0x40, 0x06, 0xff, + 0x0e, 0x00, 0x0e, 0xff, 0x0f, 0x00, 0x0f, 0xff, + 0x10, 0x00, 0x10, 0xff, 0x11, 0x00, 0x11, 0xff, + 0x12, 0x00, 0x12, 0x21, 0x06, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, + 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, + 0x0f, 0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, + 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, + 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, + 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, + 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x23, 0x23, 0x23, 0x24, 0x24, + 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, + 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, + 0x29, 0x29, 0x22, 0x06, 0x22, 0x00, 0x22, 0x00, + 0x22, 0x01, 0x22, 0x01, 0x22, 0x03, 0x22, 0x03, + 0x22, 0x05, 0x22, 0x05, 0x21, 0x00, 0x85, 0x29, + 0x01, 0x30, 0x01, 0x0b, 0x0c, 0x00, 0xfa, 0xf1, + 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xe2, 0xe4, 0xe6, + 0xc2, 0xfb, 0xa1, 0xa3, 0xa5, 0xa7, 0xa9, 0xaa, + 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, + 0xbc, 0xbe, 0xc0, 0xc3, 0xc5, 0xc7, 0xc9, 0xca, + 0xcb, 0xcc, 0xcd, 0xce, 0xd1, 0xd4, 0xd7, 0xda, + 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe3, 0xe5, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xee, 0xf2, 0x98, + 0x99, 0x31, 0x31, 0x4f, 0x31, 0x55, 0x31, 0x5b, + 0x31, 0x61, 0x31, 0xa2, 0x00, 0xa3, 0x00, 0xac, + 0x00, 0xaf, 0x00, 0xa6, 0x00, 0xa5, 0x00, 0xa9, + 0x20, 0x00, 0x00, 0x02, 0x25, 0x90, 0x21, 0x91, + 0x21, 0x92, 0x21, 0x93, 0x21, 0xa0, 0x25, 0xcb, + 0x25, 0xd2, 0x05, 0x07, 0x03, 0x01, 0xda, 0x05, + 0x07, 0x03, 0x01, 0xd0, 0x02, 0xd1, 0x02, 0xe6, + 0x00, 0x99, 0x02, 0x53, 0x02, 0x00, 0x00, 0xa3, + 0x02, 0x66, 0xab, 0xa5, 0x02, 0xa4, 0x02, 0x56, + 0x02, 0x57, 0x02, 0x91, 0x1d, 0x58, 0x02, 0x5e, + 0x02, 0xa9, 0x02, 0x64, 0x02, 0x62, 0x02, 0x60, + 0x02, 0x9b, 0x02, 0x27, 0x01, 0x9c, 0x02, 0x67, + 0x02, 0x84, 0x02, 0xaa, 0x02, 0xab, 0x02, 0x6c, + 0x02, 0x04, 0xdf, 0x8e, 0xa7, 0x6e, 0x02, 0x05, + 0xdf, 0x8e, 0x02, 0x06, 0xdf, 0xf8, 0x00, 0x76, + 0x02, 0x77, 0x02, 0x71, 0x00, 0x7a, 0x02, 0x08, + 0xdf, 0x7d, 0x02, 0x7e, 0x02, 0x80, 0x02, 0xa8, + 0x02, 0xa6, 0x02, 0x67, 0xab, 0xa7, 0x02, 0x88, + 0x02, 0x71, 0x2c, 0x00, 0x00, 0x8f, 0x02, 0xa1, + 0x02, 0xa2, 0x02, 0x98, 0x02, 0xc0, 0x01, 0xc1, + 0x01, 0xc2, 0x01, 0x0a, 0xdf, 0x1e, 0xdf, 0x41, + 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x14, 0x99, + 0x10, 0xba, 0x10, 0x00, 0x00, 0x00, 0x00, 0x9b, + 0x10, 0xba, 0x10, 0x05, 0x05, 0xa5, 0x10, 0xba, + 0x10, 0x05, 0x31, 0x11, 0x27, 0x11, 0x32, 0x11, + 0x27, 0x11, 0x55, 0x47, 0x13, 0x3e, 0x13, 0x47, + 0x13, 0x57, 0x13, 0x55, 0x82, 0x13, 0xc9, 0x13, + 0x00, 0x00, 0x00, 0x00, 0x84, 0x13, 0xbb, 0x13, + 0x05, 0x05, 0x8b, 0x13, 0xc2, 0x13, 0x05, 0x90, + 0x13, 0xc9, 0x13, 0x05, 0xc2, 0x13, 0xc2, 0x13, + 0x00, 0x00, 0x00, 0x00, 0xc2, 0x13, 0xb8, 0x13, + 0xc2, 0x13, 0xc9, 0x13, 0x05, 0x55, 0xb9, 0x14, + 0xba, 0x14, 0xb9, 0x14, 0xb0, 0x14, 0x00, 0x00, + 0x00, 0x00, 0xb9, 0x14, 0xbd, 0x14, 0x55, 0x50, + 0xb8, 0x15, 0xaf, 0x15, 0xb9, 0x15, 0xaf, 0x15, + 0x55, 0x35, 0x19, 0x30, 0x19, 0x05, 0x1e, 0x61, + 0x1e, 0x61, 0x1e, 0x61, 0x29, 0x61, 0x1e, 0x61, + 0x1f, 0x61, 0x29, 0x61, 0x1f, 0x61, 0x1e, 0x61, + 0x20, 0x61, 0x21, 0x61, 0x1f, 0x61, 0x22, 0x61, + 0x1f, 0x61, 0x21, 0x61, 0x20, 0x61, 0x55, 0x55, + 0x55, 0x55, 0x67, 0x6d, 0x67, 0x6d, 0x63, 0x6d, + 0x67, 0x6d, 0x69, 0x6d, 0x67, 0x6d, 0x55, 0x05, + 0x41, 0x00, 0x30, 0x00, 0x57, 0xd1, 0x65, 0xd1, + 0x58, 0xd1, 0x65, 0xd1, 0x5f, 0xd1, 0x6e, 0xd1, + 0x5f, 0xd1, 0x6f, 0xd1, 0x5f, 0xd1, 0x70, 0xd1, + 0x5f, 0xd1, 0x71, 0xd1, 0x5f, 0xd1, 0x72, 0xd1, + 0x55, 0x55, 0x55, 0x05, 0xb9, 0xd1, 0x65, 0xd1, + 0xba, 0xd1, 0x65, 0xd1, 0xbb, 0xd1, 0x6e, 0xd1, + 0xbc, 0xd1, 0x6e, 0xd1, 0xbb, 0xd1, 0x6f, 0xd1, + 0xbc, 0xd1, 0x6f, 0xd1, 0x55, 0x55, 0x55, 0x41, + 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x69, + 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x43, + 0x44, 0x00, 0x00, 0x47, 0x00, 0x00, 0x4a, 0x4b, + 0x00, 0x00, 0x4e, 0x4f, 0x50, 0x51, 0x00, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, + 0x62, 0x63, 0x64, 0x00, 0x66, 0x68, 0x00, 0x70, + 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x42, 0x00, + 0x44, 0x45, 0x46, 0x47, 0x4a, 0x00, 0x53, 0x00, + 0x61, 0x00, 0x41, 0x42, 0x00, 0x44, 0x45, 0x46, + 0x47, 0x00, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x00, + 0x4f, 0x53, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, + 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, + 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, + 0x00, 0x41, 0x00, 0x61, 0x00, 0x31, 0x01, 0x37, + 0x02, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, + 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, + 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, + 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, 0xa3, + 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, 0x1f, + 0x04, 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, + 0x03, 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, + 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, + 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x0b, + 0x0c, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, + 0x00, 0x30, 0x00, 0x30, 0x04, 0x3a, 0x04, 0x3e, + 0x04, 0x4b, 0x04, 0x4d, 0x04, 0x4e, 0x04, 0x89, + 0xa6, 0x30, 0x04, 0xa9, 0x26, 0x28, 0xb9, 0x7f, + 0x9f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x0a, 0x0b, 0x0e, 0x0f, 0x11, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x61, + 0x26, 0x25, 0x2f, 0x7b, 0x51, 0xa6, 0xb1, 0x04, + 0x27, 0x06, 0x00, 0x01, 0x05, 0x08, 0x2a, 0x06, + 0x1e, 0x08, 0x03, 0x0d, 0x20, 0x19, 0x1a, 0x1b, + 0x1c, 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, + 0x00, 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x44, + 0x90, 0x77, 0x45, 0x28, 0x06, 0x2c, 0x06, 0x00, + 0x00, 0x47, 0x06, 0x33, 0x06, 0x17, 0x10, 0x11, + 0x12, 0x13, 0x00, 0x06, 0x0e, 0x02, 0x0f, 0x34, + 0x06, 0x2a, 0x06, 0x2b, 0x06, 0x2e, 0x06, 0x00, + 0x00, 0x36, 0x06, 0x00, 0x00, 0x3a, 0x06, 0x2d, + 0x06, 0x00, 0x00, 0x4a, 0x06, 0x00, 0x00, 0x44, + 0x06, 0x00, 0x00, 0x46, 0x06, 0x33, 0x06, 0x39, + 0x06, 0x00, 0x00, 0x35, 0x06, 0x42, 0x06, 0x00, + 0x00, 0x34, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2e, + 0x06, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x3a, + 0x06, 0x00, 0x00, 0xba, 0x06, 0x00, 0x00, 0x6f, + 0x06, 0x00, 0x00, 0x28, 0x06, 0x2c, 0x06, 0x00, + 0x00, 0x47, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x06, 0x37, 0x06, 0x4a, 0x06, 0x43, 0x06, 0x00, + 0x00, 0x45, 0x06, 0x46, 0x06, 0x33, 0x06, 0x39, + 0x06, 0x41, 0x06, 0x35, 0x06, 0x42, 0x06, 0x00, + 0x00, 0x34, 0x06, 0x2a, 0x06, 0x2b, 0x06, 0x2e, + 0x06, 0x00, 0x00, 0x36, 0x06, 0x38, 0x06, 0x3a, + 0x06, 0x6e, 0x06, 0x00, 0x00, 0xa1, 0x06, 0x27, + 0x06, 0x00, 0x01, 0x05, 0x08, 0x20, 0x21, 0x0b, + 0x06, 0x10, 0x23, 0x2a, 0x06, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00, - 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x44, 0x90, - 0x77, 0x45, 0x28, 0x06, 0x2c, 0x06, 0x00, 0x00, - 0x47, 0x06, 0x33, 0x06, 0x17, 0x10, 0x11, 0x12, - 0x13, 0x00, 0x06, 0x0e, 0x02, 0x0f, 0x34, 0x06, - 0x2a, 0x06, 0x2b, 0x06, 0x2e, 0x06, 0x00, 0x00, - 0x36, 0x06, 0x00, 0x00, 0x3a, 0x06, 0x2d, 0x06, - 0x00, 0x00, 0x4a, 0x06, 0x00, 0x00, 0x44, 0x06, - 0x00, 0x00, 0x46, 0x06, 0x33, 0x06, 0x39, 0x06, - 0x00, 0x00, 0x35, 0x06, 0x42, 0x06, 0x00, 0x00, - 0x34, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x06, - 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x3a, 0x06, - 0x00, 0x00, 0xba, 0x06, 0x00, 0x00, 0x6f, 0x06, - 0x00, 0x00, 0x28, 0x06, 0x2c, 0x06, 0x00, 0x00, - 0x47, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x06, - 0x37, 0x06, 0x4a, 0x06, 0x43, 0x06, 0x00, 0x00, - 0x45, 0x06, 0x46, 0x06, 0x33, 0x06, 0x39, 0x06, - 0x41, 0x06, 0x35, 0x06, 0x42, 0x06, 0x00, 0x00, - 0x34, 0x06, 0x2a, 0x06, 0x2b, 0x06, 0x2e, 0x06, - 0x00, 0x00, 0x36, 0x06, 0x38, 0x06, 0x3a, 0x06, - 0x6e, 0x06, 0x00, 0x00, 0xa1, 0x06, 0x27, 0x06, - 0x00, 0x01, 0x05, 0x08, 0x20, 0x21, 0x0b, 0x06, - 0x10, 0x23, 0x2a, 0x06, 0x1a, 0x1b, 0x1c, 0x09, - 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00, 0x01, - 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x28, 0x06, 0x2c, - 0x06, 0x2f, 0x06, 0x00, 0x00, 0x48, 0x06, 0x32, - 0x06, 0x2d, 0x06, 0x37, 0x06, 0x4a, 0x06, 0x2a, - 0x06, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, 0x17, 0x0b, - 0x18, 0x07, 0x0a, 0x00, 0x01, 0x04, 0x06, 0x0c, - 0x0e, 0x10, 0x30, 0x2e, 0x30, 0x00, 0x2c, 0x00, - 0x28, 0x00, 0x41, 0x00, 0x29, 0x00, 0x14, 0x30, - 0x53, 0x00, 0x15, 0x30, 0x43, 0x52, 0x43, 0x44, - 0x57, 0x5a, 0x41, 0x00, 0x48, 0x56, 0x4d, 0x56, - 0x53, 0x44, 0x53, 0x53, 0x50, 0x50, 0x56, 0x57, - 0x43, 0x4d, 0x43, 0x4d, 0x44, 0x4d, 0x52, 0x44, - 0x4a, 0x4b, 0x30, 0x30, 0x00, 0x68, 0x68, 0x4b, - 0x62, 0x57, 0x5b, 0xcc, 0x53, 0xc7, 0x30, 0x8c, - 0x4e, 0x1a, 0x59, 0xe3, 0x89, 0x29, 0x59, 0xa4, - 0x4e, 0x20, 0x66, 0x21, 0x71, 0x99, 0x65, 0x4d, - 0x52, 0x8c, 0x5f, 0x8d, 0x51, 0xb0, 0x65, 0x1d, - 0x52, 0x42, 0x7d, 0x1f, 0x75, 0xa9, 0x8c, 0xf0, - 0x58, 0x39, 0x54, 0x14, 0x6f, 0x95, 0x62, 0x55, - 0x63, 0x00, 0x4e, 0x09, 0x4e, 0x4a, 0x90, 0xe6, - 0x5d, 0x2d, 0x4e, 0xf3, 0x53, 0x07, 0x63, 0x70, - 0x8d, 0x53, 0x62, 0x81, 0x79, 0x7a, 0x7a, 0x08, - 0x54, 0x80, 0x6e, 0x09, 0x67, 0x08, 0x67, 0x33, - 0x75, 0x72, 0x52, 0xb6, 0x55, 0x4d, 0x91, 0x14, - 0x30, 0x15, 0x30, 0x2c, 0x67, 0x09, 0x4e, 0x8c, - 0x4e, 0x89, 0x5b, 0xb9, 0x70, 0x53, 0x62, 0xd7, - 0x76, 0xdd, 0x52, 0x57, 0x65, 0x97, 0x5f, 0xef, - 0x53, 0x30, 0x00, 0x38, 0x4e, 0x05, 0x00, 0x09, - 0x22, 0x01, 0x60, 0x4f, 0xae, 0x4f, 0xbb, 0x4f, - 0x02, 0x50, 0x7a, 0x50, 0x99, 0x50, 0xe7, 0x50, - 0xcf, 0x50, 0x9e, 0x34, 0x3a, 0x06, 0x4d, 0x51, - 0x54, 0x51, 0x64, 0x51, 0x77, 0x51, 0x1c, 0x05, - 0xb9, 0x34, 0x67, 0x51, 0x8d, 0x51, 0x4b, 0x05, - 0x97, 0x51, 0xa4, 0x51, 0xcc, 0x4e, 0xac, 0x51, - 0xb5, 0x51, 0xdf, 0x91, 0xf5, 0x51, 0x03, 0x52, - 0xdf, 0x34, 0x3b, 0x52, 0x46, 0x52, 0x72, 0x52, - 0x77, 0x52, 0x15, 0x35, 0x02, 0x00, 0x20, 0x80, - 0x80, 0x00, 0x08, 0x00, 0x00, 0xc7, 0x52, 0x00, - 0x02, 0x1d, 0x33, 0x3e, 0x3f, 0x50, 0x82, 0x8a, - 0x93, 0xac, 0xb6, 0xb8, 0xb8, 0xb8, 0x2c, 0x0a, - 0x70, 0x70, 0xca, 0x53, 0xdf, 0x53, 0x63, 0x0b, - 0xeb, 0x53, 0xf1, 0x53, 0x06, 0x54, 0x9e, 0x54, - 0x38, 0x54, 0x48, 0x54, 0x68, 0x54, 0xa2, 0x54, - 0xf6, 0x54, 0x10, 0x55, 0x53, 0x55, 0x63, 0x55, - 0x84, 0x55, 0x84, 0x55, 0x99, 0x55, 0xab, 0x55, - 0xb3, 0x55, 0xc2, 0x55, 0x16, 0x57, 0x06, 0x56, - 0x17, 0x57, 0x51, 0x56, 0x74, 0x56, 0x07, 0x52, - 0xee, 0x58, 0xce, 0x57, 0xf4, 0x57, 0x0d, 0x58, - 0x8b, 0x57, 0x32, 0x58, 0x31, 0x58, 0xac, 0x58, - 0xe4, 0x14, 0xf2, 0x58, 0xf7, 0x58, 0x06, 0x59, - 0x1a, 0x59, 0x22, 0x59, 0x62, 0x59, 0xa8, 0x16, - 0xea, 0x16, 0xec, 0x59, 0x1b, 0x5a, 0x27, 0x5a, - 0xd8, 0x59, 0x66, 0x5a, 0xee, 0x36, 0xfc, 0x36, - 0x08, 0x5b, 0x3e, 0x5b, 0x3e, 0x5b, 0xc8, 0x19, - 0xc3, 0x5b, 0xd8, 0x5b, 0xe7, 0x5b, 0xf3, 0x5b, - 0x18, 0x1b, 0xff, 0x5b, 0x06, 0x5c, 0x53, 0x5f, - 0x22, 0x5c, 0x81, 0x37, 0x60, 0x5c, 0x6e, 0x5c, - 0xc0, 0x5c, 0x8d, 0x5c, 0xe4, 0x1d, 0x43, 0x5d, - 0xe6, 0x1d, 0x6e, 0x5d, 0x6b, 0x5d, 0x7c, 0x5d, - 0xe1, 0x5d, 0xe2, 0x5d, 0x2f, 0x38, 0xfd, 0x5d, - 0x28, 0x5e, 0x3d, 0x5e, 0x69, 0x5e, 0x62, 0x38, - 0x83, 0x21, 0x7c, 0x38, 0xb0, 0x5e, 0xb3, 0x5e, - 0xb6, 0x5e, 0xca, 0x5e, 0x92, 0xa3, 0xfe, 0x5e, - 0x31, 0x23, 0x31, 0x23, 0x01, 0x82, 0x22, 0x5f, - 0x22, 0x5f, 0xc7, 0x38, 0xb8, 0x32, 0xda, 0x61, - 0x62, 0x5f, 0x6b, 0x5f, 0xe3, 0x38, 0x9a, 0x5f, - 0xcd, 0x5f, 0xd7, 0x5f, 0xf9, 0x5f, 0x81, 0x60, - 0x3a, 0x39, 0x1c, 0x39, 0x94, 0x60, 0xd4, 0x26, - 0xc7, 0x60, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, - 0x02, 0x08, 0x00, 0x80, 0x08, 0x00, 0x00, 0x08, - 0x80, 0x28, 0x80, 0x02, 0x00, 0x00, 0x02, 0x48, - 0x61, 0x00, 0x04, 0x06, 0x04, 0x32, 0x46, 0x6a, - 0x5c, 0x67, 0x96, 0xaa, 0xae, 0xc8, 0xd3, 0x5d, - 0x62, 0x00, 0x54, 0x77, 0xf3, 0x0c, 0x2b, 0x3d, - 0x63, 0xfc, 0x62, 0x68, 0x63, 0x83, 0x63, 0xe4, - 0x63, 0xf1, 0x2b, 0x22, 0x64, 0xc5, 0x63, 0xa9, - 0x63, 0x2e, 0x3a, 0x69, 0x64, 0x7e, 0x64, 0x9d, - 0x64, 0x77, 0x64, 0x6c, 0x3a, 0x4f, 0x65, 0x6c, - 0x65, 0x0a, 0x30, 0xe3, 0x65, 0xf8, 0x66, 0x49, - 0x66, 0x19, 0x3b, 0x91, 0x66, 0x08, 0x3b, 0xe4, - 0x3a, 0x92, 0x51, 0x95, 0x51, 0x00, 0x67, 0x9c, - 0x66, 0xad, 0x80, 0xd9, 0x43, 0x17, 0x67, 0x1b, - 0x67, 0x21, 0x67, 0x5e, 0x67, 0x53, 0x67, 0xc3, - 0x33, 0x49, 0x3b, 0xfa, 0x67, 0x85, 0x67, 0x52, - 0x68, 0x85, 0x68, 0x6d, 0x34, 0x8e, 0x68, 0x1f, - 0x68, 0x14, 0x69, 0x9d, 0x3b, 0x42, 0x69, 0xa3, - 0x69, 0xea, 0x69, 0xa8, 0x6a, 0xa3, 0x36, 0xdb, - 0x6a, 0x18, 0x3c, 0x21, 0x6b, 0xa7, 0x38, 0x54, - 0x6b, 0x4e, 0x3c, 0x72, 0x6b, 0x9f, 0x6b, 0xba, - 0x6b, 0xbb, 0x6b, 0x8d, 0x3a, 0x0b, 0x1d, 0xfa, - 0x3a, 0x4e, 0x6c, 0xbc, 0x3c, 0xbf, 0x6c, 0xcd, - 0x6c, 0x67, 0x6c, 0x16, 0x6d, 0x3e, 0x6d, 0x77, - 0x6d, 0x41, 0x6d, 0x69, 0x6d, 0x78, 0x6d, 0x85, - 0x6d, 0x1e, 0x3d, 0x34, 0x6d, 0x2f, 0x6e, 0x6e, - 0x6e, 0x33, 0x3d, 0xcb, 0x6e, 0xc7, 0x6e, 0xd1, - 0x3e, 0xf9, 0x6d, 0x6e, 0x6f, 0x5e, 0x3f, 0x8e, - 0x3f, 0xc6, 0x6f, 0x39, 0x70, 0x1e, 0x70, 0x1b, - 0x70, 0x96, 0x3d, 0x4a, 0x70, 0x7d, 0x70, 0x77, - 0x70, 0xad, 0x70, 0x25, 0x05, 0x45, 0x71, 0x63, - 0x42, 0x9c, 0x71, 0xab, 0x43, 0x28, 0x72, 0x35, - 0x72, 0x50, 0x72, 0x08, 0x46, 0x80, 0x72, 0x95, - 0x72, 0x35, 0x47, 0x02, 0x20, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, - 0x02, 0x02, 0x80, 0x8a, 0x00, 0x00, 0x20, 0x00, - 0x08, 0x0a, 0x00, 0x80, 0x88, 0x80, 0x20, 0x14, - 0x48, 0x7a, 0x73, 0x8b, 0x73, 0xac, 0x3e, 0xa5, - 0x73, 0xb8, 0x3e, 0xb8, 0x3e, 0x47, 0x74, 0x5c, - 0x74, 0x71, 0x74, 0x85, 0x74, 0xca, 0x74, 0x1b, - 0x3f, 0x24, 0x75, 0x36, 0x4c, 0x3e, 0x75, 0x92, - 0x4c, 0x70, 0x75, 0x9f, 0x21, 0x10, 0x76, 0xa1, - 0x4f, 0xb8, 0x4f, 0x44, 0x50, 0xfc, 0x3f, 0x08, - 0x40, 0xf4, 0x76, 0xf3, 0x50, 0xf2, 0x50, 0x19, - 0x51, 0x33, 0x51, 0x1e, 0x77, 0x1f, 0x77, 0x1f, - 0x77, 0x4a, 0x77, 0x39, 0x40, 0x8b, 0x77, 0x46, - 0x40, 0x96, 0x40, 0x1d, 0x54, 0x4e, 0x78, 0x8c, - 0x78, 0xcc, 0x78, 0xe3, 0x40, 0x26, 0x56, 0x56, - 0x79, 0x9a, 0x56, 0xc5, 0x56, 0x8f, 0x79, 0xeb, - 0x79, 0x2f, 0x41, 0x40, 0x7a, 0x4a, 0x7a, 0x4f, - 0x7a, 0x7c, 0x59, 0xa7, 0x5a, 0xa7, 0x5a, 0xee, - 0x7a, 0x02, 0x42, 0xab, 0x5b, 0xc6, 0x7b, 0xc9, - 0x7b, 0x27, 0x42, 0x80, 0x5c, 0xd2, 0x7c, 0xa0, - 0x42, 0xe8, 0x7c, 0xe3, 0x7c, 0x00, 0x7d, 0x86, - 0x5f, 0x63, 0x7d, 0x01, 0x43, 0xc7, 0x7d, 0x02, - 0x7e, 0x45, 0x7e, 0x34, 0x43, 0x28, 0x62, 0x47, - 0x62, 0x59, 0x43, 0xd9, 0x62, 0x7a, 0x7f, 0x3e, - 0x63, 0x95, 0x7f, 0xfa, 0x7f, 0x05, 0x80, 0xda, - 0x64, 0x23, 0x65, 0x60, 0x80, 0xa8, 0x65, 0x70, - 0x80, 0x5f, 0x33, 0xd5, 0x43, 0xb2, 0x80, 0x03, - 0x81, 0x0b, 0x44, 0x3e, 0x81, 0xb5, 0x5a, 0xa7, - 0x67, 0xb5, 0x67, 0x93, 0x33, 0x9c, 0x33, 0x01, - 0x82, 0x04, 0x82, 0x9e, 0x8f, 0x6b, 0x44, 0x91, - 0x82, 0x8b, 0x82, 0x9d, 0x82, 0xb3, 0x52, 0xb1, - 0x82, 0xb3, 0x82, 0xbd, 0x82, 0xe6, 0x82, 0x3c, - 0x6b, 0xe5, 0x82, 0x1d, 0x83, 0x63, 0x83, 0xad, - 0x83, 0x23, 0x83, 0xbd, 0x83, 0xe7, 0x83, 0x57, - 0x84, 0x53, 0x83, 0xca, 0x83, 0xcc, 0x83, 0xdc, - 0x83, 0x36, 0x6c, 0x6b, 0x6d, 0x02, 0x00, 0x00, - 0x20, 0x22, 0x2a, 0xa0, 0x0a, 0x00, 0x20, 0x80, - 0x28, 0x00, 0xa8, 0x20, 0x20, 0x00, 0x02, 0x80, - 0x22, 0x02, 0x8a, 0x08, 0x00, 0xaa, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x28, 0xd5, 0x6c, 0x2b, - 0x45, 0xf1, 0x84, 0xf3, 0x84, 0x16, 0x85, 0xca, - 0x73, 0x64, 0x85, 0x2c, 0x6f, 0x5d, 0x45, 0x61, - 0x45, 0xb1, 0x6f, 0xd2, 0x70, 0x6b, 0x45, 0x50, - 0x86, 0x5c, 0x86, 0x67, 0x86, 0x69, 0x86, 0xa9, - 0x86, 0x88, 0x86, 0x0e, 0x87, 0xe2, 0x86, 0x79, - 0x87, 0x28, 0x87, 0x6b, 0x87, 0x86, 0x87, 0xd7, - 0x45, 0xe1, 0x87, 0x01, 0x88, 0xf9, 0x45, 0x60, - 0x88, 0x63, 0x88, 0x67, 0x76, 0xd7, 0x88, 0xde, - 0x88, 0x35, 0x46, 0xfa, 0x88, 0xbb, 0x34, 0xae, - 0x78, 0x66, 0x79, 0xbe, 0x46, 0xc7, 0x46, 0xa0, - 0x8a, 0xed, 0x8a, 0x8a, 0x8b, 0x55, 0x8c, 0xa8, - 0x7c, 0xab, 0x8c, 0xc1, 0x8c, 0x1b, 0x8d, 0x77, - 0x8d, 0x2f, 0x7f, 0x04, 0x08, 0xcb, 0x8d, 0xbc, - 0x8d, 0xf0, 0x8d, 0xde, 0x08, 0xd4, 0x8e, 0x38, - 0x8f, 0xd2, 0x85, 0xed, 0x85, 0x94, 0x90, 0xf1, - 0x90, 0x11, 0x91, 0x2e, 0x87, 0x1b, 0x91, 0x38, - 0x92, 0xd7, 0x92, 0xd8, 0x92, 0x7c, 0x92, 0xf9, - 0x93, 0x15, 0x94, 0xfa, 0x8b, 0x8b, 0x95, 0x95, - 0x49, 0xb7, 0x95, 0x77, 0x8d, 0xe6, 0x49, 0xc3, - 0x96, 0xb2, 0x5d, 0x23, 0x97, 0x45, 0x91, 0x1a, - 0x92, 0x6e, 0x4a, 0x76, 0x4a, 0xe0, 0x97, 0x0a, - 0x94, 0xb2, 0x4a, 0x96, 0x94, 0x0b, 0x98, 0x0b, - 0x98, 0x29, 0x98, 0xb6, 0x95, 0xe2, 0x98, 0x33, - 0x4b, 0x29, 0x99, 0xa7, 0x99, 0xc2, 0x99, 0xfe, - 0x99, 0xce, 0x4b, 0x30, 0x9b, 0x12, 0x9b, 0x40, - 0x9c, 0xfd, 0x9c, 0xce, 0x4c, 0xed, 0x4c, 0x67, - 0x9d, 0xce, 0xa0, 0xf8, 0x4c, 0x05, 0xa1, 0x0e, - 0xa2, 0x91, 0xa2, 0xbb, 0x9e, 0x56, 0x4d, 0xf9, - 0x9e, 0xfe, 0x9e, 0x05, 0x9f, 0x0f, 0x9f, 0x16, - 0x9f, 0x3b, 0x9f, 0x00, 0xa6, 0x02, 0x88, 0xa0, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x28, 0x00, - 0x08, 0xa0, 0x80, 0xa0, 0x80, 0x00, 0x80, 0x80, - 0x00, 0x0a, 0x88, 0x80, 0x00, 0x80, 0x00, 0x20, - 0x2a, 0x00, 0x80, + 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x28, 0x06, + 0x2c, 0x06, 0x2f, 0x06, 0x00, 0x00, 0x48, 0x06, + 0x32, 0x06, 0x2d, 0x06, 0x37, 0x06, 0x4a, 0x06, + 0x2a, 0x06, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, 0x17, + 0x0b, 0x18, 0x07, 0x0a, 0x00, 0x01, 0x04, 0x06, + 0x0c, 0x0e, 0x10, 0x30, 0x2e, 0x30, 0x00, 0x2c, + 0x00, 0x28, 0x00, 0x41, 0x00, 0x29, 0x00, 0x14, + 0x30, 0x53, 0x00, 0x15, 0x30, 0x43, 0x52, 0x43, + 0x44, 0x57, 0x5a, 0x41, 0x00, 0x48, 0x56, 0x4d, + 0x56, 0x53, 0x44, 0x53, 0x53, 0x50, 0x50, 0x56, + 0x57, 0x43, 0x4d, 0x43, 0x4d, 0x44, 0x4d, 0x52, + 0x44, 0x4a, 0x4b, 0x30, 0x30, 0x00, 0x68, 0x68, + 0x4b, 0x62, 0x57, 0x5b, 0xcc, 0x53, 0xc7, 0x30, + 0x8c, 0x4e, 0x1a, 0x59, 0xe3, 0x89, 0x29, 0x59, + 0xa4, 0x4e, 0x20, 0x66, 0x21, 0x71, 0x99, 0x65, + 0x4d, 0x52, 0x8c, 0x5f, 0x8d, 0x51, 0xb0, 0x65, + 0x1d, 0x52, 0x42, 0x7d, 0x1f, 0x75, 0xa9, 0x8c, + 0xf0, 0x58, 0x39, 0x54, 0x14, 0x6f, 0x95, 0x62, + 0x55, 0x63, 0x00, 0x4e, 0x09, 0x4e, 0x4a, 0x90, + 0xe6, 0x5d, 0x2d, 0x4e, 0xf3, 0x53, 0x07, 0x63, + 0x70, 0x8d, 0x53, 0x62, 0x81, 0x79, 0x7a, 0x7a, + 0x08, 0x54, 0x80, 0x6e, 0x09, 0x67, 0x08, 0x67, + 0x33, 0x75, 0x72, 0x52, 0xb6, 0x55, 0x4d, 0x91, + 0x14, 0x30, 0x15, 0x30, 0x2c, 0x67, 0x09, 0x4e, + 0x8c, 0x4e, 0x89, 0x5b, 0xb9, 0x70, 0x53, 0x62, + 0xd7, 0x76, 0xdd, 0x52, 0x57, 0x65, 0x97, 0x5f, + 0xef, 0x53, 0x30, 0x00, 0x38, 0x4e, 0x05, 0x00, + 0x09, 0x22, 0x01, 0x60, 0x4f, 0xae, 0x4f, 0xbb, + 0x4f, 0x02, 0x50, 0x7a, 0x50, 0x99, 0x50, 0xe7, + 0x50, 0xcf, 0x50, 0x9e, 0x34, 0x3a, 0x06, 0x4d, + 0x51, 0x54, 0x51, 0x64, 0x51, 0x77, 0x51, 0x1c, + 0x05, 0xb9, 0x34, 0x67, 0x51, 0x8d, 0x51, 0x4b, + 0x05, 0x97, 0x51, 0xa4, 0x51, 0xcc, 0x4e, 0xac, + 0x51, 0xb5, 0x51, 0xdf, 0x91, 0xf5, 0x51, 0x03, + 0x52, 0xdf, 0x34, 0x3b, 0x52, 0x46, 0x52, 0x72, + 0x52, 0x77, 0x52, 0x15, 0x35, 0x02, 0x00, 0x20, + 0x80, 0x80, 0x00, 0x08, 0x00, 0x00, 0xc7, 0x52, + 0x00, 0x02, 0x1d, 0x33, 0x3e, 0x3f, 0x50, 0x82, + 0x8a, 0x93, 0xac, 0xb6, 0xb8, 0xb8, 0xb8, 0x2c, + 0x0a, 0x70, 0x70, 0xca, 0x53, 0xdf, 0x53, 0x63, + 0x0b, 0xeb, 0x53, 0xf1, 0x53, 0x06, 0x54, 0x9e, + 0x54, 0x38, 0x54, 0x48, 0x54, 0x68, 0x54, 0xa2, + 0x54, 0xf6, 0x54, 0x10, 0x55, 0x53, 0x55, 0x63, + 0x55, 0x84, 0x55, 0x84, 0x55, 0x99, 0x55, 0xab, + 0x55, 0xb3, 0x55, 0xc2, 0x55, 0x16, 0x57, 0x06, + 0x56, 0x17, 0x57, 0x51, 0x56, 0x74, 0x56, 0x07, + 0x52, 0xee, 0x58, 0xce, 0x57, 0xf4, 0x57, 0x0d, + 0x58, 0x8b, 0x57, 0x32, 0x58, 0x31, 0x58, 0xac, + 0x58, 0xe4, 0x14, 0xf2, 0x58, 0xf7, 0x58, 0x06, + 0x59, 0x1a, 0x59, 0x22, 0x59, 0x62, 0x59, 0xa8, + 0x16, 0xea, 0x16, 0xec, 0x59, 0x1b, 0x5a, 0x27, + 0x5a, 0xd8, 0x59, 0x66, 0x5a, 0xee, 0x36, 0xfc, + 0x36, 0x08, 0x5b, 0x3e, 0x5b, 0x3e, 0x5b, 0xc8, + 0x19, 0xc3, 0x5b, 0xd8, 0x5b, 0xe7, 0x5b, 0xf3, + 0x5b, 0x18, 0x1b, 0xff, 0x5b, 0x06, 0x5c, 0x53, + 0x5f, 0x22, 0x5c, 0x81, 0x37, 0x60, 0x5c, 0x6e, + 0x5c, 0xc0, 0x5c, 0x8d, 0x5c, 0xe4, 0x1d, 0x43, + 0x5d, 0xe6, 0x1d, 0x6e, 0x5d, 0x6b, 0x5d, 0x7c, + 0x5d, 0xe1, 0x5d, 0xe2, 0x5d, 0x2f, 0x38, 0xfd, + 0x5d, 0x28, 0x5e, 0x3d, 0x5e, 0x69, 0x5e, 0x62, + 0x38, 0x83, 0x21, 0x7c, 0x38, 0xb0, 0x5e, 0xb3, + 0x5e, 0xb6, 0x5e, 0xca, 0x5e, 0x92, 0xa3, 0xfe, + 0x5e, 0x31, 0x23, 0x31, 0x23, 0x01, 0x82, 0x22, + 0x5f, 0x22, 0x5f, 0xc7, 0x38, 0xb8, 0x32, 0xda, + 0x61, 0x62, 0x5f, 0x6b, 0x5f, 0xe3, 0x38, 0x9a, + 0x5f, 0xcd, 0x5f, 0xd7, 0x5f, 0xf9, 0x5f, 0x81, + 0x60, 0x3a, 0x39, 0x1c, 0x39, 0x94, 0x60, 0xd4, + 0x26, 0xc7, 0x60, 0x02, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, + 0x00, 0x02, 0x08, 0x00, 0x80, 0x08, 0x00, 0x00, + 0x08, 0x80, 0x28, 0x80, 0x02, 0x00, 0x00, 0x02, + 0x48, 0x61, 0x00, 0x04, 0x06, 0x04, 0x32, 0x46, + 0x6a, 0x5c, 0x67, 0x96, 0xaa, 0xae, 0xc8, 0xd3, + 0x5d, 0x62, 0x00, 0x54, 0x77, 0xf3, 0x0c, 0x2b, + 0x3d, 0x63, 0xfc, 0x62, 0x68, 0x63, 0x83, 0x63, + 0xe4, 0x63, 0xf1, 0x2b, 0x22, 0x64, 0xc5, 0x63, + 0xa9, 0x63, 0x2e, 0x3a, 0x69, 0x64, 0x7e, 0x64, + 0x9d, 0x64, 0x77, 0x64, 0x6c, 0x3a, 0x4f, 0x65, + 0x6c, 0x65, 0x0a, 0x30, 0xe3, 0x65, 0xf8, 0x66, + 0x49, 0x66, 0x19, 0x3b, 0x91, 0x66, 0x08, 0x3b, + 0xe4, 0x3a, 0x92, 0x51, 0x95, 0x51, 0x00, 0x67, + 0x9c, 0x66, 0xad, 0x80, 0xd9, 0x43, 0x17, 0x67, + 0x1b, 0x67, 0x21, 0x67, 0x5e, 0x67, 0x53, 0x67, + 0xc3, 0x33, 0x49, 0x3b, 0xfa, 0x67, 0x85, 0x67, + 0x52, 0x68, 0x85, 0x68, 0x6d, 0x34, 0x8e, 0x68, + 0x1f, 0x68, 0x14, 0x69, 0x9d, 0x3b, 0x42, 0x69, + 0xa3, 0x69, 0xea, 0x69, 0xa8, 0x6a, 0xa3, 0x36, + 0xdb, 0x6a, 0x18, 0x3c, 0x21, 0x6b, 0xa7, 0x38, + 0x54, 0x6b, 0x4e, 0x3c, 0x72, 0x6b, 0x9f, 0x6b, + 0xba, 0x6b, 0xbb, 0x6b, 0x8d, 0x3a, 0x0b, 0x1d, + 0xfa, 0x3a, 0x4e, 0x6c, 0xbc, 0x3c, 0xbf, 0x6c, + 0xcd, 0x6c, 0x67, 0x6c, 0x16, 0x6d, 0x3e, 0x6d, + 0x77, 0x6d, 0x41, 0x6d, 0x69, 0x6d, 0x78, 0x6d, + 0x85, 0x6d, 0x1e, 0x3d, 0x34, 0x6d, 0x2f, 0x6e, + 0x6e, 0x6e, 0x33, 0x3d, 0xcb, 0x6e, 0xc7, 0x6e, + 0xd1, 0x3e, 0xf9, 0x6d, 0x6e, 0x6f, 0x5e, 0x3f, + 0x8e, 0x3f, 0xc6, 0x6f, 0x39, 0x70, 0x1e, 0x70, + 0x1b, 0x70, 0x96, 0x3d, 0x4a, 0x70, 0x7d, 0x70, + 0x77, 0x70, 0xad, 0x70, 0x25, 0x05, 0x45, 0x71, + 0x63, 0x42, 0x9c, 0x71, 0xab, 0x43, 0x28, 0x72, + 0x35, 0x72, 0x50, 0x72, 0x08, 0x46, 0x80, 0x72, + 0x95, 0x72, 0x35, 0x47, 0x02, 0x20, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, + 0x00, 0x02, 0x02, 0x80, 0x8a, 0x00, 0x00, 0x20, + 0x00, 0x08, 0x0a, 0x00, 0x80, 0x88, 0x80, 0x20, + 0x14, 0x48, 0x7a, 0x73, 0x8b, 0x73, 0xac, 0x3e, + 0xa5, 0x73, 0xb8, 0x3e, 0xb8, 0x3e, 0x47, 0x74, + 0x5c, 0x74, 0x71, 0x74, 0x85, 0x74, 0xca, 0x74, + 0x1b, 0x3f, 0x24, 0x75, 0x36, 0x4c, 0x3e, 0x75, + 0x92, 0x4c, 0x70, 0x75, 0x9f, 0x21, 0x10, 0x76, + 0xa1, 0x4f, 0xb8, 0x4f, 0x44, 0x50, 0xfc, 0x3f, + 0x08, 0x40, 0xf4, 0x76, 0xf3, 0x50, 0xf2, 0x50, + 0x19, 0x51, 0x33, 0x51, 0x1e, 0x77, 0x1f, 0x77, + 0x1f, 0x77, 0x4a, 0x77, 0x39, 0x40, 0x8b, 0x77, + 0x46, 0x40, 0x96, 0x40, 0x1d, 0x54, 0x4e, 0x78, + 0x8c, 0x78, 0xcc, 0x78, 0xe3, 0x40, 0x26, 0x56, + 0x56, 0x79, 0x9a, 0x56, 0xc5, 0x56, 0x8f, 0x79, + 0xeb, 0x79, 0x2f, 0x41, 0x40, 0x7a, 0x4a, 0x7a, + 0x4f, 0x7a, 0x7c, 0x59, 0xa7, 0x5a, 0xa7, 0x5a, + 0xee, 0x7a, 0x02, 0x42, 0xab, 0x5b, 0xc6, 0x7b, + 0xc9, 0x7b, 0x27, 0x42, 0x80, 0x5c, 0xd2, 0x7c, + 0xa0, 0x42, 0xe8, 0x7c, 0xe3, 0x7c, 0x00, 0x7d, + 0x86, 0x5f, 0x63, 0x7d, 0x01, 0x43, 0xc7, 0x7d, + 0x02, 0x7e, 0x45, 0x7e, 0x34, 0x43, 0x28, 0x62, + 0x47, 0x62, 0x59, 0x43, 0xd9, 0x62, 0x7a, 0x7f, + 0x3e, 0x63, 0x95, 0x7f, 0xfa, 0x7f, 0x05, 0x80, + 0xda, 0x64, 0x23, 0x65, 0x60, 0x80, 0xa8, 0x65, + 0x70, 0x80, 0x5f, 0x33, 0xd5, 0x43, 0xb2, 0x80, + 0x03, 0x81, 0x0b, 0x44, 0x3e, 0x81, 0xb5, 0x5a, + 0xa7, 0x67, 0xb5, 0x67, 0x93, 0x33, 0x9c, 0x33, + 0x01, 0x82, 0x04, 0x82, 0x9e, 0x8f, 0x6b, 0x44, + 0x91, 0x82, 0x8b, 0x82, 0x9d, 0x82, 0xb3, 0x52, + 0xb1, 0x82, 0xb3, 0x82, 0xbd, 0x82, 0xe6, 0x82, + 0x3c, 0x6b, 0xe5, 0x82, 0x1d, 0x83, 0x63, 0x83, + 0xad, 0x83, 0x23, 0x83, 0xbd, 0x83, 0xe7, 0x83, + 0x57, 0x84, 0x53, 0x83, 0xca, 0x83, 0xcc, 0x83, + 0xdc, 0x83, 0x36, 0x6c, 0x6b, 0x6d, 0x02, 0x00, + 0x00, 0x20, 0x22, 0x2a, 0xa0, 0x0a, 0x00, 0x20, + 0x80, 0x28, 0x00, 0xa8, 0x20, 0x20, 0x00, 0x02, + 0x80, 0x22, 0x02, 0x8a, 0x08, 0x00, 0xaa, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x28, 0xd5, 0x6c, + 0x2b, 0x45, 0xf1, 0x84, 0xf3, 0x84, 0x16, 0x85, + 0xca, 0x73, 0x64, 0x85, 0x2c, 0x6f, 0x5d, 0x45, + 0x61, 0x45, 0xb1, 0x6f, 0xd2, 0x70, 0x6b, 0x45, + 0x50, 0x86, 0x5c, 0x86, 0x67, 0x86, 0x69, 0x86, + 0xa9, 0x86, 0x88, 0x86, 0x0e, 0x87, 0xe2, 0x86, + 0x79, 0x87, 0x28, 0x87, 0x6b, 0x87, 0x86, 0x87, + 0xd7, 0x45, 0xe1, 0x87, 0x01, 0x88, 0xf9, 0x45, + 0x60, 0x88, 0x63, 0x88, 0x67, 0x76, 0xd7, 0x88, + 0xde, 0x88, 0x35, 0x46, 0xfa, 0x88, 0xbb, 0x34, + 0xae, 0x78, 0x66, 0x79, 0xbe, 0x46, 0xc7, 0x46, + 0xa0, 0x8a, 0xed, 0x8a, 0x8a, 0x8b, 0x55, 0x8c, + 0xa8, 0x7c, 0xab, 0x8c, 0xc1, 0x8c, 0x1b, 0x8d, + 0x77, 0x8d, 0x2f, 0x7f, 0x04, 0x08, 0xcb, 0x8d, + 0xbc, 0x8d, 0xf0, 0x8d, 0xde, 0x08, 0xd4, 0x8e, + 0x38, 0x8f, 0xd2, 0x85, 0xed, 0x85, 0x94, 0x90, + 0xf1, 0x90, 0x11, 0x91, 0x2e, 0x87, 0x1b, 0x91, + 0x38, 0x92, 0xd7, 0x92, 0xd8, 0x92, 0x7c, 0x92, + 0xf9, 0x93, 0x15, 0x94, 0xfa, 0x8b, 0x8b, 0x95, + 0x95, 0x49, 0xb7, 0x95, 0x77, 0x8d, 0xe6, 0x49, + 0xc3, 0x96, 0xb2, 0x5d, 0x23, 0x97, 0x45, 0x91, + 0x1a, 0x92, 0x6e, 0x4a, 0x76, 0x4a, 0xe0, 0x97, + 0x0a, 0x94, 0xb2, 0x4a, 0x96, 0x94, 0x0b, 0x98, + 0x0b, 0x98, 0x29, 0x98, 0xb6, 0x95, 0xe2, 0x98, + 0x33, 0x4b, 0x29, 0x99, 0xa7, 0x99, 0xc2, 0x99, + 0xfe, 0x99, 0xce, 0x4b, 0x30, 0x9b, 0x12, 0x9b, + 0x40, 0x9c, 0xfd, 0x9c, 0xce, 0x4c, 0xed, 0x4c, + 0x67, 0x9d, 0xce, 0xa0, 0xf8, 0x4c, 0x05, 0xa1, + 0x0e, 0xa2, 0x91, 0xa2, 0xbb, 0x9e, 0x56, 0x4d, + 0xf9, 0x9e, 0xfe, 0x9e, 0x05, 0x9f, 0x0f, 0x9f, + 0x16, 0x9f, 0x3b, 0x9f, 0x00, 0xa6, 0x02, 0x88, + 0xa0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x28, + 0x00, 0x08, 0xa0, 0x80, 0xa0, 0x80, 0x00, 0x80, + 0x80, 0x00, 0x0a, 0x88, 0x80, 0x00, 0x80, 0x00, + 0x20, 0x2a, 0x00, 0x80, }; static const uint16_t unicode_comp_table[965] = { @@ -2379,7 +2390,7 @@ static const char unicode_gc_name_table[] = "C,Other" "\0" ; -static const uint8_t unicode_gc_table[4070] = { +static const uint8_t unicode_gc_table[4122] = { 0xfa, 0x18, 0x17, 0x56, 0x0d, 0x56, 0x12, 0x13, 0x16, 0x0c, 0x16, 0x11, 0x36, 0xe9, 0x02, 0x36, 0x4c, 0x36, 0xe1, 0x12, 0x12, 0x16, 0x13, 0x0e, @@ -2397,8 +2408,8 @@ static const uint8_t unicode_gc_table[4070] = { 0x03, 0x02, 0x01, 0x03, 0x02, 0xff, 0x08, 0x02, 0xff, 0x0a, 0x02, 0x01, 0x03, 0x02, 0x5f, 0x21, 0x02, 0xff, 0x32, 0xa2, 0x21, 0x02, 0x21, 0x22, - 0x5f, 0x41, 0x02, 0xff, 0x00, 0xe2, 0x3c, 0x05, - 0xe2, 0x13, 0xe4, 0x0a, 0x6e, 0xe4, 0x04, 0xee, + 0x5f, 0x41, 0x02, 0xff, 0x00, 0xe2, 0x3c, 0x25, + 0xe2, 0x12, 0xe4, 0x0a, 0x6e, 0xe4, 0x04, 0xee, 0x06, 0x84, 0xce, 0x04, 0x0e, 0x04, 0xee, 0x09, 0xe6, 0x68, 0x7f, 0x04, 0x0e, 0x3f, 0x20, 0x04, 0x42, 0x16, 0x01, 0x60, 0x2e, 0x01, 0x16, 0x41, @@ -2423,166 +2434,166 @@ static const uint8_t unicode_gc_table[4070] = { 0x2d, 0xe5, 0x0e, 0x66, 0x04, 0xe6, 0x01, 0x04, 0x46, 0x04, 0x86, 0x20, 0xf6, 0x07, 0x00, 0xe5, 0x11, 0x46, 0x20, 0x16, 0x00, 0xe5, 0x03, 0x80, - 0xe5, 0x10, 0x0e, 0xa5, 0x00, 0x3b, 0x80, 0xe6, - 0x01, 0xe5, 0x21, 0x04, 0xe6, 0x10, 0x1b, 0xe6, - 0x18, 0x07, 0xe5, 0x2e, 0x06, 0x07, 0x06, 0x05, - 0x47, 0xe6, 0x00, 0x67, 0x06, 0x27, 0x05, 0xc6, - 0xe5, 0x02, 0x26, 0x36, 0xe9, 0x02, 0x16, 0x04, - 0xe5, 0x07, 0x06, 0x27, 0x00, 0xe5, 0x00, 0x20, - 0x25, 0x20, 0xe5, 0x0e, 0x00, 0xc5, 0x00, 0x05, - 0x40, 0x65, 0x20, 0x06, 0x05, 0x47, 0x66, 0x20, - 0x27, 0x20, 0x27, 0x06, 0x05, 0xe0, 0x00, 0x07, - 0x60, 0x25, 0x00, 0x45, 0x26, 0x20, 0xe9, 0x02, - 0x25, 0x2d, 0xab, 0x0f, 0x0d, 0x05, 0x16, 0x06, - 0x20, 0x26, 0x07, 0x00, 0xa5, 0x60, 0x25, 0x20, - 0xe5, 0x0e, 0x00, 0xc5, 0x00, 0x25, 0x00, 0x25, - 0x00, 0x25, 0x20, 0x06, 0x00, 0x47, 0x26, 0x60, - 0x26, 0x20, 0x46, 0x40, 0x06, 0xc0, 0x65, 0x00, - 0x05, 0xc0, 0xe9, 0x02, 0x26, 0x45, 0x06, 0x16, - 0xe0, 0x02, 0x26, 0x07, 0x00, 0xe5, 0x01, 0x00, - 0x45, 0x00, 0xe5, 0x0e, 0x00, 0xc5, 0x00, 0x25, - 0x00, 0x85, 0x20, 0x06, 0x05, 0x47, 0x86, 0x00, - 0x26, 0x07, 0x00, 0x27, 0x06, 0x20, 0x05, 0xe0, - 0x07, 0x25, 0x26, 0x20, 0xe9, 0x02, 0x16, 0x0d, - 0xc0, 0x05, 0xa6, 0x00, 0x06, 0x27, 0x00, 0xe5, - 0x00, 0x20, 0x25, 0x20, 0xe5, 0x0e, 0x00, 0xc5, - 0x00, 0x25, 0x00, 0x85, 0x20, 0x06, 0x05, 0x07, - 0x06, 0x07, 0x66, 0x20, 0x27, 0x20, 0x27, 0x06, - 0xc0, 0x26, 0x07, 0x60, 0x25, 0x00, 0x45, 0x26, - 0x20, 0xe9, 0x02, 0x0f, 0x05, 0xab, 0xe0, 0x02, - 0x06, 0x05, 0x00, 0xa5, 0x40, 0x45, 0x00, 0x65, - 0x40, 0x25, 0x00, 0x05, 0x00, 0x25, 0x40, 0x25, - 0x40, 0x45, 0x40, 0xe5, 0x04, 0x60, 0x27, 0x06, - 0x27, 0x40, 0x47, 0x00, 0x47, 0x06, 0x20, 0x05, - 0xa0, 0x07, 0xe0, 0x06, 0xe9, 0x02, 0x4b, 0xaf, - 0x0d, 0x0f, 0x80, 0x06, 0x47, 0x06, 0xe5, 0x00, - 0x00, 0x45, 0x00, 0xe5, 0x0f, 0x00, 0xe5, 0x08, - 0x20, 0x06, 0x05, 0x46, 0x67, 0x00, 0x46, 0x00, - 0x66, 0xc0, 0x26, 0x00, 0x45, 0x20, 0x05, 0x20, - 0x25, 0x26, 0x20, 0xe9, 0x02, 0xc0, 0x16, 0xcb, - 0x0f, 0x05, 0x06, 0x27, 0x16, 0xe5, 0x00, 0x00, - 0x45, 0x00, 0xe5, 0x0f, 0x00, 0xe5, 0x02, 0x00, - 0x85, 0x20, 0x06, 0x05, 0x07, 0x06, 0x87, 0x00, - 0x06, 0x27, 0x00, 0x27, 0x26, 0xc0, 0x27, 0xa0, - 0x25, 0x00, 0x25, 0x26, 0x20, 0xe9, 0x02, 0x00, - 0x25, 0x07, 0xe0, 0x04, 0x26, 0x27, 0xe5, 0x01, - 0x00, 0x45, 0x00, 0xe5, 0x21, 0x26, 0x05, 0x47, - 0x66, 0x00, 0x47, 0x00, 0x47, 0x06, 0x05, 0x0f, - 0x60, 0x45, 0x07, 0xcb, 0x45, 0x26, 0x20, 0xe9, - 0x02, 0xeb, 0x01, 0x0f, 0xa5, 0x00, 0x06, 0x27, - 0x00, 0xe5, 0x0a, 0x40, 0xe5, 0x10, 0x00, 0xe5, - 0x01, 0x00, 0x05, 0x20, 0xc5, 0x40, 0x06, 0x60, - 0x47, 0x46, 0x00, 0x06, 0x00, 0xe7, 0x00, 0xa0, - 0xe9, 0x02, 0x20, 0x27, 0x16, 0xe0, 0x04, 0xe5, - 0x28, 0x06, 0x25, 0xc6, 0x60, 0x0d, 0xa5, 0x04, - 0xe6, 0x00, 0x16, 0xe9, 0x02, 0x36, 0xe0, 0x1d, - 0x25, 0x00, 0x05, 0x00, 0x85, 0x00, 0xe5, 0x10, - 0x00, 0x05, 0x00, 0xe5, 0x02, 0x06, 0x25, 0xe6, - 0x01, 0x05, 0x20, 0x85, 0x00, 0x04, 0x00, 0xc6, - 0x00, 0xe9, 0x02, 0x20, 0x65, 0xe0, 0x18, 0x05, - 0x4f, 0xf6, 0x07, 0x0f, 0x16, 0x4f, 0x26, 0xaf, - 0xe9, 0x02, 0xeb, 0x02, 0x0f, 0x06, 0x0f, 0x06, - 0x0f, 0x06, 0x12, 0x13, 0x12, 0x13, 0x27, 0xe5, - 0x00, 0x00, 0xe5, 0x1c, 0x60, 0xe6, 0x06, 0x07, - 0x86, 0x16, 0x26, 0x85, 0xe6, 0x03, 0x00, 0xe6, - 0x1c, 0x00, 0xef, 0x00, 0x06, 0xaf, 0x00, 0x2f, - 0x96, 0x6f, 0x36, 0xe0, 0x1d, 0xe5, 0x23, 0x27, - 0x66, 0x07, 0xa6, 0x07, 0x26, 0x27, 0x26, 0x05, - 0xe9, 0x02, 0xb6, 0xa5, 0x27, 0x26, 0x65, 0x46, - 0x05, 0x47, 0x25, 0xc7, 0x45, 0x66, 0xe5, 0x05, - 0x06, 0x27, 0x26, 0xa7, 0x06, 0x05, 0x07, 0xe9, - 0x02, 0x47, 0x06, 0x2f, 0xe1, 0x1e, 0x00, 0x01, - 0x80, 0x01, 0x20, 0xe2, 0x23, 0x16, 0x04, 0x42, - 0xe5, 0x80, 0xc1, 0x00, 0x65, 0x20, 0xc5, 0x00, - 0x05, 0x00, 0x65, 0x20, 0xe5, 0x21, 0x00, 0x65, - 0x20, 0xe5, 0x19, 0x00, 0x65, 0x20, 0xc5, 0x00, - 0x05, 0x00, 0x65, 0x20, 0xe5, 0x07, 0x00, 0xe5, - 0x31, 0x00, 0x65, 0x20, 0xe5, 0x3b, 0x20, 0x46, - 0xf6, 0x01, 0xeb, 0x0c, 0x40, 0xe5, 0x08, 0xef, - 0x02, 0xa0, 0xe1, 0x4e, 0x20, 0xa2, 0x20, 0x11, - 0xe5, 0x81, 0xe4, 0x0f, 0x16, 0xe5, 0x09, 0x17, - 0xe5, 0x12, 0x12, 0x13, 0x40, 0xe5, 0x43, 0x56, - 0x4a, 0xe5, 0x00, 0xc0, 0xe5, 0x0a, 0x46, 0x07, - 0xe0, 0x01, 0xe5, 0x0b, 0x26, 0x07, 0x36, 0xe0, - 0x01, 0xe5, 0x0a, 0x26, 0xe0, 0x04, 0xe5, 0x05, - 0x00, 0x45, 0x00, 0x26, 0xe0, 0x04, 0xe5, 0x2c, - 0x26, 0x07, 0xc6, 0xe7, 0x00, 0x06, 0x27, 0xe6, - 0x03, 0x56, 0x04, 0x56, 0x0d, 0x05, 0x06, 0x20, - 0xe9, 0x02, 0xa0, 0xeb, 0x02, 0xa0, 0xb6, 0x11, - 0x76, 0x46, 0x1b, 0x06, 0xe9, 0x02, 0xa0, 0xe5, - 0x1b, 0x04, 0xe5, 0x2d, 0xc0, 0x85, 0x26, 0xe5, - 0x1a, 0x06, 0x05, 0x80, 0xe5, 0x3e, 0xe0, 0x02, - 0xe5, 0x17, 0x00, 0x46, 0x67, 0x26, 0x47, 0x60, - 0x27, 0x06, 0xa7, 0x46, 0x60, 0x0f, 0x40, 0x36, - 0xe9, 0x02, 0xe5, 0x16, 0x20, 0x85, 0xe0, 0x03, - 0xe5, 0x24, 0x60, 0xe5, 0x12, 0xa0, 0xe9, 0x02, - 0x0b, 0x40, 0xef, 0x1a, 0xe5, 0x0f, 0x26, 0x27, - 0x06, 0x20, 0x36, 0xe5, 0x2d, 0x07, 0x06, 0x07, - 0xc6, 0x00, 0x06, 0x07, 0x06, 0x27, 0xe6, 0x00, - 0xa7, 0xe6, 0x02, 0x20, 0x06, 0xe9, 0x02, 0xa0, - 0xe9, 0x02, 0xa0, 0xd6, 0x04, 0xb6, 0x20, 0xe6, - 0x06, 0x08, 0xe6, 0x08, 0xe0, 0x29, 0x66, 0x07, - 0xe5, 0x27, 0x06, 0x07, 0x86, 0x07, 0x06, 0x87, - 0x06, 0x27, 0xe5, 0x00, 0x00, 0x36, 0xe9, 0x02, - 0xd6, 0xef, 0x02, 0xe6, 0x01, 0xef, 0x01, 0x56, - 0x26, 0x07, 0xe5, 0x16, 0x07, 0x66, 0x27, 0x26, - 0x07, 0x46, 0x25, 0xe9, 0x02, 0xe5, 0x24, 0x06, - 0x07, 0x26, 0x47, 0x06, 0x07, 0x46, 0x27, 0xe0, - 0x00, 0x76, 0xe5, 0x1c, 0xe7, 0x00, 0xe6, 0x00, - 0x27, 0x26, 0x40, 0x96, 0xe9, 0x02, 0x40, 0x45, - 0xe9, 0x02, 0xe5, 0x16, 0xa4, 0x36, 0xe2, 0x01, - 0x3f, 0x80, 0xe1, 0x23, 0x20, 0x41, 0xf6, 0x00, - 0xe0, 0x00, 0x46, 0x16, 0xe6, 0x05, 0x07, 0xc6, - 0x65, 0x06, 0xa5, 0x06, 0x25, 0x07, 0x26, 0x05, - 0x80, 0xe2, 0x24, 0xe4, 0x37, 0xe2, 0x05, 0x04, - 0xe2, 0x1a, 0xe4, 0x1d, 0xe6, 0x38, 0xff, 0x80, - 0x0e, 0xe2, 0x00, 0xff, 0x5a, 0xe2, 0x00, 0xe1, - 0x00, 0xa2, 0x20, 0xa1, 0x20, 0xe2, 0x00, 0xe1, - 0x00, 0xe2, 0x00, 0xe1, 0x00, 0xa2, 0x20, 0xa1, - 0x20, 0xe2, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, - 0x01, 0x00, 0x3f, 0xc2, 0xe1, 0x00, 0xe2, 0x06, - 0x20, 0xe2, 0x00, 0xe3, 0x00, 0xe2, 0x00, 0xe3, - 0x00, 0xe2, 0x00, 0xe3, 0x00, 0x82, 0x00, 0x22, - 0x61, 0x03, 0x0e, 0x02, 0x4e, 0x42, 0x00, 0x22, - 0x61, 0x03, 0x4e, 0x62, 0x20, 0x22, 0x61, 0x00, - 0x4e, 0xe2, 0x00, 0x81, 0x4e, 0x20, 0x42, 0x00, - 0x22, 0x61, 0x03, 0x2e, 0x00, 0xf7, 0x03, 0x9b, - 0xb1, 0x36, 0x14, 0x15, 0x12, 0x34, 0x15, 0x12, - 0x14, 0xf6, 0x00, 0x18, 0x19, 0x9b, 0x17, 0xf6, - 0x01, 0x14, 0x15, 0x76, 0x30, 0x56, 0x0c, 0x12, - 0x13, 0xf6, 0x03, 0x0c, 0x16, 0x10, 0xf6, 0x02, - 0x17, 0x9b, 0x00, 0xfb, 0x02, 0x0b, 0x04, 0x20, - 0xab, 0x4c, 0x12, 0x13, 0x04, 0xeb, 0x02, 0x4c, - 0x12, 0x13, 0x00, 0xe4, 0x05, 0x40, 0xed, 0x19, - 0xe0, 0x07, 0xe6, 0x05, 0x68, 0x06, 0x48, 0xe6, - 0x04, 0xe0, 0x07, 0x2f, 0x01, 0x6f, 0x01, 0x2f, - 0x02, 0x41, 0x22, 0x41, 0x02, 0x0f, 0x01, 0x2f, - 0x0c, 0x81, 0xaf, 0x01, 0x0f, 0x01, 0x0f, 0x01, - 0x0f, 0x61, 0x0f, 0x02, 0x61, 0x02, 0x65, 0x02, - 0x2f, 0x22, 0x21, 0x8c, 0x3f, 0x42, 0x0f, 0x0c, - 0x2f, 0x02, 0x0f, 0xeb, 0x08, 0xea, 0x1b, 0x3f, - 0x6a, 0x0b, 0x2f, 0x60, 0x8c, 0x8f, 0x2c, 0x6f, - 0x0c, 0x2f, 0x0c, 0x2f, 0x0c, 0xcf, 0x0c, 0xef, - 0x17, 0x2c, 0x2f, 0x0c, 0x0f, 0x0c, 0xef, 0x17, - 0xec, 0x80, 0x84, 0xef, 0x00, 0x12, 0x13, 0x12, - 0x13, 0xef, 0x0c, 0x2c, 0xcf, 0x12, 0x13, 0xef, - 0x49, 0x0c, 0xef, 0x16, 0xec, 0x11, 0xef, 0x20, - 0xac, 0xef, 0x40, 0xe0, 0x0e, 0xef, 0x03, 0xe0, - 0x0d, 0xeb, 0x34, 0xef, 0x46, 0xeb, 0x0e, 0xef, - 0x80, 0x2f, 0x0c, 0xef, 0x01, 0x0c, 0xef, 0x2e, - 0xec, 0x00, 0xef, 0x67, 0x0c, 0xef, 0x80, 0x70, + 0xe5, 0x10, 0x0e, 0xc5, 0x3b, 0x80, 0xe6, 0x01, + 0xe5, 0x21, 0x04, 0xe6, 0x10, 0x1b, 0xe6, 0x18, + 0x07, 0xe5, 0x2e, 0x06, 0x07, 0x06, 0x05, 0x47, + 0xe6, 0x00, 0x67, 0x06, 0x27, 0x05, 0xc6, 0xe5, + 0x02, 0x26, 0x36, 0xe9, 0x02, 0x16, 0x04, 0xe5, + 0x07, 0x06, 0x27, 0x00, 0xe5, 0x00, 0x20, 0x25, + 0x20, 0xe5, 0x0e, 0x00, 0xc5, 0x00, 0x05, 0x40, + 0x65, 0x20, 0x06, 0x05, 0x47, 0x66, 0x20, 0x27, + 0x20, 0x27, 0x06, 0x05, 0xe0, 0x00, 0x07, 0x60, + 0x25, 0x00, 0x45, 0x26, 0x20, 0xe9, 0x02, 0x25, + 0x2d, 0xab, 0x0f, 0x0d, 0x05, 0x16, 0x06, 0x20, + 0x26, 0x07, 0x00, 0xa5, 0x60, 0x25, 0x20, 0xe5, + 0x0e, 0x00, 0xc5, 0x00, 0x25, 0x00, 0x25, 0x00, + 0x25, 0x20, 0x06, 0x00, 0x47, 0x26, 0x60, 0x26, + 0x20, 0x46, 0x40, 0x06, 0xc0, 0x65, 0x00, 0x05, + 0xc0, 0xe9, 0x02, 0x26, 0x45, 0x06, 0x16, 0xe0, + 0x02, 0x26, 0x07, 0x00, 0xe5, 0x01, 0x00, 0x45, + 0x00, 0xe5, 0x0e, 0x00, 0xc5, 0x00, 0x25, 0x00, + 0x85, 0x20, 0x06, 0x05, 0x47, 0x86, 0x00, 0x26, + 0x07, 0x00, 0x27, 0x06, 0x20, 0x05, 0xe0, 0x07, + 0x25, 0x26, 0x20, 0xe9, 0x02, 0x16, 0x0d, 0xc0, + 0x05, 0xa6, 0x00, 0x06, 0x27, 0x00, 0xe5, 0x00, + 0x20, 0x25, 0x20, 0xe5, 0x0e, 0x00, 0xc5, 0x00, + 0x25, 0x00, 0x85, 0x20, 0x06, 0x05, 0x07, 0x06, + 0x07, 0x66, 0x20, 0x27, 0x20, 0x27, 0x06, 0xc0, + 0x26, 0x07, 0x60, 0x25, 0x00, 0x45, 0x26, 0x20, + 0xe9, 0x02, 0x0f, 0x05, 0xab, 0xe0, 0x02, 0x06, + 0x05, 0x00, 0xa5, 0x40, 0x45, 0x00, 0x65, 0x40, + 0x25, 0x00, 0x05, 0x00, 0x25, 0x40, 0x25, 0x40, + 0x45, 0x40, 0xe5, 0x04, 0x60, 0x27, 0x06, 0x27, + 0x40, 0x47, 0x00, 0x47, 0x06, 0x20, 0x05, 0xa0, + 0x07, 0xe0, 0x06, 0xe9, 0x02, 0x4b, 0xaf, 0x0d, + 0x0f, 0x80, 0x06, 0x47, 0x06, 0xe5, 0x00, 0x00, + 0x45, 0x00, 0xe5, 0x0f, 0x00, 0xe5, 0x08, 0x20, + 0x06, 0x05, 0x46, 0x67, 0x00, 0x46, 0x00, 0x66, + 0xc0, 0x26, 0x00, 0x45, 0x00, 0x25, 0x20, 0x25, + 0x26, 0x20, 0xe9, 0x02, 0xc0, 0x16, 0xcb, 0x0f, + 0x05, 0x06, 0x27, 0x16, 0xe5, 0x00, 0x00, 0x45, + 0x00, 0xe5, 0x0f, 0x00, 0xe5, 0x02, 0x00, 0x85, + 0x20, 0x06, 0x05, 0x07, 0x06, 0x87, 0x00, 0x06, + 0x27, 0x00, 0x27, 0x26, 0xc0, 0x27, 0x80, 0x45, + 0x00, 0x25, 0x26, 0x20, 0xe9, 0x02, 0x00, 0x25, + 0x07, 0xe0, 0x04, 0x26, 0x27, 0xe5, 0x01, 0x00, + 0x45, 0x00, 0xe5, 0x21, 0x26, 0x05, 0x47, 0x66, + 0x00, 0x47, 0x00, 0x47, 0x06, 0x05, 0x0f, 0x60, + 0x45, 0x07, 0xcb, 0x45, 0x26, 0x20, 0xe9, 0x02, + 0xeb, 0x01, 0x0f, 0xa5, 0x00, 0x06, 0x27, 0x00, + 0xe5, 0x0a, 0x40, 0xe5, 0x10, 0x00, 0xe5, 0x01, + 0x00, 0x05, 0x20, 0xc5, 0x40, 0x06, 0x60, 0x47, + 0x46, 0x00, 0x06, 0x00, 0xe7, 0x00, 0xa0, 0xe9, + 0x02, 0x20, 0x27, 0x16, 0xe0, 0x04, 0xe5, 0x28, + 0x06, 0x25, 0xc6, 0x60, 0x0d, 0xa5, 0x04, 0xe6, + 0x00, 0x16, 0xe9, 0x02, 0x36, 0xe0, 0x1d, 0x25, + 0x00, 0x05, 0x00, 0x85, 0x00, 0xe5, 0x10, 0x00, + 0x05, 0x00, 0xe5, 0x02, 0x06, 0x25, 0xe6, 0x01, + 0x05, 0x20, 0x85, 0x00, 0x04, 0x00, 0xc6, 0x00, + 0xe9, 0x02, 0x20, 0x65, 0xe0, 0x18, 0x05, 0x4f, + 0xf6, 0x07, 0x0f, 0x16, 0x4f, 0x26, 0xaf, 0xe9, + 0x02, 0xeb, 0x02, 0x0f, 0x06, 0x0f, 0x06, 0x0f, + 0x06, 0x12, 0x13, 0x12, 0x13, 0x27, 0xe5, 0x00, + 0x00, 0xe5, 0x1c, 0x60, 0xe6, 0x06, 0x07, 0x86, + 0x16, 0x26, 0x85, 0xe6, 0x03, 0x00, 0xe6, 0x1c, + 0x00, 0xef, 0x00, 0x06, 0xaf, 0x00, 0x2f, 0x96, + 0x6f, 0x36, 0xe0, 0x1d, 0xe5, 0x23, 0x27, 0x66, + 0x07, 0xa6, 0x07, 0x26, 0x27, 0x26, 0x05, 0xe9, + 0x02, 0xb6, 0xa5, 0x27, 0x26, 0x65, 0x46, 0x05, + 0x47, 0x25, 0xc7, 0x45, 0x66, 0xe5, 0x05, 0x06, + 0x27, 0x26, 0xa7, 0x06, 0x05, 0x07, 0xe9, 0x02, + 0x47, 0x06, 0x2f, 0xe1, 0x1e, 0x00, 0x01, 0x80, + 0x01, 0x20, 0xe2, 0x23, 0x16, 0x04, 0x42, 0xe5, + 0x80, 0xc1, 0x00, 0x65, 0x20, 0xc5, 0x00, 0x05, + 0x00, 0x65, 0x20, 0xe5, 0x21, 0x00, 0x65, 0x20, + 0xe5, 0x19, 0x00, 0x65, 0x20, 0xc5, 0x00, 0x05, + 0x00, 0x65, 0x20, 0xe5, 0x07, 0x00, 0xe5, 0x31, + 0x00, 0x65, 0x20, 0xe5, 0x3b, 0x20, 0x46, 0xf6, + 0x01, 0xeb, 0x0c, 0x40, 0xe5, 0x08, 0xef, 0x02, + 0xa0, 0xe1, 0x4e, 0x20, 0xa2, 0x20, 0x11, 0xe5, + 0x81, 0xe4, 0x0f, 0x16, 0xe5, 0x09, 0x17, 0xe5, + 0x12, 0x12, 0x13, 0x40, 0xe5, 0x43, 0x56, 0x4a, + 0xe5, 0x00, 0xc0, 0xe5, 0x0a, 0x46, 0x07, 0xe0, + 0x01, 0xe5, 0x0b, 0x26, 0x07, 0x36, 0xe0, 0x01, + 0xe5, 0x0a, 0x26, 0xe0, 0x04, 0xe5, 0x05, 0x00, + 0x45, 0x00, 0x26, 0xe0, 0x04, 0xe5, 0x2c, 0x26, + 0x07, 0xc6, 0xe7, 0x00, 0x06, 0x27, 0xe6, 0x03, + 0x56, 0x04, 0x56, 0x0d, 0x05, 0x06, 0x20, 0xe9, + 0x02, 0xa0, 0xeb, 0x02, 0xa0, 0xb6, 0x11, 0x76, + 0x46, 0x1b, 0x06, 0xe9, 0x02, 0xa0, 0xe5, 0x1b, + 0x04, 0xe5, 0x2d, 0xc0, 0x85, 0x26, 0xe5, 0x1a, + 0x06, 0x05, 0x80, 0xe5, 0x3e, 0xe0, 0x02, 0xe5, + 0x17, 0x00, 0x46, 0x67, 0x26, 0x47, 0x60, 0x27, + 0x06, 0xa7, 0x46, 0x60, 0x0f, 0x40, 0x36, 0xe9, + 0x02, 0xe5, 0x16, 0x20, 0x85, 0xe0, 0x03, 0xe5, + 0x24, 0x60, 0xe5, 0x12, 0xa0, 0xe9, 0x02, 0x0b, + 0x40, 0xef, 0x1a, 0xe5, 0x0f, 0x26, 0x27, 0x06, + 0x20, 0x36, 0xe5, 0x2d, 0x07, 0x06, 0x07, 0xc6, + 0x00, 0x06, 0x07, 0x06, 0x27, 0xe6, 0x00, 0xa7, + 0xe6, 0x02, 0x20, 0x06, 0xe9, 0x02, 0xa0, 0xe9, + 0x02, 0xa0, 0xd6, 0x04, 0xb6, 0x20, 0xe6, 0x06, + 0x08, 0xe6, 0x17, 0x20, 0xe6, 0x04, 0xe0, 0x0c, + 0x66, 0x07, 0xe5, 0x27, 0x06, 0x07, 0x86, 0x07, + 0x06, 0x87, 0x06, 0x27, 0xe5, 0x00, 0x00, 0x36, + 0xe9, 0x02, 0xd6, 0xef, 0x02, 0xe6, 0x01, 0xef, + 0x01, 0x56, 0x26, 0x07, 0xe5, 0x16, 0x07, 0x66, + 0x27, 0x26, 0x07, 0x46, 0x25, 0xe9, 0x02, 0xe5, + 0x24, 0x06, 0x07, 0x26, 0x47, 0x06, 0x07, 0x46, + 0x27, 0xe0, 0x00, 0x76, 0xe5, 0x1c, 0xe7, 0x00, + 0xe6, 0x00, 0x27, 0x26, 0x40, 0x96, 0xe9, 0x02, + 0x40, 0x45, 0xe9, 0x02, 0xe5, 0x16, 0xa4, 0x36, + 0xe2, 0x01, 0x3f, 0x80, 0xe1, 0x23, 0x20, 0x41, + 0xf6, 0x00, 0xe0, 0x00, 0x46, 0x16, 0xe6, 0x05, + 0x07, 0xc6, 0x65, 0x06, 0xa5, 0x06, 0x25, 0x07, + 0x26, 0x05, 0x80, 0xe2, 0x24, 0xe4, 0x37, 0xe2, + 0x05, 0x04, 0xe2, 0x1a, 0xe4, 0x1d, 0xe6, 0x38, + 0xff, 0x80, 0x0e, 0xe2, 0x00, 0xff, 0x5a, 0xe2, + 0x00, 0xe1, 0x00, 0xa2, 0x20, 0xa1, 0x20, 0xe2, + 0x00, 0xe1, 0x00, 0xe2, 0x00, 0xe1, 0x00, 0xa2, + 0x20, 0xa1, 0x20, 0xe2, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x3f, 0xc2, 0xe1, 0x00, + 0xe2, 0x06, 0x20, 0xe2, 0x00, 0xe3, 0x00, 0xe2, + 0x00, 0xe3, 0x00, 0xe2, 0x00, 0xe3, 0x00, 0x82, + 0x00, 0x22, 0x61, 0x03, 0x0e, 0x02, 0x4e, 0x42, + 0x00, 0x22, 0x61, 0x03, 0x4e, 0x62, 0x20, 0x22, + 0x61, 0x00, 0x4e, 0xe2, 0x00, 0x81, 0x4e, 0x20, + 0x42, 0x00, 0x22, 0x61, 0x03, 0x2e, 0x00, 0xf7, + 0x03, 0x9b, 0xb1, 0x36, 0x14, 0x15, 0x12, 0x34, + 0x15, 0x12, 0x14, 0xf6, 0x00, 0x18, 0x19, 0x9b, + 0x17, 0xf6, 0x01, 0x14, 0x15, 0x76, 0x30, 0x56, + 0x0c, 0x12, 0x13, 0xf6, 0x03, 0x0c, 0x16, 0x10, + 0xf6, 0x02, 0x17, 0x9b, 0x00, 0xfb, 0x02, 0x0b, + 0x04, 0x20, 0xab, 0x4c, 0x12, 0x13, 0x04, 0xeb, + 0x02, 0x4c, 0x12, 0x13, 0x00, 0xe4, 0x05, 0x40, + 0xed, 0x1a, 0xe0, 0x06, 0xe6, 0x05, 0x68, 0x06, + 0x48, 0xe6, 0x04, 0xe0, 0x07, 0x2f, 0x01, 0x6f, + 0x01, 0x2f, 0x02, 0x41, 0x22, 0x41, 0x02, 0x0f, + 0x01, 0x2f, 0x0c, 0x81, 0xaf, 0x01, 0x0f, 0x01, + 0x0f, 0x01, 0x0f, 0x61, 0x0f, 0x02, 0x61, 0x02, + 0x65, 0x02, 0x2f, 0x22, 0x21, 0x8c, 0x3f, 0x42, + 0x0f, 0x0c, 0x2f, 0x02, 0x0f, 0xeb, 0x08, 0xea, + 0x1b, 0x3f, 0x6a, 0x0b, 0x2f, 0x60, 0x8c, 0x8f, + 0x2c, 0x6f, 0x0c, 0x2f, 0x0c, 0x2f, 0x0c, 0xcf, + 0x0c, 0xef, 0x17, 0x2c, 0x2f, 0x0c, 0x0f, 0x0c, + 0xef, 0x17, 0xec, 0x80, 0x84, 0xef, 0x00, 0x12, + 0x13, 0x12, 0x13, 0xef, 0x0c, 0x2c, 0xcf, 0x12, + 0x13, 0xef, 0x49, 0x0c, 0xef, 0x16, 0xec, 0x11, + 0xef, 0x20, 0xac, 0xef, 0x40, 0xe0, 0x0e, 0xef, + 0x03, 0xe0, 0x0d, 0xeb, 0x34, 0xef, 0x46, 0xeb, + 0x0e, 0xef, 0x80, 0x2f, 0x0c, 0xef, 0x01, 0x0c, + 0xef, 0x2e, 0xec, 0x00, 0xef, 0x67, 0x0c, 0xef, + 0x80, 0x70, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, - 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0xeb, 0x16, - 0xef, 0x24, 0x8c, 0x12, 0x13, 0xec, 0x17, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0xec, 0x08, 0xef, 0x80, 0x78, 0xec, 0x7b, + 0xeb, 0x16, 0xef, 0x24, 0x8c, 0x12, 0x13, 0xec, + 0x17, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, + 0x13, 0x12, 0x13, 0xec, 0x08, 0xef, 0x80, 0x78, + 0xec, 0x7b, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, - 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0xec, 0x37, - 0x12, 0x13, 0x12, 0x13, 0xec, 0x18, 0x12, 0x13, - 0xec, 0x80, 0x7a, 0xef, 0x28, 0xec, 0x0d, 0x2f, - 0xac, 0xef, 0x1f, 0x20, 0xef, 0x18, 0x00, 0xef, - 0x61, 0xe1, 0x28, 0xe2, 0x28, 0x5f, 0x21, 0x22, + 0xec, 0x37, 0x12, 0x13, 0x12, 0x13, 0xec, 0x18, + 0x12, 0x13, 0xec, 0x80, 0x7a, 0xef, 0x28, 0xec, + 0x0d, 0x2f, 0xac, 0xef, 0x1f, 0x20, 0xef, 0x80, + 0x02, 0xe1, 0x28, 0xe2, 0x28, 0x5f, 0x21, 0x22, 0xdf, 0x41, 0x02, 0x3f, 0x02, 0x3f, 0x82, 0x24, 0x41, 0x02, 0xff, 0x5a, 0x02, 0xaf, 0x7f, 0x46, 0x3f, 0x80, 0x76, 0x0b, 0x36, 0xe2, 0x1e, 0x00, @@ -2622,273 +2633,280 @@ static const uint8_t unicode_gc_table[4070] = { 0xff, 0x36, 0x04, 0xe2, 0x00, 0x9f, 0xff, 0x02, 0x04, 0x2e, 0x7f, 0x05, 0x7f, 0x22, 0xff, 0x0d, 0x61, 0x02, 0x81, 0x02, 0xff, 0x07, 0x41, 0x02, - 0x5f, 0x3f, 0x20, 0x3f, 0x00, 0x02, 0x00, 0x02, - 0xdf, 0xe0, 0x0d, 0x44, 0x3f, 0x05, 0x24, 0x02, - 0xc5, 0x06, 0x45, 0x06, 0x65, 0x06, 0xe5, 0x0f, - 0x27, 0x26, 0x07, 0x6f, 0x06, 0x40, 0xab, 0x2f, - 0x0d, 0x0f, 0xa0, 0xe5, 0x2c, 0x76, 0xe0, 0x00, - 0x27, 0xe5, 0x2a, 0xe7, 0x08, 0x26, 0xe0, 0x00, - 0x36, 0xe9, 0x02, 0xa0, 0xe6, 0x0a, 0xa5, 0x56, - 0x05, 0x16, 0x25, 0x06, 0xe9, 0x02, 0xe5, 0x14, - 0xe6, 0x00, 0x36, 0xe5, 0x0f, 0xe6, 0x03, 0x27, - 0xe0, 0x03, 0x16, 0xe5, 0x15, 0x40, 0x46, 0x07, - 0xe5, 0x27, 0x06, 0x27, 0x66, 0x27, 0x26, 0x47, - 0xf6, 0x05, 0x00, 0x04, 0xe9, 0x02, 0x60, 0x36, - 0x85, 0x06, 0x04, 0xe5, 0x01, 0xe9, 0x02, 0x85, - 0x00, 0xe5, 0x21, 0xa6, 0x27, 0x26, 0x27, 0x26, - 0xe0, 0x01, 0x45, 0x06, 0xe5, 0x00, 0x06, 0x07, - 0x20, 0xe9, 0x02, 0x20, 0x76, 0xe5, 0x08, 0x04, - 0xa5, 0x4f, 0x05, 0x07, 0x06, 0x07, 0xe5, 0x2a, - 0x06, 0x05, 0x46, 0x25, 0x26, 0x85, 0x26, 0x05, - 0x06, 0x05, 0xe0, 0x10, 0x25, 0x04, 0x36, 0xe5, - 0x03, 0x07, 0x26, 0x27, 0x36, 0x05, 0x24, 0x07, - 0x06, 0xe0, 0x02, 0xa5, 0x20, 0xa5, 0x20, 0xa5, - 0xe0, 0x01, 0xc5, 0x00, 0xc5, 0x00, 0xe2, 0x23, - 0x0e, 0x64, 0xe2, 0x01, 0x04, 0x2e, 0x60, 0xe2, - 0x48, 0xe5, 0x1b, 0x27, 0x06, 0x27, 0x06, 0x27, - 0x16, 0x07, 0x06, 0x20, 0xe9, 0x02, 0xa0, 0xe5, - 0xab, 0x1c, 0xe0, 0x04, 0xe5, 0x0f, 0x60, 0xe5, - 0x29, 0x60, 0xfc, 0x87, 0x78, 0xfd, 0x98, 0x78, - 0xe5, 0x80, 0xe6, 0x20, 0xe5, 0x62, 0xe0, 0x1e, - 0xc2, 0xe0, 0x04, 0x82, 0x80, 0x05, 0x06, 0xe5, - 0x02, 0x0c, 0xe5, 0x05, 0x00, 0x85, 0x00, 0x05, - 0x00, 0x25, 0x00, 0x25, 0x00, 0xe5, 0x64, 0xee, - 0x09, 0xe0, 0x08, 0xe5, 0x80, 0xe3, 0x13, 0x12, - 0xef, 0x08, 0xe5, 0x38, 0x20, 0xe5, 0x2e, 0xc0, - 0x0f, 0xe0, 0x18, 0xe5, 0x04, 0x0d, 0x4f, 0xe6, - 0x08, 0xd6, 0x12, 0x13, 0x16, 0xa0, 0xe6, 0x08, - 0x16, 0x31, 0x30, 0x12, 0x13, 0x12, 0x13, 0x12, + 0x5f, 0xff, 0x09, 0xe0, 0x0c, 0x64, 0x3f, 0x05, + 0x24, 0x02, 0xc5, 0x06, 0x45, 0x06, 0x65, 0x06, + 0xe5, 0x0f, 0x27, 0x26, 0x07, 0x6f, 0x06, 0x40, + 0xab, 0x2f, 0x0d, 0x0f, 0xa0, 0xe5, 0x2c, 0x76, + 0xe0, 0x00, 0x27, 0xe5, 0x2a, 0xe7, 0x08, 0x26, + 0xe0, 0x00, 0x36, 0xe9, 0x02, 0xa0, 0xe6, 0x0a, + 0xa5, 0x56, 0x05, 0x16, 0x25, 0x06, 0xe9, 0x02, + 0xe5, 0x14, 0xe6, 0x00, 0x36, 0xe5, 0x0f, 0xe6, + 0x03, 0x27, 0xe0, 0x03, 0x16, 0xe5, 0x15, 0x40, + 0x46, 0x07, 0xe5, 0x27, 0x06, 0x27, 0x66, 0x27, + 0x26, 0x47, 0xf6, 0x05, 0x00, 0x04, 0xe9, 0x02, + 0x60, 0x36, 0x85, 0x06, 0x04, 0xe5, 0x01, 0xe9, + 0x02, 0x85, 0x00, 0xe5, 0x21, 0xa6, 0x27, 0x26, + 0x27, 0x26, 0xe0, 0x01, 0x45, 0x06, 0xe5, 0x00, + 0x06, 0x07, 0x20, 0xe9, 0x02, 0x20, 0x76, 0xe5, + 0x08, 0x04, 0xa5, 0x4f, 0x05, 0x07, 0x06, 0x07, + 0xe5, 0x2a, 0x06, 0x05, 0x46, 0x25, 0x26, 0x85, + 0x26, 0x05, 0x06, 0x05, 0xe0, 0x10, 0x25, 0x04, + 0x36, 0xe5, 0x03, 0x07, 0x26, 0x27, 0x36, 0x05, + 0x24, 0x07, 0x06, 0xe0, 0x02, 0xa5, 0x20, 0xa5, + 0x20, 0xa5, 0xe0, 0x01, 0xc5, 0x00, 0xc5, 0x00, + 0xe2, 0x23, 0x0e, 0x64, 0xe2, 0x01, 0x04, 0x2e, + 0x60, 0xe2, 0x48, 0xe5, 0x1b, 0x27, 0x06, 0x27, + 0x06, 0x27, 0x16, 0x07, 0x06, 0x20, 0xe9, 0x02, + 0xa0, 0xe5, 0xab, 0x1c, 0xe0, 0x04, 0xe5, 0x0f, + 0x60, 0xe5, 0x29, 0x60, 0xfc, 0x87, 0x78, 0xfd, + 0x98, 0x78, 0xe5, 0x80, 0xe6, 0x20, 0xe5, 0x62, + 0xe0, 0x1e, 0xc2, 0xe0, 0x04, 0x82, 0x80, 0x05, + 0x06, 0xe5, 0x02, 0x0c, 0xe5, 0x05, 0x00, 0x85, + 0x00, 0x05, 0x00, 0x25, 0x00, 0x25, 0x00, 0xe5, + 0x64, 0xee, 0x09, 0xef, 0x08, 0xe5, 0x80, 0xe3, + 0x13, 0x12, 0xef, 0x08, 0xe5, 0x38, 0x2f, 0xe5, + 0x2e, 0xef, 0x00, 0xe0, 0x18, 0xe5, 0x04, 0x0d, + 0x4f, 0xe6, 0x08, 0xd6, 0x12, 0x13, 0x16, 0xa0, + 0xe6, 0x08, 0x16, 0x31, 0x30, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0x12, 0x13, 0x36, 0x12, 0x13, 0x76, 0x50, - 0x56, 0x00, 0x76, 0x11, 0x12, 0x13, 0x12, 0x13, - 0x12, 0x13, 0x56, 0x0c, 0x11, 0x4c, 0x00, 0x16, - 0x0d, 0x36, 0x60, 0x85, 0x00, 0xe5, 0x7f, 0x20, - 0x1b, 0x00, 0x56, 0x0d, 0x56, 0x12, 0x13, 0x16, - 0x0c, 0x16, 0x11, 0x36, 0xe9, 0x02, 0x36, 0x4c, - 0x36, 0xe1, 0x12, 0x12, 0x16, 0x13, 0x0e, 0x10, - 0x0e, 0xe2, 0x12, 0x12, 0x0c, 0x13, 0x0c, 0x12, - 0x13, 0x16, 0x12, 0x13, 0x36, 0xe5, 0x02, 0x04, - 0xe5, 0x25, 0x24, 0xe5, 0x17, 0x40, 0xa5, 0x20, - 0xa5, 0x20, 0xa5, 0x20, 0x45, 0x40, 0x2d, 0x0c, - 0x0e, 0x0f, 0x2d, 0x00, 0x0f, 0x6c, 0x2f, 0xe0, - 0x02, 0x5b, 0x2f, 0x20, 0xe5, 0x04, 0x00, 0xe5, - 0x12, 0x00, 0xe5, 0x0b, 0x00, 0x25, 0x00, 0xe5, - 0x07, 0x20, 0xe5, 0x06, 0xe0, 0x1a, 0xe5, 0x73, - 0x80, 0x56, 0x60, 0xeb, 0x25, 0x40, 0xef, 0x01, - 0xea, 0x2d, 0x6b, 0xef, 0x09, 0x2b, 0x4f, 0x00, - 0xef, 0x05, 0x40, 0x0f, 0xe0, 0x27, 0xef, 0x25, - 0x06, 0xe0, 0x7a, 0xe5, 0x15, 0x40, 0xe5, 0x29, - 0xe0, 0x07, 0x06, 0xeb, 0x13, 0x60, 0xe5, 0x18, - 0x6b, 0xe0, 0x01, 0xe5, 0x0c, 0x0a, 0xe5, 0x00, - 0x0a, 0x80, 0xe5, 0x1e, 0x86, 0x80, 0xe5, 0x16, - 0x00, 0x16, 0xe5, 0x1c, 0x60, 0xe5, 0x00, 0x16, - 0x8a, 0xe0, 0x22, 0xe1, 0x20, 0xe2, 0x20, 0xe5, - 0x46, 0x20, 0xe9, 0x02, 0xa0, 0xe1, 0x1c, 0x60, - 0xe2, 0x1c, 0x60, 0xe5, 0x20, 0xe0, 0x00, 0xe5, - 0x2c, 0xe0, 0x03, 0x16, 0xe1, 0x03, 0x00, 0xe1, - 0x07, 0x00, 0xc1, 0x00, 0x21, 0x00, 0xe2, 0x03, - 0x00, 0xe2, 0x07, 0x00, 0xc2, 0x00, 0x22, 0x40, - 0xe5, 0x2c, 0xe0, 0x04, 0xe5, 0x80, 0xaf, 0xe0, - 0x01, 0xe5, 0x0e, 0xe0, 0x02, 0xe5, 0x00, 0xe0, - 0x10, 0xa4, 0x00, 0xe4, 0x22, 0x00, 0xe4, 0x01, - 0xe0, 0x3d, 0xa5, 0x20, 0x05, 0x00, 0xe5, 0x24, - 0x00, 0x25, 0x40, 0x05, 0x20, 0xe5, 0x0f, 0x00, - 0x16, 0xeb, 0x00, 0xe5, 0x0f, 0x2f, 0xcb, 0xe5, - 0x17, 0xe0, 0x00, 0xeb, 0x01, 0xe0, 0x28, 0xe5, - 0x0b, 0x00, 0x25, 0x80, 0x8b, 0xe5, 0x0e, 0xab, - 0x40, 0x16, 0xe5, 0x12, 0x80, 0x16, 0xe0, 0x38, - 0xe5, 0x30, 0x60, 0x2b, 0x25, 0xeb, 0x08, 0x20, - 0xeb, 0x26, 0x05, 0x46, 0x00, 0x26, 0x80, 0x66, - 0x65, 0x00, 0x45, 0x00, 0xe5, 0x15, 0x20, 0x46, - 0x60, 0x06, 0xeb, 0x01, 0xc0, 0xf6, 0x01, 0xc0, - 0xe5, 0x15, 0x2b, 0x16, 0xe5, 0x15, 0x4b, 0xe0, - 0x18, 0xe5, 0x00, 0x0f, 0xe5, 0x14, 0x26, 0x60, - 0x8b, 0xd6, 0xe0, 0x01, 0xe5, 0x2e, 0x40, 0xd6, - 0xe5, 0x0e, 0x20, 0xeb, 0x00, 0xe5, 0x0b, 0x80, - 0xeb, 0x00, 0xe5, 0x0a, 0xc0, 0x76, 0xe0, 0x04, - 0xcb, 0xe0, 0x48, 0xe5, 0x41, 0xe0, 0x2f, 0xe1, - 0x2b, 0xe0, 0x05, 0xe2, 0x2b, 0xc0, 0xab, 0xe5, - 0x1c, 0x66, 0xe0, 0x00, 0xe9, 0x02, 0xa0, 0xe9, - 0x02, 0x65, 0x04, 0x05, 0xe1, 0x0e, 0x40, 0x86, - 0x11, 0x04, 0xe2, 0x0e, 0xe0, 0x00, 0x2c, 0xe0, - 0x80, 0x48, 0xeb, 0x17, 0x00, 0xe5, 0x22, 0x00, - 0x26, 0x11, 0x20, 0x25, 0xe0, 0x08, 0x45, 0xe0, - 0x2f, 0x66, 0xe5, 0x15, 0xeb, 0x02, 0x05, 0xe0, - 0x00, 0xe5, 0x0e, 0xe6, 0x03, 0x6b, 0x96, 0xe0, - 0x0e, 0xe5, 0x0a, 0x66, 0x76, 0xe0, 0x1e, 0xe5, - 0x0d, 0xcb, 0xe0, 0x0c, 0xe5, 0x0f, 0xe0, 0x01, - 0x07, 0x06, 0x07, 0xe5, 0x2d, 0xe6, 0x07, 0xd6, - 0x60, 0xeb, 0x0c, 0xe9, 0x02, 0x06, 0x25, 0x26, - 0x05, 0xe0, 0x01, 0x46, 0x07, 0xe5, 0x25, 0x47, - 0x66, 0x27, 0x26, 0x36, 0x1b, 0x76, 0x06, 0xe0, - 0x02, 0x1b, 0x20, 0xe5, 0x11, 0xc0, 0xe9, 0x02, - 0xa0, 0x46, 0xe5, 0x1c, 0x86, 0x07, 0xe6, 0x00, - 0x00, 0xe9, 0x02, 0x76, 0x05, 0x27, 0x05, 0xe0, - 0x00, 0xe5, 0x1b, 0x06, 0x36, 0x05, 0xe0, 0x01, - 0x26, 0x07, 0xe5, 0x28, 0x47, 0xe6, 0x01, 0x27, - 0x65, 0x76, 0x66, 0x16, 0x07, 0x06, 0xe9, 0x02, - 0x05, 0x16, 0x05, 0x56, 0x00, 0xeb, 0x0c, 0xe0, - 0x03, 0xe5, 0x0a, 0x00, 0xe5, 0x11, 0x47, 0x46, - 0x27, 0x06, 0x07, 0x26, 0xb6, 0x06, 0x25, 0x06, - 0xe0, 0x36, 0xc5, 0x00, 0x05, 0x00, 0x65, 0x00, - 0xe5, 0x07, 0x00, 0xe5, 0x02, 0x16, 0xa0, 0xe5, - 0x27, 0x06, 0x47, 0xe6, 0x00, 0x80, 0xe9, 0x02, - 0xa0, 0x26, 0x27, 0x00, 0xe5, 0x00, 0x20, 0x25, - 0x20, 0xe5, 0x0e, 0x00, 0xc5, 0x00, 0x25, 0x00, - 0x85, 0x00, 0x26, 0x05, 0x27, 0x06, 0x67, 0x20, - 0x27, 0x20, 0x47, 0x20, 0x05, 0xa0, 0x07, 0x80, - 0x85, 0x27, 0x20, 0xc6, 0x40, 0x86, 0xe0, 0x03, - 0xe5, 0x02, 0x00, 0x05, 0x20, 0x05, 0x00, 0xe5, - 0x1e, 0x00, 0x05, 0x47, 0xa6, 0x00, 0x07, 0x20, - 0x07, 0x00, 0x67, 0x00, 0x27, 0x06, 0x07, 0x06, - 0x05, 0x06, 0x05, 0x36, 0x00, 0x36, 0xe0, 0x00, - 0x26, 0xe0, 0x15, 0xe5, 0x2d, 0x47, 0xe6, 0x00, - 0x27, 0x46, 0x07, 0x06, 0x65, 0x96, 0xe9, 0x02, - 0x36, 0x00, 0x16, 0x06, 0x45, 0xe0, 0x16, 0xe5, - 0x28, 0x47, 0xa6, 0x07, 0x06, 0x67, 0x26, 0x07, - 0x26, 0x25, 0x16, 0x05, 0xe0, 0x00, 0xe9, 0x02, - 0xe0, 0x80, 0x1e, 0xe5, 0x27, 0x47, 0x66, 0x20, - 0x67, 0x26, 0x07, 0x26, 0xf6, 0x0f, 0x65, 0x26, - 0xe0, 0x1a, 0xe5, 0x28, 0x47, 0xe6, 0x00, 0x27, - 0x06, 0x07, 0x26, 0x56, 0x05, 0xe0, 0x03, 0xe9, - 0x02, 0xa0, 0xf6, 0x05, 0xe0, 0x0b, 0xe5, 0x23, - 0x06, 0x07, 0x06, 0x27, 0xa6, 0x07, 0x06, 0x05, - 0x16, 0xa0, 0xe9, 0x02, 0xa0, 0xe9, 0x0c, 0xe0, - 0x14, 0xe5, 0x13, 0x20, 0x06, 0x07, 0x06, 0x27, - 0x66, 0x07, 0x86, 0x60, 0xe9, 0x02, 0x2b, 0x56, - 0x0f, 0xc5, 0xe0, 0x80, 0x31, 0xe5, 0x24, 0x47, - 0xe6, 0x01, 0x07, 0x26, 0x16, 0xe0, 0x5c, 0xe1, - 0x18, 0xe2, 0x18, 0xe9, 0x02, 0xeb, 0x01, 0xe0, - 0x04, 0xe5, 0x00, 0x20, 0x05, 0x20, 0xe5, 0x00, - 0x00, 0x25, 0x00, 0xe5, 0x10, 0xa7, 0x00, 0x27, - 0x20, 0x26, 0x07, 0x06, 0x05, 0x07, 0x05, 0x07, - 0x06, 0x56, 0xe0, 0x01, 0xe9, 0x02, 0xe0, 0x3e, - 0xe5, 0x00, 0x20, 0xe5, 0x1f, 0x47, 0x66, 0x20, - 0x26, 0x67, 0x06, 0x05, 0x16, 0x05, 0x07, 0xe0, - 0x13, 0x05, 0xe6, 0x02, 0xe5, 0x20, 0xa6, 0x07, - 0x05, 0x66, 0xf6, 0x00, 0x06, 0xe0, 0x00, 0x05, - 0xa6, 0x27, 0x46, 0xe5, 0x26, 0xe6, 0x05, 0x07, - 0x26, 0x56, 0x05, 0x96, 0xe0, 0x05, 0xe5, 0x41, - 0xc0, 0xf6, 0x02, 0xe0, 0x80, 0x2e, 0xe5, 0x19, - 0x16, 0xe0, 0x06, 0xe9, 0x02, 0xa0, 0xe5, 0x01, - 0x00, 0xe5, 0x1d, 0x07, 0xc6, 0x00, 0xa6, 0x07, - 0x06, 0x05, 0x96, 0xe0, 0x02, 0xe9, 0x02, 0xeb, - 0x0b, 0x40, 0x36, 0xe5, 0x16, 0x20, 0xe6, 0x0e, - 0x00, 0x07, 0xc6, 0x07, 0x26, 0x07, 0x26, 0xe0, - 0x41, 0xc5, 0x00, 0x25, 0x00, 0xe5, 0x1e, 0xa6, - 0x40, 0x06, 0x00, 0x26, 0x00, 0xc6, 0x05, 0x06, - 0xe0, 0x00, 0xe9, 0x02, 0xa0, 0xa5, 0x00, 0x25, - 0x00, 0xe5, 0x18, 0x87, 0x00, 0x26, 0x00, 0x27, - 0x06, 0x07, 0x06, 0x05, 0xc0, 0xe9, 0x02, 0xe0, - 0x80, 0xae, 0xe5, 0x0b, 0x26, 0x27, 0x36, 0xc0, - 0x26, 0x05, 0x07, 0xe5, 0x05, 0x00, 0xe5, 0x1a, - 0x27, 0x86, 0x40, 0x27, 0x06, 0x07, 0x06, 0xf6, - 0x05, 0xe9, 0x02, 0x06, 0xe0, 0x4d, 0x05, 0xe0, - 0x07, 0xeb, 0x0d, 0xef, 0x00, 0x6d, 0xef, 0x09, - 0xe0, 0x05, 0x16, 0xe5, 0x83, 0x12, 0xe0, 0x5e, - 0xea, 0x67, 0x00, 0x96, 0xe0, 0x03, 0xe5, 0x80, - 0x3c, 0xe0, 0x89, 0xc4, 0xe5, 0x59, 0x36, 0xe0, - 0x05, 0xe5, 0x83, 0xa8, 0xfb, 0x08, 0x06, 0xa5, - 0xe6, 0x07, 0xe0, 0x02, 0xe5, 0x8f, 0x13, 0x80, - 0xe5, 0x81, 0xbf, 0xe0, 0x9a, 0x31, 0xe5, 0x16, - 0xe6, 0x04, 0x47, 0x46, 0xe9, 0x02, 0xe0, 0x86, - 0x3e, 0xe5, 0x81, 0xb1, 0xc0, 0xe5, 0x17, 0x00, - 0xe9, 0x02, 0x60, 0x36, 0xe5, 0x47, 0x00, 0xe9, - 0x02, 0xa0, 0xe5, 0x16, 0x20, 0x86, 0x16, 0xe0, - 0x02, 0xe5, 0x28, 0xc6, 0x96, 0x6f, 0x64, 0x16, - 0x0f, 0xe0, 0x02, 0xe9, 0x02, 0x00, 0xcb, 0x00, - 0xe5, 0x0d, 0x80, 0xe5, 0x0b, 0xe0, 0x81, 0x28, - 0x44, 0xe5, 0x20, 0x24, 0x56, 0xe9, 0x02, 0xe0, - 0x80, 0x3e, 0xe1, 0x18, 0xe2, 0x18, 0xeb, 0x0f, - 0x76, 0xe0, 0x5d, 0xe5, 0x43, 0x60, 0x06, 0x05, + 0x13, 0x12, 0x13, 0x12, 0x13, 0x36, 0x12, 0x13, + 0x76, 0x50, 0x56, 0x00, 0x76, 0x11, 0x12, 0x13, + 0x12, 0x13, 0x12, 0x13, 0x56, 0x0c, 0x11, 0x4c, + 0x00, 0x16, 0x0d, 0x36, 0x60, 0x85, 0x00, 0xe5, + 0x7f, 0x20, 0x1b, 0x00, 0x56, 0x0d, 0x56, 0x12, + 0x13, 0x16, 0x0c, 0x16, 0x11, 0x36, 0xe9, 0x02, + 0x36, 0x4c, 0x36, 0xe1, 0x12, 0x12, 0x16, 0x13, + 0x0e, 0x10, 0x0e, 0xe2, 0x12, 0x12, 0x0c, 0x13, + 0x0c, 0x12, 0x13, 0x16, 0x12, 0x13, 0x36, 0xe5, + 0x02, 0x04, 0xe5, 0x25, 0x24, 0xe5, 0x17, 0x40, + 0xa5, 0x20, 0xa5, 0x20, 0xa5, 0x20, 0x45, 0x40, + 0x2d, 0x0c, 0x0e, 0x0f, 0x2d, 0x00, 0x0f, 0x6c, + 0x2f, 0xe0, 0x02, 0x5b, 0x2f, 0x20, 0xe5, 0x04, + 0x00, 0xe5, 0x12, 0x00, 0xe5, 0x0b, 0x00, 0x25, + 0x00, 0xe5, 0x07, 0x20, 0xe5, 0x06, 0xe0, 0x1a, + 0xe5, 0x73, 0x80, 0x56, 0x60, 0xeb, 0x25, 0x40, + 0xef, 0x01, 0xea, 0x2d, 0x6b, 0xef, 0x09, 0x2b, + 0x4f, 0x00, 0xef, 0x05, 0x40, 0x0f, 0xe0, 0x27, + 0xef, 0x25, 0x06, 0xe0, 0x7a, 0xe5, 0x15, 0x40, + 0xe5, 0x29, 0xe0, 0x07, 0x06, 0xeb, 0x13, 0x60, + 0xe5, 0x18, 0x6b, 0xe0, 0x01, 0xe5, 0x0c, 0x0a, + 0xe5, 0x00, 0x0a, 0x80, 0xe5, 0x1e, 0x86, 0x80, + 0xe5, 0x16, 0x00, 0x16, 0xe5, 0x1c, 0x60, 0xe5, + 0x00, 0x16, 0x8a, 0xe0, 0x22, 0xe1, 0x20, 0xe2, + 0x20, 0xe5, 0x46, 0x20, 0xe9, 0x02, 0xa0, 0xe1, + 0x1c, 0x60, 0xe2, 0x1c, 0x60, 0xe5, 0x20, 0xe0, + 0x00, 0xe5, 0x2c, 0xe0, 0x03, 0x16, 0xe1, 0x03, + 0x00, 0xe1, 0x07, 0x00, 0xc1, 0x00, 0x21, 0x00, + 0xe2, 0x03, 0x00, 0xe2, 0x07, 0x00, 0xc2, 0x00, + 0x22, 0x40, 0xe5, 0x2c, 0xe0, 0x04, 0xe5, 0x80, + 0xaf, 0xe0, 0x01, 0xe5, 0x0e, 0xe0, 0x02, 0xe5, + 0x00, 0xe0, 0x10, 0xa4, 0x00, 0xe4, 0x22, 0x00, + 0xe4, 0x01, 0xe0, 0x3d, 0xa5, 0x20, 0x05, 0x00, + 0xe5, 0x24, 0x00, 0x25, 0x40, 0x05, 0x20, 0xe5, + 0x0f, 0x00, 0x16, 0xeb, 0x00, 0xe5, 0x0f, 0x2f, + 0xcb, 0xe5, 0x17, 0xe0, 0x00, 0xeb, 0x01, 0xe0, + 0x28, 0xe5, 0x0b, 0x00, 0x25, 0x80, 0x8b, 0xe5, + 0x0e, 0xab, 0x40, 0x16, 0xe5, 0x12, 0x80, 0x16, + 0xe5, 0x12, 0xe0, 0x1e, 0xe5, 0x30, 0x60, 0x2b, + 0x25, 0xeb, 0x08, 0x20, 0xeb, 0x26, 0x05, 0x46, + 0x00, 0x26, 0x80, 0x66, 0x65, 0x00, 0x45, 0x00, + 0xe5, 0x15, 0x20, 0x46, 0x60, 0x06, 0xeb, 0x01, + 0xc0, 0xf6, 0x01, 0xc0, 0xe5, 0x15, 0x2b, 0x16, + 0xe5, 0x15, 0x4b, 0xe0, 0x18, 0xe5, 0x00, 0x0f, + 0xe5, 0x14, 0x26, 0x60, 0x8b, 0xd6, 0xe0, 0x01, + 0xe5, 0x2e, 0x40, 0xd6, 0xe5, 0x0e, 0x20, 0xeb, + 0x00, 0xe5, 0x0b, 0x80, 0xeb, 0x00, 0xe5, 0x0a, + 0xc0, 0x76, 0xe0, 0x04, 0xcb, 0xe0, 0x48, 0xe5, + 0x41, 0xe0, 0x2f, 0xe1, 0x2b, 0xe0, 0x05, 0xe2, + 0x2b, 0xc0, 0xab, 0xe5, 0x1c, 0x66, 0xe0, 0x00, + 0xe9, 0x02, 0xa0, 0xe9, 0x02, 0x65, 0x04, 0x05, + 0xe1, 0x0e, 0x40, 0x86, 0x11, 0x04, 0xe2, 0x0e, + 0xe0, 0x00, 0x2c, 0xe0, 0x80, 0x48, 0xeb, 0x17, + 0x00, 0xe5, 0x22, 0x00, 0x26, 0x11, 0x20, 0x25, + 0xe0, 0x08, 0x45, 0x04, 0x25, 0xe0, 0x00, 0x16, + 0xef, 0x00, 0xe0, 0x19, 0xa6, 0xe5, 0x15, 0xeb, + 0x02, 0x05, 0xe0, 0x00, 0xe5, 0x0e, 0xe6, 0x03, + 0x6b, 0x96, 0xe0, 0x0e, 0xe5, 0x0a, 0x66, 0x76, + 0xe0, 0x1e, 0xe5, 0x0d, 0xcb, 0xe0, 0x0c, 0xe5, + 0x0f, 0xe0, 0x01, 0x07, 0x06, 0x07, 0xe5, 0x2d, + 0xe6, 0x07, 0xd6, 0x60, 0xeb, 0x0c, 0xe9, 0x02, + 0x06, 0x25, 0x26, 0x05, 0xe0, 0x01, 0x46, 0x07, + 0xe5, 0x25, 0x47, 0x66, 0x27, 0x26, 0x36, 0x1b, + 0x76, 0x06, 0xe0, 0x02, 0x1b, 0x20, 0xe5, 0x11, + 0xc0, 0xe9, 0x02, 0xa0, 0x46, 0xe5, 0x1c, 0x86, + 0x07, 0xe6, 0x00, 0x00, 0xe9, 0x02, 0x76, 0x05, + 0x27, 0x05, 0xe0, 0x00, 0xe5, 0x1b, 0x06, 0x36, + 0x05, 0xe0, 0x01, 0x26, 0x07, 0xe5, 0x28, 0x47, + 0xe6, 0x01, 0x27, 0x65, 0x76, 0x66, 0x16, 0x07, + 0x06, 0xe9, 0x02, 0x05, 0x16, 0x05, 0x56, 0x00, + 0xeb, 0x0c, 0xe0, 0x03, 0xe5, 0x0a, 0x00, 0xe5, + 0x11, 0x47, 0x46, 0x27, 0x06, 0x07, 0x26, 0xb6, + 0x06, 0x25, 0x06, 0xe0, 0x36, 0xc5, 0x00, 0x05, + 0x00, 0x65, 0x00, 0xe5, 0x07, 0x00, 0xe5, 0x02, + 0x16, 0xa0, 0xe5, 0x27, 0x06, 0x47, 0xe6, 0x00, + 0x80, 0xe9, 0x02, 0xa0, 0x26, 0x27, 0x00, 0xe5, + 0x00, 0x20, 0x25, 0x20, 0xe5, 0x0e, 0x00, 0xc5, + 0x00, 0x25, 0x00, 0x85, 0x00, 0x26, 0x05, 0x27, + 0x06, 0x67, 0x20, 0x27, 0x20, 0x47, 0x20, 0x05, + 0xa0, 0x07, 0x80, 0x85, 0x27, 0x20, 0xc6, 0x40, + 0x86, 0xe0, 0x03, 0xe5, 0x02, 0x00, 0x05, 0x20, + 0x05, 0x00, 0xe5, 0x1e, 0x00, 0x05, 0x47, 0xa6, + 0x00, 0x07, 0x20, 0x07, 0x00, 0x67, 0x00, 0x27, + 0x06, 0x07, 0x06, 0x05, 0x06, 0x05, 0x36, 0x00, + 0x36, 0xe0, 0x00, 0x26, 0xe0, 0x15, 0xe5, 0x2d, + 0x47, 0xe6, 0x00, 0x27, 0x46, 0x07, 0x06, 0x65, + 0x96, 0xe9, 0x02, 0x36, 0x00, 0x16, 0x06, 0x45, + 0xe0, 0x16, 0xe5, 0x28, 0x47, 0xa6, 0x07, 0x06, + 0x67, 0x26, 0x07, 0x26, 0x25, 0x16, 0x05, 0xe0, + 0x00, 0xe9, 0x02, 0xe0, 0x80, 0x1e, 0xe5, 0x27, + 0x47, 0x66, 0x20, 0x67, 0x26, 0x07, 0x26, 0xf6, + 0x0f, 0x65, 0x26, 0xe0, 0x1a, 0xe5, 0x28, 0x47, + 0xe6, 0x00, 0x27, 0x06, 0x07, 0x26, 0x56, 0x05, + 0xe0, 0x03, 0xe9, 0x02, 0xa0, 0xf6, 0x05, 0xe0, + 0x0b, 0xe5, 0x23, 0x06, 0x07, 0x06, 0x27, 0xa6, + 0x07, 0x06, 0x05, 0x16, 0xa0, 0xe9, 0x02, 0xa0, + 0xe9, 0x0c, 0xe0, 0x14, 0xe5, 0x13, 0x20, 0x06, + 0x07, 0x06, 0x27, 0x66, 0x07, 0x86, 0x60, 0xe9, + 0x02, 0x2b, 0x56, 0x0f, 0xc5, 0xe0, 0x80, 0x31, + 0xe5, 0x24, 0x47, 0xe6, 0x01, 0x07, 0x26, 0x16, + 0xe0, 0x5c, 0xe1, 0x18, 0xe2, 0x18, 0xe9, 0x02, + 0xeb, 0x01, 0xe0, 0x04, 0xe5, 0x00, 0x20, 0x05, + 0x20, 0xe5, 0x00, 0x00, 0x25, 0x00, 0xe5, 0x10, + 0xa7, 0x00, 0x27, 0x20, 0x26, 0x07, 0x06, 0x05, + 0x07, 0x05, 0x07, 0x06, 0x56, 0xe0, 0x01, 0xe9, + 0x02, 0xe0, 0x3e, 0xe5, 0x00, 0x20, 0xe5, 0x1f, + 0x47, 0x66, 0x20, 0x26, 0x67, 0x06, 0x05, 0x16, + 0x05, 0x07, 0xe0, 0x13, 0x05, 0xe6, 0x02, 0xe5, + 0x20, 0xa6, 0x07, 0x05, 0x66, 0xf6, 0x00, 0x06, + 0xe0, 0x00, 0x05, 0xa6, 0x27, 0x46, 0xe5, 0x26, + 0xe6, 0x05, 0x07, 0x26, 0x56, 0x05, 0x96, 0xe0, + 0x05, 0xe5, 0x41, 0xc0, 0xf6, 0x02, 0xe0, 0x4e, + 0x06, 0x07, 0x46, 0x07, 0x06, 0x07, 0xe0, 0x50, + 0xe5, 0x19, 0x16, 0xe0, 0x06, 0xe9, 0x02, 0xa0, + 0xe5, 0x01, 0x00, 0xe5, 0x1d, 0x07, 0xc6, 0x00, + 0xa6, 0x07, 0x06, 0x05, 0x96, 0xe0, 0x02, 0xe9, + 0x02, 0xeb, 0x0b, 0x40, 0x36, 0xe5, 0x16, 0x20, + 0xe6, 0x0e, 0x00, 0x07, 0xc6, 0x07, 0x26, 0x07, + 0x26, 0xe0, 0x41, 0xc5, 0x00, 0x25, 0x00, 0xe5, + 0x1e, 0xa6, 0x40, 0x06, 0x00, 0x26, 0x00, 0xc6, + 0x05, 0x06, 0xe0, 0x00, 0xe9, 0x02, 0xa0, 0xa5, + 0x00, 0x25, 0x00, 0xe5, 0x18, 0x87, 0x00, 0x26, + 0x00, 0x27, 0x06, 0x07, 0x06, 0x05, 0xc0, 0xe9, + 0x02, 0xa0, 0xe5, 0x21, 0x04, 0x25, 0x60, 0xe9, + 0x02, 0xe0, 0x80, 0x6e, 0xe5, 0x0b, 0x26, 0x27, + 0x36, 0xc0, 0x26, 0x05, 0x07, 0xe5, 0x05, 0x00, + 0xe5, 0x1a, 0x27, 0x86, 0x40, 0x27, 0x06, 0x07, + 0x06, 0xf6, 0x05, 0xe9, 0x02, 0x06, 0xe0, 0x4d, + 0x05, 0xe0, 0x07, 0xeb, 0x0d, 0xef, 0x00, 0x6d, + 0xef, 0x09, 0xe0, 0x05, 0x16, 0xe5, 0x83, 0x12, + 0xe0, 0x5e, 0xea, 0x67, 0x00, 0x96, 0xe0, 0x03, + 0xe5, 0x80, 0x3c, 0xe0, 0x89, 0xc4, 0xe5, 0x59, + 0x36, 0xe0, 0x05, 0xe5, 0x83, 0xa8, 0xfb, 0x08, + 0x06, 0xa5, 0xe6, 0x07, 0xe0, 0x02, 0xe5, 0x8f, + 0x13, 0x80, 0xe5, 0x81, 0xbf, 0xe0, 0x9a, 0x31, + 0xe5, 0x16, 0xe6, 0x04, 0x47, 0x46, 0xe9, 0x02, + 0xe0, 0x86, 0x3e, 0xe5, 0x81, 0xb1, 0xc0, 0xe5, + 0x17, 0x00, 0xe9, 0x02, 0x60, 0x36, 0xe5, 0x47, + 0x00, 0xe9, 0x02, 0xa0, 0xe5, 0x16, 0x20, 0x86, + 0x16, 0xe0, 0x02, 0xe5, 0x28, 0xc6, 0x96, 0x6f, + 0x64, 0x16, 0x0f, 0xe0, 0x02, 0xe9, 0x02, 0x00, + 0xcb, 0x00, 0xe5, 0x0d, 0x80, 0xe5, 0x0b, 0xe0, + 0x81, 0x28, 0x44, 0xe5, 0x20, 0x24, 0x56, 0xe9, + 0x02, 0xe0, 0x80, 0x3e, 0xe1, 0x18, 0xe2, 0x18, + 0xeb, 0x0f, 0x76, 0x80, 0xe1, 0x11, 0x20, 0xe2, + 0x11, 0xe0, 0x24, 0xe5, 0x43, 0x60, 0x06, 0x05, 0xe7, 0x2f, 0xc0, 0x66, 0xe4, 0x05, 0xe0, 0x38, - 0x24, 0x16, 0x04, 0x06, 0xe0, 0x03, 0x27, 0xe0, - 0x06, 0xe5, 0x97, 0x70, 0xe0, 0x00, 0xe5, 0x84, - 0x4e, 0xe0, 0x21, 0xe5, 0x02, 0xe0, 0xa2, 0x5f, - 0x64, 0x00, 0xc4, 0x00, 0x24, 0x00, 0xe5, 0x80, - 0x9b, 0xe0, 0x07, 0x05, 0xe0, 0x15, 0x45, 0x20, - 0x05, 0xe0, 0x06, 0x65, 0xe0, 0x00, 0xe5, 0x81, - 0x04, 0xe0, 0x88, 0x7c, 0xe5, 0x63, 0x80, 0xe5, - 0x05, 0x40, 0xe5, 0x01, 0xc0, 0xe5, 0x02, 0x20, - 0x0f, 0x26, 0x16, 0x7b, 0xe0, 0x8e, 0xd4, 0xef, - 0x80, 0x68, 0xe9, 0x02, 0xa0, 0xef, 0x81, 0x2c, - 0xe0, 0x44, 0xe6, 0x26, 0x20, 0xe6, 0x0f, 0xe0, - 0x01, 0xef, 0x6c, 0xe0, 0x34, 0xef, 0x80, 0x6e, - 0xe0, 0x02, 0xef, 0x1f, 0x20, 0xef, 0x34, 0x27, - 0x46, 0x4f, 0xa7, 0xfb, 0x00, 0xe6, 0x00, 0x2f, - 0xc6, 0xef, 0x16, 0x66, 0xef, 0x35, 0xe0, 0x0d, - 0xef, 0x3a, 0x46, 0x0f, 0xe0, 0x72, 0xeb, 0x0c, - 0xe0, 0x04, 0xeb, 0x0c, 0xe0, 0x04, 0xef, 0x4f, - 0xe0, 0x01, 0xeb, 0x11, 0xe0, 0x7f, 0xe1, 0x12, - 0xe2, 0x12, 0xe1, 0x12, 0xc2, 0x00, 0xe2, 0x0a, - 0xe1, 0x12, 0xe2, 0x12, 0x01, 0x00, 0x21, 0x20, - 0x01, 0x20, 0x21, 0x20, 0x61, 0x00, 0xe1, 0x00, - 0x62, 0x00, 0x02, 0x00, 0xc2, 0x00, 0xe2, 0x03, - 0xe1, 0x12, 0xe2, 0x12, 0x21, 0x00, 0x61, 0x20, - 0xe1, 0x00, 0x00, 0xc1, 0x00, 0xe2, 0x12, 0x21, - 0x00, 0x61, 0x00, 0x81, 0x00, 0x01, 0x40, 0xc1, - 0x00, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, - 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, - 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, - 0x12, 0xe2, 0x14, 0x20, 0xe1, 0x11, 0x0c, 0xe2, + 0x24, 0x16, 0x04, 0x06, 0xe0, 0x03, 0x27, 0x24, + 0x4a, 0xe0, 0x01, 0xe5, 0x9c, 0x4e, 0xe0, 0x21, + 0xe5, 0x18, 0xe0, 0x59, 0xe5, 0x6b, 0xe0, 0xa1, + 0x75, 0x64, 0x00, 0xc4, 0x00, 0x24, 0x00, 0xe5, + 0x80, 0x9b, 0xe0, 0x07, 0x05, 0xe0, 0x15, 0x45, + 0x20, 0x05, 0xe0, 0x06, 0x65, 0xe0, 0x00, 0xe5, + 0x81, 0x04, 0xe0, 0x88, 0x7c, 0xe5, 0x63, 0x80, + 0xe5, 0x05, 0x40, 0xe5, 0x01, 0xc0, 0xe5, 0x02, + 0x20, 0x0f, 0x26, 0x16, 0x7b, 0xe0, 0x8e, 0xd4, + 0xef, 0x80, 0x68, 0xe9, 0x02, 0x4f, 0x40, 0xef, + 0x81, 0x2c, 0xa0, 0xef, 0x0f, 0xe0, 0x07, 0xef, + 0x08, 0x0c, 0xe0, 0x07, 0xe6, 0x26, 0x20, 0xe6, + 0x0f, 0xe0, 0x01, 0xef, 0x6c, 0xe0, 0x34, 0xef, + 0x80, 0x6e, 0xe0, 0x02, 0xef, 0x1f, 0x20, 0xef, + 0x34, 0x27, 0x46, 0x4f, 0xa7, 0xfb, 0x00, 0xe6, + 0x00, 0x2f, 0xc6, 0xef, 0x16, 0x66, 0xef, 0x35, + 0xe0, 0x0d, 0xef, 0x3a, 0x46, 0x0f, 0xe0, 0x72, + 0xeb, 0x0c, 0xe0, 0x04, 0xeb, 0x0c, 0xe0, 0x04, + 0xef, 0x4f, 0xe0, 0x01, 0xeb, 0x11, 0xe0, 0x7f, + 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xc2, 0x00, + 0xe2, 0x0a, 0xe1, 0x12, 0xe2, 0x12, 0x01, 0x00, + 0x21, 0x20, 0x01, 0x20, 0x21, 0x20, 0x61, 0x00, + 0xe1, 0x00, 0x62, 0x00, 0x02, 0x00, 0xc2, 0x00, + 0xe2, 0x03, 0xe1, 0x12, 0xe2, 0x12, 0x21, 0x00, + 0x61, 0x20, 0xe1, 0x00, 0x00, 0xc1, 0x00, 0xe2, + 0x12, 0x21, 0x00, 0x61, 0x00, 0x81, 0x00, 0x01, + 0x40, 0xc1, 0x00, 0xe2, 0x12, 0xe1, 0x12, 0xe2, + 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, + 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, + 0x12, 0xe1, 0x12, 0xe2, 0x14, 0x20, 0xe1, 0x11, + 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, + 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, - 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, - 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0x3f, - 0x20, 0xe9, 0x2a, 0xef, 0x81, 0x78, 0xe6, 0x2f, - 0x6f, 0xe6, 0x2a, 0xef, 0x00, 0x06, 0xef, 0x06, - 0x06, 0x2f, 0x96, 0xe0, 0x07, 0x86, 0x00, 0xe6, - 0x07, 0xe0, 0x83, 0xc8, 0xe2, 0x02, 0x05, 0xe2, - 0x0c, 0xa0, 0xa2, 0xe0, 0x80, 0x4d, 0xc6, 0x00, - 0xe6, 0x09, 0x20, 0xc6, 0x00, 0x26, 0x00, 0x86, - 0x80, 0xe4, 0x36, 0xe0, 0x19, 0x06, 0xe0, 0x68, - 0xe5, 0x25, 0x40, 0xc6, 0xc4, 0x20, 0xe9, 0x02, - 0x60, 0x05, 0x0f, 0xe0, 0x80, 0xb8, 0xe5, 0x16, - 0x06, 0xe0, 0x09, 0xe5, 0x24, 0x66, 0xe9, 0x02, - 0x80, 0x0d, 0xe0, 0x81, 0x48, 0xe5, 0x13, 0x04, - 0x66, 0xe9, 0x02, 0xe0, 0x80, 0x4e, 0xe5, 0x16, - 0x26, 0x05, 0xe9, 0x02, 0x60, 0x16, 0xe0, 0x81, - 0x58, 0xc5, 0x00, 0x65, 0x00, 0x25, 0x00, 0xe5, - 0x07, 0x00, 0xe5, 0x80, 0x3d, 0x20, 0xeb, 0x01, - 0xc6, 0xe0, 0x21, 0xe1, 0x1a, 0xe2, 0x1a, 0xc6, - 0x04, 0x60, 0xe9, 0x02, 0x60, 0x36, 0xe0, 0x82, - 0x89, 0xeb, 0x33, 0x0f, 0x4b, 0x0d, 0x6b, 0xe0, - 0x44, 0xeb, 0x25, 0x0f, 0xeb, 0x07, 0xe0, 0x80, - 0x3a, 0x65, 0x00, 0xe5, 0x13, 0x00, 0x25, 0x00, - 0x05, 0x20, 0x05, 0x00, 0xe5, 0x02, 0x00, 0x65, - 0x00, 0x05, 0x00, 0x05, 0xa0, 0x05, 0x60, 0x05, - 0x00, 0x05, 0x00, 0x05, 0x00, 0x45, 0x00, 0x25, - 0x00, 0x05, 0x20, 0x05, 0x00, 0x05, 0x00, 0x05, - 0x00, 0x05, 0x00, 0x05, 0x00, 0x25, 0x00, 0x05, - 0x20, 0x65, 0x00, 0xc5, 0x00, 0x65, 0x00, 0x65, - 0x00, 0x05, 0x00, 0xe5, 0x02, 0x00, 0xe5, 0x09, - 0x80, 0x45, 0x00, 0x85, 0x00, 0xe5, 0x09, 0xe0, - 0x2c, 0x2c, 0xe0, 0x80, 0x86, 0xef, 0x24, 0x60, - 0xef, 0x5c, 0xe0, 0x04, 0xef, 0x07, 0x20, 0xef, - 0x07, 0x00, 0xef, 0x07, 0x00, 0xef, 0x1d, 0xe0, - 0x02, 0xeb, 0x05, 0xef, 0x80, 0x19, 0xe0, 0x30, - 0xef, 0x15, 0xe0, 0x05, 0xef, 0x24, 0x60, 0xef, - 0x01, 0xc0, 0x2f, 0xe0, 0x06, 0xaf, 0xe0, 0x80, - 0x12, 0xef, 0x80, 0x73, 0x8e, 0xef, 0x82, 0x50, - 0x60, 0xef, 0x09, 0x40, 0xef, 0x05, 0x40, 0xef, - 0x6f, 0x60, 0xef, 0x57, 0xa0, 0xef, 0x04, 0x60, - 0x0f, 0xe0, 0x07, 0xef, 0x04, 0x60, 0xef, 0x30, - 0xe0, 0x00, 0xef, 0x02, 0xa0, 0xef, 0x20, 0xe0, - 0x00, 0xef, 0x16, 0x20, 0xef, 0x04, 0x60, 0x2f, - 0xe0, 0x36, 0xef, 0x80, 0xcc, 0xe0, 0x04, 0xef, - 0x06, 0x20, 0xef, 0x05, 0x40, 0xef, 0x02, 0x80, - 0xef, 0x30, 0xc0, 0xef, 0x07, 0x20, 0xef, 0x03, - 0xa0, 0xef, 0x01, 0xc0, 0xef, 0x80, 0x0b, 0x00, - 0xef, 0x54, 0xe9, 0x02, 0xe0, 0x83, 0x7e, 0xe5, - 0xc0, 0x66, 0x58, 0xe0, 0x18, 0xe5, 0x8f, 0xb2, - 0xa0, 0xe5, 0x80, 0x56, 0x20, 0xe5, 0x95, 0xfa, - 0xe0, 0x06, 0xe5, 0x9c, 0xa9, 0xe0, 0x07, 0xe5, - 0x81, 0xe6, 0xe0, 0x89, 0x1a, 0xe5, 0x81, 0x96, - 0xe0, 0x85, 0x5a, 0xe5, 0x92, 0xc3, 0x80, 0xe5, - 0x8f, 0xd8, 0xe0, 0xca, 0x9b, 0xc9, 0x1b, 0xe0, - 0x16, 0xfb, 0x58, 0xe0, 0x78, 0xe6, 0x80, 0x68, - 0xe0, 0xc0, 0xbd, 0x88, 0xfd, 0xc0, 0xbf, 0x76, - 0x20, 0xfd, 0xc0, 0xbf, 0x76, 0x20, + 0xa2, 0x3f, 0x20, 0xe9, 0x2a, 0xef, 0x81, 0x78, + 0xe6, 0x2f, 0x6f, 0xe6, 0x2a, 0xef, 0x00, 0x06, + 0xef, 0x06, 0x06, 0x2f, 0x96, 0xe0, 0x07, 0x86, + 0x00, 0xe6, 0x07, 0xe0, 0x83, 0xc8, 0xe2, 0x02, + 0x05, 0xe2, 0x0c, 0xa0, 0xa2, 0xe0, 0x80, 0x4d, + 0xc6, 0x00, 0xe6, 0x09, 0x20, 0xc6, 0x00, 0x26, + 0x00, 0x86, 0x80, 0xe4, 0x36, 0xe0, 0x19, 0x06, + 0xe0, 0x68, 0xe5, 0x25, 0x40, 0xc6, 0xc4, 0x20, + 0xe9, 0x02, 0x60, 0x05, 0x0f, 0xe0, 0x80, 0xb8, + 0xe5, 0x16, 0x06, 0xe0, 0x09, 0xe5, 0x24, 0x66, + 0xe9, 0x02, 0x80, 0x0d, 0xe0, 0x81, 0x48, 0xe5, + 0x13, 0x04, 0x66, 0xe9, 0x02, 0xe0, 0x80, 0x4e, + 0xe5, 0x16, 0x26, 0x05, 0xe9, 0x02, 0x60, 0x16, + 0xe0, 0x80, 0x38, 0xe5, 0x17, 0x00, 0x45, 0x06, + 0x25, 0x06, 0xc5, 0x26, 0x85, 0x06, 0xe0, 0x00, + 0x05, 0x04, 0xe0, 0x80, 0x58, 0xc5, 0x00, 0x65, + 0x00, 0x25, 0x00, 0xe5, 0x07, 0x00, 0xe5, 0x80, + 0x3d, 0x20, 0xeb, 0x01, 0xc6, 0xe0, 0x21, 0xe1, + 0x1a, 0xe2, 0x1a, 0xc6, 0x04, 0x60, 0xe9, 0x02, + 0x60, 0x36, 0xe0, 0x82, 0x89, 0xeb, 0x33, 0x0f, + 0x4b, 0x0d, 0x6b, 0xe0, 0x44, 0xeb, 0x25, 0x0f, + 0xeb, 0x07, 0xe0, 0x80, 0x3a, 0x65, 0x00, 0xe5, + 0x13, 0x00, 0x25, 0x00, 0x05, 0x20, 0x05, 0x00, + 0xe5, 0x02, 0x00, 0x65, 0x00, 0x05, 0x00, 0x05, + 0xa0, 0x05, 0x60, 0x05, 0x00, 0x05, 0x00, 0x05, + 0x00, 0x45, 0x00, 0x25, 0x00, 0x05, 0x20, 0x05, + 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, + 0x00, 0x25, 0x00, 0x05, 0x20, 0x65, 0x00, 0xc5, + 0x00, 0x65, 0x00, 0x65, 0x00, 0x05, 0x00, 0xe5, + 0x02, 0x00, 0xe5, 0x09, 0x80, 0x45, 0x00, 0x85, + 0x00, 0xe5, 0x09, 0xe0, 0x2c, 0x2c, 0xe0, 0x80, + 0x86, 0xef, 0x24, 0x60, 0xef, 0x5c, 0xe0, 0x04, + 0xef, 0x07, 0x20, 0xef, 0x07, 0x00, 0xef, 0x07, + 0x00, 0xef, 0x1d, 0xe0, 0x02, 0xeb, 0x05, 0xef, + 0x80, 0x19, 0xe0, 0x30, 0xef, 0x15, 0xe0, 0x05, + 0xef, 0x24, 0x60, 0xef, 0x01, 0xc0, 0x2f, 0xe0, + 0x06, 0xaf, 0xe0, 0x80, 0x12, 0xef, 0x80, 0x73, + 0x8e, 0xef, 0x82, 0x51, 0x40, 0xef, 0x09, 0x40, + 0xef, 0x05, 0x40, 0xef, 0x80, 0x52, 0xa0, 0xef, + 0x04, 0x60, 0x0f, 0xe0, 0x07, 0xef, 0x04, 0x60, + 0xef, 0x30, 0xe0, 0x00, 0xef, 0x02, 0xa0, 0xef, + 0x20, 0xe0, 0x00, 0xef, 0x16, 0x20, 0xef, 0x04, + 0x60, 0x2f, 0xe0, 0x06, 0xec, 0x01, 0xe0, 0x1f, + 0xef, 0x80, 0xd0, 0xe0, 0x00, 0xef, 0x06, 0x20, + 0xef, 0x05, 0x40, 0xef, 0x03, 0x40, 0xef, 0x31, + 0x00, 0x0f, 0x60, 0xef, 0x08, 0x20, 0xef, 0x04, + 0x60, 0xef, 0x02, 0xc0, 0xef, 0x80, 0x0b, 0x00, + 0xef, 0x54, 0xe9, 0x02, 0x0f, 0xe0, 0x83, 0x7d, + 0xe5, 0xc0, 0x66, 0x58, 0xe0, 0x18, 0xe5, 0x90, + 0x96, 0x20, 0xe5, 0x96, 0x06, 0x20, 0xe5, 0x9c, + 0xa9, 0xe0, 0x07, 0xe5, 0x81, 0xe6, 0xe0, 0x89, + 0x1a, 0xe5, 0x81, 0x96, 0xe0, 0x85, 0x5a, 0xe5, + 0x92, 0xc3, 0x80, 0xe5, 0xa0, 0xa2, 0xe0, 0xca, + 0x8a, 0xff, 0x1b, 0xe0, 0x16, 0xfb, 0x58, 0xe0, + 0x78, 0xe6, 0x80, 0x68, 0xe0, 0xc0, 0xbd, 0x88, + 0xfd, 0xc0, 0xbf, 0x76, 0x20, 0xfd, 0xc0, 0xbf, + 0x76, 0x20, }; typedef enum { @@ -2904,6 +2922,7 @@ typedef enum { UNICODE_SCRIPT_Bassa_Vah, UNICODE_SCRIPT_Batak, UNICODE_SCRIPT_Bengali, + UNICODE_SCRIPT_Beria_Erfe, UNICODE_SCRIPT_Bhaiksuki, UNICODE_SCRIPT_Bopomofo, UNICODE_SCRIPT_Brahmi, @@ -2957,6 +2976,7 @@ typedef enum { UNICODE_SCRIPT_Kaithi, UNICODE_SCRIPT_Kannada, UNICODE_SCRIPT_Katakana, + UNICODE_SCRIPT_Katakana_Or_Hiragana, UNICODE_SCRIPT_Kawi, UNICODE_SCRIPT_Kayah_Li, UNICODE_SCRIPT_Kharoshthi, @@ -3028,6 +3048,7 @@ typedef enum { UNICODE_SCRIPT_Sharada, UNICODE_SCRIPT_Shavian, UNICODE_SCRIPT_Siddham, + UNICODE_SCRIPT_Sidetic, UNICODE_SCRIPT_SignWriting, UNICODE_SCRIPT_Sinhala, UNICODE_SCRIPT_Sogdian, @@ -3042,6 +3063,7 @@ typedef enum { UNICODE_SCRIPT_Tai_Le, UNICODE_SCRIPT_Tai_Tham, UNICODE_SCRIPT_Tai_Viet, + UNICODE_SCRIPT_Tai_Yo, UNICODE_SCRIPT_Takri, UNICODE_SCRIPT_Tamil, UNICODE_SCRIPT_Tangut, @@ -3053,6 +3075,7 @@ typedef enum { UNICODE_SCRIPT_Tirhuta, UNICODE_SCRIPT_Tangsa, UNICODE_SCRIPT_Todhri, + UNICODE_SCRIPT_Tolong_Siki, UNICODE_SCRIPT_Toto, UNICODE_SCRIPT_Tulu_Tigalari, UNICODE_SCRIPT_Ugaritic, @@ -3078,6 +3101,7 @@ static const char unicode_script_name_table[] = "Bassa_Vah,Bass" "\0" "Batak,Batk" "\0" "Bengali,Beng" "\0" + "Beria_Erfe,Berf" "\0" "Bhaiksuki,Bhks" "\0" "Bopomofo,Bopo" "\0" "Brahmi,Brah" "\0" @@ -3131,6 +3155,7 @@ static const char unicode_script_name_table[] = "Kaithi,Kthi" "\0" "Kannada,Knda" "\0" "Katakana,Kana" "\0" + "Katakana_Or_Hiragana,Hrkt" "\0" "Kawi,Kawi" "\0" "Kayah_Li,Kali" "\0" "Kharoshthi,Khar" "\0" @@ -3202,6 +3227,7 @@ static const char unicode_script_name_table[] = "Sharada,Shrd" "\0" "Shavian,Shaw" "\0" "Siddham,Sidd" "\0" + "Sidetic,Sidt" "\0" "SignWriting,Sgnw" "\0" "Sinhala,Sinh" "\0" "Sogdian,Sogd" "\0" @@ -3216,6 +3242,7 @@ static const char unicode_script_name_table[] = "Tai_Le,Tale" "\0" "Tai_Tham,Lana" "\0" "Tai_Viet,Tavt" "\0" + "Tai_Yo,Tayo" "\0" "Takri,Takr" "\0" "Tamil,Taml" "\0" "Tangut,Tang" "\0" @@ -3227,6 +3254,7 @@ static const char unicode_script_name_table[] = "Tirhuta,Tirh" "\0" "Tangsa,Tnsa" "\0" "Todhri,Todr" "\0" + "Tolong_Siki,Tols" "\0" "Toto,Toto" "\0" "Tulu_Tigalari,Tutg" "\0" "Ugaritic,Ugar" "\0" @@ -3239,518 +3267,523 @@ static const char unicode_script_name_table[] = "Zanabazar_Square,Zanb" "\0" ; -static const uint8_t unicode_script_table[2803] = { - 0xc0, 0x19, 0x99, 0x4a, 0x85, 0x19, 0x99, 0x4a, - 0xae, 0x19, 0x80, 0x4a, 0x8e, 0x19, 0x80, 0x4a, - 0x84, 0x19, 0x96, 0x4a, 0x80, 0x19, 0x9e, 0x4a, - 0x80, 0x19, 0xe1, 0x60, 0x4a, 0xa6, 0x19, 0x84, - 0x4a, 0x84, 0x19, 0x81, 0x0d, 0x93, 0x19, 0xe0, - 0x0f, 0x3a, 0x83, 0x2d, 0x80, 0x19, 0x82, 0x2d, - 0x01, 0x83, 0x2d, 0x80, 0x19, 0x80, 0x2d, 0x03, - 0x80, 0x2d, 0x80, 0x19, 0x80, 0x2d, 0x80, 0x19, - 0x82, 0x2d, 0x00, 0x80, 0x2d, 0x00, 0x93, 0x2d, - 0x00, 0xbe, 0x2d, 0x8d, 0x1a, 0x8f, 0x2d, 0xe0, - 0x24, 0x1d, 0x81, 0x3a, 0xe0, 0x48, 0x1d, 0x00, +static const uint8_t unicode_script_table[2818] = { + 0xc0, 0x1a, 0x99, 0x4c, 0x85, 0x1a, 0x99, 0x4c, + 0xae, 0x1a, 0x80, 0x4c, 0x8e, 0x1a, 0x80, 0x4c, + 0x84, 0x1a, 0x96, 0x4c, 0x80, 0x1a, 0x9e, 0x4c, + 0x80, 0x1a, 0xe1, 0x60, 0x4c, 0xa6, 0x1a, 0x84, + 0x4c, 0x84, 0x1a, 0x81, 0x0e, 0x93, 0x1a, 0xe0, + 0x0f, 0x3b, 0x83, 0x2e, 0x80, 0x1a, 0x82, 0x2e, + 0x01, 0x83, 0x2e, 0x80, 0x1a, 0x80, 0x2e, 0x03, + 0x80, 0x2e, 0x80, 0x1a, 0x80, 0x2e, 0x80, 0x1a, + 0x82, 0x2e, 0x00, 0x80, 0x2e, 0x00, 0x93, 0x2e, + 0x00, 0xbe, 0x2e, 0x8d, 0x1b, 0x8f, 0x2e, 0xe0, + 0x24, 0x1e, 0x81, 0x3b, 0xe0, 0x48, 0x1e, 0x00, 0xa5, 0x05, 0x01, 0xb1, 0x05, 0x01, 0x82, 0x05, - 0x00, 0xb6, 0x37, 0x07, 0x9a, 0x37, 0x03, 0x85, - 0x37, 0x0a, 0x84, 0x04, 0x80, 0x19, 0x85, 0x04, - 0x80, 0x19, 0x8d, 0x04, 0x80, 0x19, 0x82, 0x04, - 0x80, 0x19, 0x9f, 0x04, 0x80, 0x19, 0x89, 0x04, - 0x8a, 0x3a, 0x99, 0x04, 0x80, 0x3a, 0xe0, 0x0b, - 0x04, 0x80, 0x19, 0xa1, 0x04, 0x8d, 0x90, 0x00, - 0xbb, 0x90, 0x01, 0x82, 0x90, 0xaf, 0x04, 0xb1, - 0x9a, 0x0d, 0xba, 0x69, 0x01, 0x82, 0x69, 0xad, - 0x83, 0x01, 0x8e, 0x83, 0x00, 0x9b, 0x55, 0x01, - 0x80, 0x55, 0x00, 0x8a, 0x90, 0x04, 0x9e, 0x04, - 0x00, 0x81, 0x04, 0x04, 0xca, 0x04, 0x80, 0x19, - 0x9c, 0x04, 0xd0, 0x20, 0x83, 0x3a, 0x8e, 0x20, - 0x81, 0x19, 0x99, 0x20, 0x83, 0x0b, 0x00, 0x87, - 0x0b, 0x01, 0x81, 0x0b, 0x01, 0x95, 0x0b, 0x00, - 0x86, 0x0b, 0x00, 0x80, 0x0b, 0x02, 0x83, 0x0b, - 0x01, 0x88, 0x0b, 0x01, 0x81, 0x0b, 0x01, 0x83, - 0x0b, 0x07, 0x80, 0x0b, 0x03, 0x81, 0x0b, 0x00, - 0x84, 0x0b, 0x01, 0x98, 0x0b, 0x01, 0x82, 0x30, - 0x00, 0x85, 0x30, 0x03, 0x81, 0x30, 0x01, 0x95, - 0x30, 0x00, 0x86, 0x30, 0x00, 0x81, 0x30, 0x00, - 0x81, 0x30, 0x00, 0x81, 0x30, 0x01, 0x80, 0x30, - 0x00, 0x84, 0x30, 0x03, 0x81, 0x30, 0x01, 0x82, - 0x30, 0x02, 0x80, 0x30, 0x06, 0x83, 0x30, 0x00, - 0x80, 0x30, 0x06, 0x90, 0x30, 0x09, 0x82, 0x2e, - 0x00, 0x88, 0x2e, 0x00, 0x82, 0x2e, 0x00, 0x95, - 0x2e, 0x00, 0x86, 0x2e, 0x00, 0x81, 0x2e, 0x00, - 0x84, 0x2e, 0x01, 0x89, 0x2e, 0x00, 0x82, 0x2e, - 0x00, 0x82, 0x2e, 0x01, 0x80, 0x2e, 0x0e, 0x83, - 0x2e, 0x01, 0x8b, 0x2e, 0x06, 0x86, 0x2e, 0x00, - 0x82, 0x78, 0x00, 0x87, 0x78, 0x01, 0x81, 0x78, - 0x01, 0x95, 0x78, 0x00, 0x86, 0x78, 0x00, 0x81, - 0x78, 0x00, 0x84, 0x78, 0x01, 0x88, 0x78, 0x01, - 0x81, 0x78, 0x01, 0x82, 0x78, 0x06, 0x82, 0x78, - 0x03, 0x81, 0x78, 0x00, 0x84, 0x78, 0x01, 0x91, - 0x78, 0x09, 0x81, 0x97, 0x00, 0x85, 0x97, 0x02, - 0x82, 0x97, 0x00, 0x83, 0x97, 0x02, 0x81, 0x97, - 0x00, 0x80, 0x97, 0x00, 0x81, 0x97, 0x02, 0x81, - 0x97, 0x02, 0x82, 0x97, 0x02, 0x8b, 0x97, 0x03, - 0x84, 0x97, 0x02, 0x82, 0x97, 0x00, 0x83, 0x97, - 0x01, 0x80, 0x97, 0x05, 0x80, 0x97, 0x0d, 0x94, - 0x97, 0x04, 0x8c, 0x99, 0x00, 0x82, 0x99, 0x00, - 0x96, 0x99, 0x00, 0x8f, 0x99, 0x01, 0x88, 0x99, - 0x00, 0x82, 0x99, 0x00, 0x83, 0x99, 0x06, 0x81, - 0x99, 0x00, 0x82, 0x99, 0x01, 0x80, 0x99, 0x01, - 0x83, 0x99, 0x01, 0x89, 0x99, 0x06, 0x88, 0x99, - 0x8c, 0x3f, 0x00, 0x82, 0x3f, 0x00, 0x96, 0x3f, - 0x00, 0x89, 0x3f, 0x00, 0x84, 0x3f, 0x01, 0x88, - 0x3f, 0x00, 0x82, 0x3f, 0x00, 0x83, 0x3f, 0x06, - 0x81, 0x3f, 0x05, 0x81, 0x3f, 0x00, 0x83, 0x3f, - 0x01, 0x89, 0x3f, 0x00, 0x82, 0x3f, 0x0b, 0x8c, - 0x54, 0x00, 0x82, 0x54, 0x00, 0xb2, 0x54, 0x00, - 0x82, 0x54, 0x00, 0x85, 0x54, 0x03, 0x8f, 0x54, - 0x01, 0x99, 0x54, 0x00, 0x82, 0x89, 0x00, 0x91, - 0x89, 0x02, 0x97, 0x89, 0x00, 0x88, 0x89, 0x00, - 0x80, 0x89, 0x01, 0x86, 0x89, 0x02, 0x80, 0x89, - 0x03, 0x85, 0x89, 0x00, 0x80, 0x89, 0x00, 0x87, - 0x89, 0x05, 0x89, 0x89, 0x01, 0x82, 0x89, 0x0b, - 0xb9, 0x9b, 0x03, 0x80, 0x19, 0x9b, 0x9b, 0x24, - 0x81, 0x49, 0x00, 0x80, 0x49, 0x00, 0x84, 0x49, - 0x00, 0x97, 0x49, 0x00, 0x80, 0x49, 0x00, 0x96, - 0x49, 0x01, 0x84, 0x49, 0x00, 0x80, 0x49, 0x00, - 0x86, 0x49, 0x00, 0x89, 0x49, 0x01, 0x83, 0x49, - 0x1f, 0xc7, 0x9c, 0x00, 0xa3, 0x9c, 0x03, 0xa6, - 0x9c, 0x00, 0xa3, 0x9c, 0x00, 0x8e, 0x9c, 0x00, - 0x86, 0x9c, 0x83, 0x19, 0x81, 0x9c, 0x24, 0xe0, - 0x3f, 0x63, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04, - 0x80, 0x28, 0x01, 0xaa, 0x28, 0x80, 0x19, 0x83, - 0x28, 0xe0, 0x9f, 0x33, 0xc8, 0x27, 0x00, 0x83, - 0x27, 0x01, 0x86, 0x27, 0x00, 0x80, 0x27, 0x00, - 0x83, 0x27, 0x01, 0xa8, 0x27, 0x00, 0x83, 0x27, - 0x01, 0xa0, 0x27, 0x00, 0x83, 0x27, 0x01, 0x86, - 0x27, 0x00, 0x80, 0x27, 0x00, 0x83, 0x27, 0x01, - 0x8e, 0x27, 0x00, 0xb8, 0x27, 0x00, 0x83, 0x27, - 0x01, 0xc2, 0x27, 0x01, 0x9f, 0x27, 0x02, 0x99, - 0x27, 0x05, 0xd5, 0x17, 0x01, 0x85, 0x17, 0x01, - 0xe2, 0x1f, 0x12, 0x9c, 0x6c, 0x02, 0xca, 0x82, - 0x82, 0x19, 0x8a, 0x82, 0x06, 0x95, 0x91, 0x08, - 0x80, 0x91, 0x94, 0x35, 0x81, 0x19, 0x08, 0x93, - 0x11, 0x0b, 0x8c, 0x92, 0x00, 0x82, 0x92, 0x00, - 0x81, 0x92, 0x0b, 0xdd, 0x44, 0x01, 0x89, 0x44, - 0x05, 0x89, 0x44, 0x05, 0x81, 0x60, 0x81, 0x19, - 0x80, 0x60, 0x80, 0x19, 0x93, 0x60, 0x05, 0xd8, - 0x60, 0x06, 0xaa, 0x60, 0x04, 0xc5, 0x12, 0x09, - 0x9e, 0x4c, 0x00, 0x8b, 0x4c, 0x03, 0x8b, 0x4c, - 0x03, 0x80, 0x4c, 0x02, 0x8b, 0x4c, 0x9d, 0x93, - 0x01, 0x84, 0x93, 0x0a, 0xab, 0x67, 0x03, 0x99, - 0x67, 0x05, 0x8a, 0x67, 0x02, 0x81, 0x67, 0x9f, - 0x44, 0x9b, 0x10, 0x01, 0x81, 0x10, 0xbe, 0x94, - 0x00, 0x9c, 0x94, 0x01, 0x8a, 0x94, 0x05, 0x89, - 0x94, 0x05, 0x8d, 0x94, 0x01, 0x9e, 0x3a, 0x30, - 0xcc, 0x07, 0x00, 0xb1, 0x07, 0xbf, 0x8d, 0xb3, - 0x0a, 0x07, 0x83, 0x0a, 0xb7, 0x4b, 0x02, 0x8e, - 0x4b, 0x02, 0x82, 0x4b, 0xaf, 0x6d, 0x8a, 0x1d, - 0x04, 0xaa, 0x28, 0x01, 0x82, 0x28, 0x87, 0x8d, - 0x07, 0x82, 0x3a, 0x80, 0x19, 0x8c, 0x3a, 0x80, - 0x19, 0x86, 0x3a, 0x83, 0x19, 0x80, 0x3a, 0x85, - 0x19, 0x80, 0x3a, 0x82, 0x19, 0x81, 0x3a, 0x80, - 0x19, 0x04, 0xa5, 0x4a, 0x84, 0x2d, 0x80, 0x1d, - 0xb0, 0x4a, 0x84, 0x2d, 0x83, 0x4a, 0x84, 0x2d, - 0x8c, 0x4a, 0x80, 0x1d, 0xc5, 0x4a, 0x80, 0x2d, - 0xbf, 0x3a, 0xe0, 0x9f, 0x4a, 0x95, 0x2d, 0x01, - 0x85, 0x2d, 0x01, 0xa5, 0x2d, 0x01, 0x85, 0x2d, - 0x01, 0x87, 0x2d, 0x00, 0x80, 0x2d, 0x00, 0x80, - 0x2d, 0x00, 0x80, 0x2d, 0x00, 0x9e, 0x2d, 0x01, - 0xb4, 0x2d, 0x00, 0x8e, 0x2d, 0x00, 0x8d, 0x2d, - 0x01, 0x85, 0x2d, 0x00, 0x92, 0x2d, 0x01, 0x82, - 0x2d, 0x00, 0x88, 0x2d, 0x00, 0x8b, 0x19, 0x81, - 0x3a, 0xd6, 0x19, 0x00, 0x8a, 0x19, 0x80, 0x4a, - 0x01, 0x8a, 0x19, 0x80, 0x4a, 0x8e, 0x19, 0x00, - 0x8c, 0x4a, 0x02, 0xa0, 0x19, 0x0e, 0xa0, 0x3a, - 0x0e, 0xa5, 0x19, 0x80, 0x2d, 0x82, 0x19, 0x81, - 0x4a, 0x85, 0x19, 0x80, 0x4a, 0x9a, 0x19, 0x80, - 0x4a, 0x90, 0x19, 0xa8, 0x4a, 0x82, 0x19, 0x03, - 0xe2, 0x39, 0x19, 0x15, 0x8a, 0x19, 0x14, 0xe3, - 0x3f, 0x19, 0xe0, 0x9f, 0x0f, 0xe2, 0x13, 0x19, - 0x01, 0x9f, 0x19, 0x00, 0xe0, 0x08, 0x19, 0xdf, - 0x29, 0x9f, 0x4a, 0xe0, 0x13, 0x1a, 0x04, 0x86, - 0x1a, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04, 0x80, - 0x28, 0x01, 0xb7, 0x9d, 0x06, 0x81, 0x9d, 0x0d, - 0x80, 0x9d, 0x96, 0x27, 0x08, 0x86, 0x27, 0x00, - 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x27, - 0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, - 0x27, 0x00, 0x86, 0x27, 0x00, 0x9f, 0x1d, 0xdd, - 0x19, 0x21, 0x99, 0x32, 0x00, 0xd8, 0x32, 0x0b, - 0xe0, 0x75, 0x32, 0x19, 0x94, 0x19, 0x80, 0x32, - 0x80, 0x19, 0x80, 0x32, 0x98, 0x19, 0x88, 0x32, - 0x83, 0x3a, 0x81, 0x33, 0x87, 0x19, 0x83, 0x32, - 0x83, 0x19, 0x00, 0xd5, 0x38, 0x01, 0x81, 0x3a, - 0x81, 0x19, 0x82, 0x38, 0x80, 0x19, 0xd9, 0x40, - 0x81, 0x19, 0x82, 0x40, 0x04, 0xaa, 0x0d, 0x00, - 0xdd, 0x33, 0x00, 0x8f, 0x19, 0x9f, 0x0d, 0xa5, - 0x19, 0x08, 0x80, 0x19, 0x8f, 0x40, 0x9e, 0x33, - 0x00, 0xbf, 0x19, 0x9e, 0x33, 0xd0, 0x19, 0xae, - 0x40, 0x80, 0x19, 0xd7, 0x40, 0xe0, 0x47, 0x19, - 0xf0, 0x09, 0x5f, 0x32, 0xbf, 0x19, 0xf0, 0x41, - 0x9f, 0x32, 0xe4, 0x2c, 0xa9, 0x02, 0xb6, 0xa9, - 0x08, 0xaf, 0x4f, 0xe0, 0xcb, 0xa4, 0x13, 0xdf, - 0x1d, 0xd7, 0x08, 0x07, 0xa1, 0x19, 0xe0, 0x05, - 0x4a, 0x82, 0x19, 0xc2, 0x4a, 0x01, 0x81, 0x4a, - 0x00, 0x80, 0x4a, 0x00, 0x87, 0x4a, 0x14, 0x8d, - 0x4a, 0xac, 0x8f, 0x02, 0x89, 0x19, 0x05, 0xb7, - 0x7e, 0x07, 0xc5, 0x84, 0x07, 0x8b, 0x84, 0x05, - 0x9f, 0x20, 0xad, 0x42, 0x80, 0x19, 0x80, 0x42, - 0xa3, 0x81, 0x0a, 0x80, 0x81, 0x9c, 0x33, 0x02, - 0xcd, 0x3d, 0x00, 0x80, 0x19, 0x89, 0x3d, 0x03, - 0x81, 0x3d, 0x9e, 0x63, 0x00, 0xb6, 0x16, 0x08, - 0x8d, 0x16, 0x01, 0x89, 0x16, 0x01, 0x83, 0x16, - 0x9f, 0x63, 0xc2, 0x95, 0x17, 0x84, 0x95, 0x96, - 0x5a, 0x09, 0x85, 0x27, 0x01, 0x85, 0x27, 0x01, - 0x85, 0x27, 0x08, 0x86, 0x27, 0x00, 0x86, 0x27, - 0x00, 0xaa, 0x4a, 0x80, 0x19, 0x88, 0x4a, 0x80, - 0x2d, 0x83, 0x4a, 0x81, 0x19, 0x03, 0xcf, 0x17, - 0xad, 0x5a, 0x01, 0x89, 0x5a, 0x05, 0xf0, 0x1b, - 0x43, 0x33, 0x0b, 0x96, 0x33, 0x03, 0xb0, 0x33, - 0x70, 0x10, 0xa3, 0xe1, 0x0d, 0x32, 0x01, 0xe0, - 0x09, 0x32, 0x25, 0x86, 0x4a, 0x0b, 0x84, 0x05, - 0x04, 0x99, 0x37, 0x00, 0x84, 0x37, 0x00, 0x80, - 0x37, 0x00, 0x81, 0x37, 0x00, 0x81, 0x37, 0x00, - 0x89, 0x37, 0xe0, 0x12, 0x04, 0x0f, 0xe1, 0x0a, - 0x04, 0x81, 0x19, 0xcf, 0x04, 0x01, 0xb5, 0x04, - 0x06, 0x80, 0x04, 0x1f, 0x8f, 0x04, 0x8f, 0x3a, - 0x89, 0x19, 0x05, 0x8d, 0x3a, 0x81, 0x1d, 0xa2, - 0x19, 0x00, 0x92, 0x19, 0x00, 0x83, 0x19, 0x03, - 0x84, 0x04, 0x00, 0xe0, 0x26, 0x04, 0x01, 0x80, - 0x19, 0x00, 0x9f, 0x19, 0x99, 0x4a, 0x85, 0x19, - 0x99, 0x4a, 0x8a, 0x19, 0x89, 0x40, 0x80, 0x19, - 0xac, 0x40, 0x81, 0x19, 0x9e, 0x33, 0x02, 0x85, - 0x33, 0x01, 0x85, 0x33, 0x01, 0x85, 0x33, 0x01, - 0x82, 0x33, 0x02, 0x86, 0x19, 0x00, 0x86, 0x19, - 0x09, 0x84, 0x19, 0x01, 0x8b, 0x4e, 0x00, 0x99, - 0x4e, 0x00, 0x92, 0x4e, 0x00, 0x81, 0x4e, 0x00, - 0x8e, 0x4e, 0x01, 0x8d, 0x4e, 0x21, 0xe0, 0x1a, - 0x4e, 0x04, 0x82, 0x19, 0x03, 0xac, 0x19, 0x02, - 0x88, 0x19, 0xce, 0x2d, 0x00, 0x8c, 0x19, 0x02, - 0x80, 0x2d, 0x2e, 0xac, 0x19, 0x80, 0x3a, 0x60, - 0x21, 0x9c, 0x50, 0x02, 0xb0, 0x13, 0x0e, 0x80, - 0x3a, 0x9a, 0x19, 0x03, 0xa3, 0x70, 0x08, 0x82, - 0x70, 0x9a, 0x2a, 0x04, 0xaa, 0x72, 0x04, 0x9d, - 0xa3, 0x00, 0x80, 0xa3, 0xa3, 0x73, 0x03, 0x8d, - 0x73, 0x29, 0xcf, 0x1f, 0xaf, 0x86, 0x9d, 0x7a, - 0x01, 0x89, 0x7a, 0x05, 0xa3, 0x79, 0x03, 0xa3, - 0x79, 0x03, 0xa7, 0x25, 0x07, 0xb3, 0x14, 0x0a, - 0x80, 0x14, 0x8a, 0xa5, 0x00, 0x8e, 0xa5, 0x00, - 0x86, 0xa5, 0x00, 0x81, 0xa5, 0x00, 0x8a, 0xa5, - 0x00, 0x8e, 0xa5, 0x00, 0x86, 0xa5, 0x00, 0x81, - 0xa5, 0x02, 0xb3, 0xa0, 0x0b, 0xe0, 0xd6, 0x4d, - 0x08, 0x95, 0x4d, 0x09, 0x87, 0x4d, 0x17, 0x85, - 0x4a, 0x00, 0xa9, 0x4a, 0x00, 0x88, 0x4a, 0x44, - 0x85, 0x1c, 0x01, 0x80, 0x1c, 0x00, 0xab, 0x1c, - 0x00, 0x81, 0x1c, 0x02, 0x80, 0x1c, 0x01, 0x80, - 0x1c, 0x95, 0x39, 0x00, 0x88, 0x39, 0x9f, 0x7c, - 0x9e, 0x64, 0x07, 0x88, 0x64, 0x2f, 0x92, 0x36, - 0x00, 0x81, 0x36, 0x04, 0x84, 0x36, 0x9b, 0x7f, - 0x02, 0x80, 0x7f, 0x99, 0x51, 0x04, 0x80, 0x51, - 0x3f, 0x9f, 0x5d, 0x97, 0x5c, 0x03, 0x93, 0x5c, - 0x01, 0xad, 0x5c, 0x83, 0x43, 0x00, 0x81, 0x43, - 0x04, 0x87, 0x43, 0x00, 0x82, 0x43, 0x00, 0x9c, - 0x43, 0x01, 0x82, 0x43, 0x03, 0x89, 0x43, 0x06, - 0x88, 0x43, 0x06, 0x9f, 0x75, 0x9f, 0x71, 0x1f, - 0xa6, 0x56, 0x03, 0x8b, 0x56, 0x08, 0xb5, 0x06, - 0x02, 0x86, 0x06, 0x95, 0x3c, 0x01, 0x87, 0x3c, - 0x92, 0x3b, 0x04, 0x87, 0x3b, 0x91, 0x80, 0x06, - 0x83, 0x80, 0x0b, 0x86, 0x80, 0x4f, 0xc8, 0x76, - 0x36, 0xb2, 0x6f, 0x0c, 0xb2, 0x6f, 0x06, 0x85, - 0x6f, 0xa7, 0x34, 0x07, 0x89, 0x34, 0x05, 0xa5, - 0x2b, 0x02, 0x9c, 0x2b, 0x07, 0x81, 0x2b, 0x60, - 0x6f, 0x9e, 0x04, 0x00, 0xa9, 0xa8, 0x00, 0x82, - 0xa8, 0x01, 0x81, 0xa8, 0x0f, 0x82, 0x04, 0x36, - 0x83, 0x04, 0xa7, 0x74, 0x07, 0xa9, 0x8a, 0x15, - 0x99, 0x77, 0x25, 0x9b, 0x18, 0x13, 0x96, 0x26, - 0x08, 0xcd, 0x0e, 0x03, 0xa3, 0x0e, 0x08, 0x80, - 0x0e, 0xc2, 0x3e, 0x09, 0x80, 0x3e, 0x01, 0x98, - 0x8b, 0x06, 0x89, 0x8b, 0x05, 0xb4, 0x15, 0x00, - 0x91, 0x15, 0x07, 0xa6, 0x53, 0x08, 0xdf, 0x85, - 0x00, 0x93, 0x89, 0x0a, 0x91, 0x45, 0x00, 0xae, - 0x45, 0x3d, 0x86, 0x62, 0x00, 0x80, 0x62, 0x00, - 0x83, 0x62, 0x00, 0x8e, 0x62, 0x00, 0x8a, 0x62, - 0x05, 0xba, 0x47, 0x04, 0x89, 0x47, 0x05, 0x83, - 0x2c, 0x00, 0x87, 0x2c, 0x01, 0x81, 0x2c, 0x01, - 0x95, 0x2c, 0x00, 0x86, 0x2c, 0x00, 0x81, 0x2c, - 0x00, 0x84, 0x2c, 0x00, 0x80, 0x3a, 0x88, 0x2c, - 0x01, 0x81, 0x2c, 0x01, 0x82, 0x2c, 0x01, 0x80, - 0x2c, 0x05, 0x80, 0x2c, 0x04, 0x86, 0x2c, 0x01, - 0x86, 0x2c, 0x02, 0x84, 0x2c, 0x0a, 0x89, 0xa2, - 0x00, 0x80, 0xa2, 0x01, 0x80, 0xa2, 0x00, 0xa5, - 0xa2, 0x00, 0x89, 0xa2, 0x00, 0x80, 0xa2, 0x01, - 0x80, 0xa2, 0x00, 0x83, 0xa2, 0x00, 0x89, 0xa2, - 0x00, 0x81, 0xa2, 0x07, 0x81, 0xa2, 0x1c, 0xdb, - 0x68, 0x00, 0x84, 0x68, 0x1d, 0xc7, 0x9e, 0x07, - 0x89, 0x9e, 0x60, 0x45, 0xb5, 0x87, 0x01, 0xa5, - 0x87, 0x21, 0xc4, 0x5f, 0x0a, 0x89, 0x5f, 0x05, - 0x8c, 0x60, 0x12, 0xb9, 0x96, 0x05, 0x89, 0x96, - 0x05, 0x93, 0x63, 0x1b, 0x9a, 0x02, 0x01, 0x8e, - 0x02, 0x03, 0x96, 0x02, 0x60, 0x58, 0xbb, 0x22, - 0x60, 0x03, 0xd2, 0xa7, 0x0b, 0x80, 0xa7, 0x86, - 0x21, 0x01, 0x80, 0x21, 0x01, 0x87, 0x21, 0x00, - 0x81, 0x21, 0x00, 0x9d, 0x21, 0x00, 0x81, 0x21, - 0x01, 0x8b, 0x21, 0x08, 0x89, 0x21, 0x45, 0x87, - 0x66, 0x01, 0xad, 0x66, 0x01, 0x8a, 0x66, 0x1a, - 0xc7, 0xaa, 0x07, 0xd2, 0x8c, 0x0c, 0x8f, 0x12, - 0xb8, 0x7d, 0x06, 0x89, 0x20, 0x60, 0x55, 0xa1, - 0x8e, 0x0d, 0x89, 0x8e, 0x05, 0x88, 0x0c, 0x00, - 0xac, 0x0c, 0x00, 0x8d, 0x0c, 0x09, 0x9c, 0x0c, - 0x02, 0x9f, 0x57, 0x01, 0x95, 0x57, 0x00, 0x8d, - 0x57, 0x48, 0x86, 0x58, 0x00, 0x81, 0x58, 0x00, - 0xab, 0x58, 0x02, 0x80, 0x58, 0x00, 0x81, 0x58, - 0x00, 0x88, 0x58, 0x07, 0x89, 0x58, 0x05, 0x85, - 0x2f, 0x00, 0x81, 0x2f, 0x00, 0xa4, 0x2f, 0x00, - 0x81, 0x2f, 0x00, 0x85, 0x2f, 0x06, 0x89, 0x2f, - 0x60, 0xd5, 0x98, 0x52, 0x06, 0x90, 0x41, 0x00, - 0xa8, 0x41, 0x02, 0x9c, 0x41, 0x54, 0x80, 0x4f, - 0x0e, 0xb1, 0x97, 0x0c, 0x80, 0x97, 0xe3, 0x39, - 0x1b, 0x60, 0x05, 0xe0, 0x0e, 0x1b, 0x00, 0x84, - 0x1b, 0x0a, 0xe0, 0x63, 0x1b, 0x69, 0xeb, 0xe0, - 0x02, 0x1e, 0x0c, 0xe3, 0xf5, 0x24, 0x09, 0xef, - 0x3a, 0x24, 0x04, 0xe1, 0xe6, 0x03, 0x70, 0x0a, - 0x58, 0xb9, 0x31, 0x66, 0x65, 0xe1, 0xd8, 0x08, - 0x06, 0x9e, 0x61, 0x00, 0x89, 0x61, 0x03, 0x81, - 0x61, 0xce, 0x9f, 0x00, 0x89, 0x9f, 0x05, 0x9d, - 0x09, 0x01, 0x85, 0x09, 0x09, 0xc5, 0x7b, 0x09, - 0x89, 0x7b, 0x00, 0x86, 0x7b, 0x00, 0x94, 0x7b, - 0x04, 0x92, 0x7b, 0x61, 0x4f, 0xb9, 0x48, 0x60, - 0x65, 0xda, 0x59, 0x60, 0x04, 0xca, 0x5e, 0x03, - 0xb8, 0x5e, 0x06, 0x90, 0x5e, 0x3f, 0x80, 0x98, - 0x80, 0x6a, 0x81, 0x32, 0x80, 0x46, 0x0a, 0x81, - 0x32, 0x0d, 0xf0, 0x07, 0x97, 0x98, 0x07, 0xe2, - 0x9f, 0x98, 0xe1, 0x75, 0x46, 0x28, 0x80, 0x46, - 0x88, 0x98, 0x70, 0x12, 0x86, 0x83, 0x40, 0x00, - 0x86, 0x40, 0x00, 0x81, 0x40, 0x00, 0x80, 0x40, - 0xe0, 0xbe, 0x38, 0x82, 0x40, 0x0e, 0x80, 0x38, - 0x1c, 0x82, 0x38, 0x01, 0x80, 0x40, 0x0d, 0x83, - 0x40, 0x07, 0xe1, 0x2b, 0x6a, 0x68, 0xa3, 0xe0, - 0x0a, 0x23, 0x04, 0x8c, 0x23, 0x02, 0x88, 0x23, - 0x06, 0x89, 0x23, 0x01, 0x83, 0x23, 0x83, 0x19, - 0x6e, 0xfb, 0xe0, 0x99, 0x19, 0x05, 0xe1, 0x53, - 0x19, 0x4b, 0xad, 0x3a, 0x01, 0x96, 0x3a, 0x08, - 0xe0, 0x13, 0x19, 0x3b, 0xe0, 0x95, 0x19, 0x09, - 0xa6, 0x19, 0x01, 0xbd, 0x19, 0x82, 0x3a, 0x90, - 0x19, 0x87, 0x3a, 0x81, 0x19, 0x86, 0x3a, 0x9d, - 0x19, 0x83, 0x3a, 0xbc, 0x19, 0x14, 0xc5, 0x2d, - 0x60, 0x19, 0x93, 0x19, 0x0b, 0x93, 0x19, 0x0b, - 0xd6, 0x19, 0x08, 0x98, 0x19, 0x60, 0x26, 0xd4, - 0x19, 0x00, 0xc6, 0x19, 0x00, 0x81, 0x19, 0x01, - 0x80, 0x19, 0x01, 0x81, 0x19, 0x01, 0x83, 0x19, - 0x00, 0x8b, 0x19, 0x00, 0x80, 0x19, 0x00, 0x86, - 0x19, 0x00, 0xc0, 0x19, 0x00, 0x83, 0x19, 0x01, - 0x87, 0x19, 0x00, 0x86, 0x19, 0x00, 0x9b, 0x19, - 0x00, 0x83, 0x19, 0x00, 0x84, 0x19, 0x00, 0x80, - 0x19, 0x02, 0x86, 0x19, 0x00, 0xe0, 0xf3, 0x19, - 0x01, 0xe0, 0xc3, 0x19, 0x01, 0xb1, 0x19, 0xe2, - 0x2b, 0x88, 0x0e, 0x84, 0x88, 0x00, 0x8e, 0x88, - 0x63, 0xef, 0x9e, 0x4a, 0x05, 0x85, 0x4a, 0x60, - 0x74, 0x86, 0x29, 0x00, 0x90, 0x29, 0x01, 0x86, - 0x29, 0x00, 0x81, 0x29, 0x00, 0x84, 0x29, 0x04, - 0xbd, 0x1d, 0x20, 0x80, 0x1d, 0x60, 0x0f, 0xac, - 0x6b, 0x02, 0x8d, 0x6b, 0x01, 0x89, 0x6b, 0x03, - 0x81, 0x6b, 0x60, 0xdf, 0x9e, 0xa1, 0x10, 0xb9, - 0xa6, 0x04, 0x80, 0xa6, 0x61, 0x6f, 0xa9, 0x65, - 0x60, 0x75, 0xaa, 0x6e, 0x03, 0x80, 0x6e, 0x61, - 0x7f, 0x86, 0x27, 0x00, 0x83, 0x27, 0x00, 0x81, - 0x27, 0x00, 0x8e, 0x27, 0x00, 0xe0, 0x64, 0x5b, - 0x01, 0x8f, 0x5b, 0x28, 0xcb, 0x01, 0x03, 0x89, - 0x01, 0x03, 0x81, 0x01, 0x62, 0xb0, 0xc3, 0x19, - 0x4b, 0xbc, 0x19, 0x60, 0x61, 0x83, 0x04, 0x00, - 0x9a, 0x04, 0x00, 0x81, 0x04, 0x00, 0x80, 0x04, - 0x01, 0x80, 0x04, 0x00, 0x89, 0x04, 0x00, 0x83, - 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, 0x05, - 0x80, 0x04, 0x03, 0x80, 0x04, 0x00, 0x80, 0x04, - 0x00, 0x80, 0x04, 0x00, 0x82, 0x04, 0x00, 0x81, - 0x04, 0x00, 0x80, 0x04, 0x01, 0x80, 0x04, 0x00, - 0x80, 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, - 0x00, 0x80, 0x04, 0x00, 0x81, 0x04, 0x00, 0x80, - 0x04, 0x01, 0x83, 0x04, 0x00, 0x86, 0x04, 0x00, - 0x83, 0x04, 0x00, 0x83, 0x04, 0x00, 0x80, 0x04, - 0x00, 0x89, 0x04, 0x00, 0x90, 0x04, 0x04, 0x82, - 0x04, 0x00, 0x84, 0x04, 0x00, 0x90, 0x04, 0x33, - 0x81, 0x04, 0x60, 0xad, 0xab, 0x19, 0x03, 0xe0, - 0x03, 0x19, 0x0b, 0x8e, 0x19, 0x01, 0x8e, 0x19, - 0x00, 0x8e, 0x19, 0x00, 0xa4, 0x19, 0x09, 0xe0, - 0x4d, 0x19, 0x37, 0x99, 0x19, 0x80, 0x38, 0x81, - 0x19, 0x0c, 0xab, 0x19, 0x03, 0x88, 0x19, 0x06, - 0x81, 0x19, 0x0d, 0x85, 0x19, 0x60, 0x39, 0xe3, - 0x77, 0x19, 0x03, 0x90, 0x19, 0x02, 0x8c, 0x19, - 0x02, 0xe0, 0x16, 0x19, 0x03, 0xde, 0x19, 0x05, - 0x8b, 0x19, 0x03, 0x80, 0x19, 0x0e, 0x8b, 0x19, - 0x03, 0xb7, 0x19, 0x07, 0x89, 0x19, 0x05, 0xa7, - 0x19, 0x07, 0x9d, 0x19, 0x01, 0x8b, 0x19, 0x03, - 0x81, 0x19, 0x3d, 0xe0, 0xf3, 0x19, 0x0b, 0x8d, - 0x19, 0x01, 0x8c, 0x19, 0x02, 0x89, 0x19, 0x04, - 0xb7, 0x19, 0x06, 0x8e, 0x19, 0x01, 0x8a, 0x19, - 0x05, 0x88, 0x19, 0x06, 0xe0, 0x32, 0x19, 0x00, - 0xe0, 0x05, 0x19, 0x63, 0xa5, 0xf0, 0x96, 0x7f, - 0x32, 0x1f, 0xef, 0xd9, 0x32, 0x05, 0xe0, 0x7d, - 0x32, 0x01, 0xf0, 0x06, 0x21, 0x32, 0x0d, 0xf0, - 0x0c, 0xd0, 0x32, 0x0e, 0xe2, 0x0d, 0x32, 0x69, - 0x41, 0xe1, 0xbd, 0x32, 0x65, 0x81, 0xf0, 0x02, - 0xea, 0x32, 0x04, 0xef, 0xff, 0x32, 0x7a, 0xcb, - 0xf0, 0x80, 0x19, 0x1d, 0xdf, 0x19, 0x60, 0x1f, - 0xe0, 0x8f, 0x3a, + 0x00, 0xb6, 0x38, 0x07, 0x9a, 0x38, 0x03, 0x85, + 0x38, 0x0a, 0x84, 0x04, 0x80, 0x1a, 0x85, 0x04, + 0x80, 0x1a, 0x8d, 0x04, 0x80, 0x1a, 0x82, 0x04, + 0x80, 0x1a, 0x9f, 0x04, 0x80, 0x1a, 0x89, 0x04, + 0x8a, 0x3b, 0x99, 0x04, 0x80, 0x3b, 0xe0, 0x0b, + 0x04, 0x80, 0x1a, 0xa1, 0x04, 0x8d, 0x93, 0x00, + 0xbb, 0x93, 0x01, 0x82, 0x93, 0xaf, 0x04, 0xb1, + 0x9e, 0x0d, 0xba, 0x6b, 0x01, 0x82, 0x6b, 0xad, + 0x85, 0x01, 0x8e, 0x85, 0x00, 0x9b, 0x57, 0x01, + 0x80, 0x57, 0x00, 0x8a, 0x93, 0x04, 0xa1, 0x04, + 0x04, 0xca, 0x04, 0x80, 0x1a, 0x9c, 0x04, 0xd0, + 0x21, 0x83, 0x3b, 0x8e, 0x21, 0x81, 0x1a, 0x99, + 0x21, 0x83, 0x0b, 0x00, 0x87, 0x0b, 0x01, 0x81, + 0x0b, 0x01, 0x95, 0x0b, 0x00, 0x86, 0x0b, 0x00, + 0x80, 0x0b, 0x02, 0x83, 0x0b, 0x01, 0x88, 0x0b, + 0x01, 0x81, 0x0b, 0x01, 0x83, 0x0b, 0x07, 0x80, + 0x0b, 0x03, 0x81, 0x0b, 0x00, 0x84, 0x0b, 0x01, + 0x98, 0x0b, 0x01, 0x82, 0x31, 0x00, 0x85, 0x31, + 0x03, 0x81, 0x31, 0x01, 0x95, 0x31, 0x00, 0x86, + 0x31, 0x00, 0x81, 0x31, 0x00, 0x81, 0x31, 0x00, + 0x81, 0x31, 0x01, 0x80, 0x31, 0x00, 0x84, 0x31, + 0x03, 0x81, 0x31, 0x01, 0x82, 0x31, 0x02, 0x80, + 0x31, 0x06, 0x83, 0x31, 0x00, 0x80, 0x31, 0x06, + 0x90, 0x31, 0x09, 0x82, 0x2f, 0x00, 0x88, 0x2f, + 0x00, 0x82, 0x2f, 0x00, 0x95, 0x2f, 0x00, 0x86, + 0x2f, 0x00, 0x81, 0x2f, 0x00, 0x84, 0x2f, 0x01, + 0x89, 0x2f, 0x00, 0x82, 0x2f, 0x00, 0x82, 0x2f, + 0x01, 0x80, 0x2f, 0x0e, 0x83, 0x2f, 0x01, 0x8b, + 0x2f, 0x06, 0x86, 0x2f, 0x00, 0x82, 0x7a, 0x00, + 0x87, 0x7a, 0x01, 0x81, 0x7a, 0x01, 0x95, 0x7a, + 0x00, 0x86, 0x7a, 0x00, 0x81, 0x7a, 0x00, 0x84, + 0x7a, 0x01, 0x88, 0x7a, 0x01, 0x81, 0x7a, 0x01, + 0x82, 0x7a, 0x06, 0x82, 0x7a, 0x03, 0x81, 0x7a, + 0x00, 0x84, 0x7a, 0x01, 0x91, 0x7a, 0x09, 0x81, + 0x9b, 0x00, 0x85, 0x9b, 0x02, 0x82, 0x9b, 0x00, + 0x83, 0x9b, 0x02, 0x81, 0x9b, 0x00, 0x80, 0x9b, + 0x00, 0x81, 0x9b, 0x02, 0x81, 0x9b, 0x02, 0x82, + 0x9b, 0x02, 0x8b, 0x9b, 0x03, 0x84, 0x9b, 0x02, + 0x82, 0x9b, 0x00, 0x83, 0x9b, 0x01, 0x80, 0x9b, + 0x05, 0x80, 0x9b, 0x0d, 0x94, 0x9b, 0x04, 0x8c, + 0x9d, 0x00, 0x82, 0x9d, 0x00, 0x96, 0x9d, 0x00, + 0x8f, 0x9d, 0x01, 0x88, 0x9d, 0x00, 0x82, 0x9d, + 0x00, 0x83, 0x9d, 0x06, 0x81, 0x9d, 0x00, 0x82, + 0x9d, 0x00, 0x81, 0x9d, 0x01, 0x83, 0x9d, 0x01, + 0x89, 0x9d, 0x06, 0x88, 0x9d, 0x8c, 0x40, 0x00, + 0x82, 0x40, 0x00, 0x96, 0x40, 0x00, 0x89, 0x40, + 0x00, 0x84, 0x40, 0x01, 0x88, 0x40, 0x00, 0x82, + 0x40, 0x00, 0x83, 0x40, 0x06, 0x81, 0x40, 0x04, + 0x82, 0x40, 0x00, 0x83, 0x40, 0x01, 0x89, 0x40, + 0x00, 0x82, 0x40, 0x0b, 0x8c, 0x56, 0x00, 0x82, + 0x56, 0x00, 0xb2, 0x56, 0x00, 0x82, 0x56, 0x00, + 0x85, 0x56, 0x03, 0x8f, 0x56, 0x01, 0x99, 0x56, + 0x00, 0x82, 0x8c, 0x00, 0x91, 0x8c, 0x02, 0x97, + 0x8c, 0x00, 0x88, 0x8c, 0x00, 0x80, 0x8c, 0x01, + 0x86, 0x8c, 0x02, 0x80, 0x8c, 0x03, 0x85, 0x8c, + 0x00, 0x80, 0x8c, 0x00, 0x87, 0x8c, 0x05, 0x89, + 0x8c, 0x01, 0x82, 0x8c, 0x0b, 0xb9, 0x9f, 0x03, + 0x80, 0x1a, 0x9b, 0x9f, 0x24, 0x81, 0x4b, 0x00, + 0x80, 0x4b, 0x00, 0x84, 0x4b, 0x00, 0x97, 0x4b, + 0x00, 0x80, 0x4b, 0x00, 0x96, 0x4b, 0x01, 0x84, + 0x4b, 0x00, 0x80, 0x4b, 0x00, 0x86, 0x4b, 0x00, + 0x89, 0x4b, 0x01, 0x83, 0x4b, 0x1f, 0xc7, 0xa0, + 0x00, 0xa3, 0xa0, 0x03, 0xa6, 0xa0, 0x00, 0xa3, + 0xa0, 0x00, 0x8e, 0xa0, 0x00, 0x86, 0xa0, 0x83, + 0x1a, 0x81, 0xa0, 0x24, 0xe0, 0x3f, 0x65, 0xa5, + 0x29, 0x00, 0x80, 0x29, 0x04, 0x80, 0x29, 0x01, + 0xaa, 0x29, 0x80, 0x1a, 0x83, 0x29, 0xe0, 0x9f, + 0x34, 0xc8, 0x28, 0x00, 0x83, 0x28, 0x01, 0x86, + 0x28, 0x00, 0x80, 0x28, 0x00, 0x83, 0x28, 0x01, + 0xa8, 0x28, 0x00, 0x83, 0x28, 0x01, 0xa0, 0x28, + 0x00, 0x83, 0x28, 0x01, 0x86, 0x28, 0x00, 0x80, + 0x28, 0x00, 0x83, 0x28, 0x01, 0x8e, 0x28, 0x00, + 0xb8, 0x28, 0x00, 0x83, 0x28, 0x01, 0xc2, 0x28, + 0x01, 0x9f, 0x28, 0x02, 0x99, 0x28, 0x05, 0xd5, + 0x18, 0x01, 0x85, 0x18, 0x01, 0xe2, 0x1f, 0x13, + 0x9c, 0x6e, 0x02, 0xca, 0x84, 0x82, 0x1a, 0x8a, + 0x84, 0x06, 0x95, 0x94, 0x08, 0x80, 0x94, 0x94, + 0x36, 0x81, 0x1a, 0x08, 0x93, 0x12, 0x0b, 0x8c, + 0x95, 0x00, 0x82, 0x95, 0x00, 0x81, 0x95, 0x0b, + 0xdd, 0x46, 0x01, 0x89, 0x46, 0x05, 0x89, 0x46, + 0x05, 0x81, 0x62, 0x81, 0x1a, 0x80, 0x62, 0x80, + 0x1a, 0x93, 0x62, 0x05, 0xd8, 0x62, 0x06, 0xaa, + 0x62, 0x04, 0xc5, 0x13, 0x09, 0x9e, 0x4e, 0x00, + 0x8b, 0x4e, 0x03, 0x8b, 0x4e, 0x03, 0x80, 0x4e, + 0x02, 0x8b, 0x4e, 0x9d, 0x96, 0x01, 0x84, 0x96, + 0x0a, 0xab, 0x69, 0x03, 0x99, 0x69, 0x05, 0x8a, + 0x69, 0x02, 0x81, 0x69, 0x9f, 0x46, 0x9b, 0x11, + 0x01, 0x81, 0x11, 0xbe, 0x97, 0x00, 0x9c, 0x97, + 0x01, 0x8a, 0x97, 0x05, 0x89, 0x97, 0x05, 0x8d, + 0x97, 0x01, 0xad, 0x3b, 0x01, 0x8b, 0x3b, 0x13, + 0xcc, 0x07, 0x00, 0xb1, 0x07, 0xbf, 0x90, 0xb3, + 0x0a, 0x07, 0x83, 0x0a, 0xb7, 0x4d, 0x02, 0x8e, + 0x4d, 0x02, 0x82, 0x4d, 0xaf, 0x6f, 0x8a, 0x1e, + 0x04, 0xaa, 0x29, 0x01, 0x82, 0x29, 0x87, 0x90, + 0x07, 0x82, 0x3b, 0x80, 0x1a, 0x8c, 0x3b, 0x80, + 0x1a, 0x86, 0x3b, 0x83, 0x1a, 0x80, 0x3b, 0x85, + 0x1a, 0x80, 0x3b, 0x82, 0x1a, 0x81, 0x3b, 0x80, + 0x1a, 0x04, 0xa5, 0x4c, 0x84, 0x2e, 0x80, 0x1e, + 0xb0, 0x4c, 0x84, 0x2e, 0x83, 0x4c, 0x84, 0x2e, + 0x8c, 0x4c, 0x80, 0x1e, 0xc5, 0x4c, 0x80, 0x2e, + 0xbf, 0x3b, 0xe0, 0x9f, 0x4c, 0x95, 0x2e, 0x01, + 0x85, 0x2e, 0x01, 0xa5, 0x2e, 0x01, 0x85, 0x2e, + 0x01, 0x87, 0x2e, 0x00, 0x80, 0x2e, 0x00, 0x80, + 0x2e, 0x00, 0x80, 0x2e, 0x00, 0x9e, 0x2e, 0x01, + 0xb4, 0x2e, 0x00, 0x8e, 0x2e, 0x00, 0x8d, 0x2e, + 0x01, 0x85, 0x2e, 0x00, 0x92, 0x2e, 0x01, 0x82, + 0x2e, 0x00, 0x88, 0x2e, 0x00, 0x8b, 0x1a, 0x81, + 0x3b, 0xd6, 0x1a, 0x00, 0x8a, 0x1a, 0x80, 0x4c, + 0x01, 0x8a, 0x1a, 0x80, 0x4c, 0x8e, 0x1a, 0x00, + 0x8c, 0x4c, 0x02, 0xa1, 0x1a, 0x0d, 0xa0, 0x3b, + 0x0e, 0xa5, 0x1a, 0x80, 0x2e, 0x82, 0x1a, 0x81, + 0x4c, 0x85, 0x1a, 0x80, 0x4c, 0x9a, 0x1a, 0x80, + 0x4c, 0x90, 0x1a, 0xa8, 0x4c, 0x82, 0x1a, 0x03, + 0xe2, 0x39, 0x1a, 0x15, 0x8a, 0x1a, 0x14, 0xe3, + 0x3f, 0x1a, 0xe0, 0x9f, 0x10, 0xe2, 0x13, 0x1a, + 0x01, 0xe0, 0x29, 0x1a, 0xdf, 0x2a, 0x9f, 0x4c, + 0xe0, 0x13, 0x1b, 0x04, 0x86, 0x1b, 0xa5, 0x29, + 0x00, 0x80, 0x29, 0x04, 0x80, 0x29, 0x01, 0xb7, + 0xa1, 0x06, 0x81, 0xa1, 0x0d, 0x80, 0xa1, 0x96, + 0x28, 0x08, 0x86, 0x28, 0x00, 0x86, 0x28, 0x00, + 0x86, 0x28, 0x00, 0x86, 0x28, 0x00, 0x86, 0x28, + 0x00, 0x86, 0x28, 0x00, 0x86, 0x28, 0x00, 0x86, + 0x28, 0x00, 0x9f, 0x1e, 0xdd, 0x1a, 0x21, 0x99, + 0x33, 0x00, 0xd8, 0x33, 0x0b, 0xe0, 0x75, 0x33, + 0x19, 0x94, 0x1a, 0x80, 0x33, 0x80, 0x1a, 0x80, + 0x33, 0x98, 0x1a, 0x88, 0x33, 0x83, 0x3b, 0x81, + 0x34, 0x87, 0x1a, 0x83, 0x33, 0x83, 0x1a, 0x00, + 0xd5, 0x39, 0x01, 0x81, 0x3b, 0x81, 0x1a, 0x82, + 0x39, 0x80, 0x1a, 0xd9, 0x41, 0x81, 0x1a, 0x82, + 0x41, 0x04, 0xaa, 0x0e, 0x00, 0xdd, 0x34, 0x00, + 0x8f, 0x1a, 0x9f, 0x0e, 0xa5, 0x1a, 0x08, 0x80, + 0x1a, 0x8f, 0x41, 0x9e, 0x34, 0x00, 0xbf, 0x1a, + 0x9e, 0x34, 0xd0, 0x1a, 0xae, 0x41, 0x80, 0x1a, + 0xd7, 0x41, 0xe0, 0x47, 0x1a, 0xf0, 0x09, 0x5f, + 0x33, 0xbf, 0x1a, 0xf0, 0x41, 0x9f, 0x33, 0xe4, + 0x2c, 0xae, 0x02, 0xb6, 0xae, 0x08, 0xaf, 0x51, + 0xe0, 0xcb, 0xa9, 0x13, 0xdf, 0x1e, 0xd7, 0x08, + 0x07, 0xa1, 0x1a, 0xe0, 0x05, 0x4c, 0x82, 0x1a, + 0xd1, 0x4c, 0x13, 0x8e, 0x4c, 0xac, 0x92, 0x02, + 0x89, 0x1a, 0x05, 0xb7, 0x80, 0x07, 0xc5, 0x86, + 0x07, 0x8b, 0x86, 0x05, 0x9f, 0x21, 0xad, 0x44, + 0x80, 0x1a, 0x80, 0x44, 0xa3, 0x83, 0x0a, 0x80, + 0x83, 0x9c, 0x34, 0x02, 0xcd, 0x3e, 0x00, 0x80, + 0x1a, 0x89, 0x3e, 0x03, 0x81, 0x3e, 0x9e, 0x65, + 0x00, 0xb6, 0x17, 0x08, 0x8d, 0x17, 0x01, 0x89, + 0x17, 0x01, 0x83, 0x17, 0x9f, 0x65, 0xc2, 0x98, + 0x17, 0x84, 0x98, 0x96, 0x5c, 0x09, 0x85, 0x28, + 0x01, 0x85, 0x28, 0x01, 0x85, 0x28, 0x08, 0x86, + 0x28, 0x00, 0x86, 0x28, 0x00, 0xaa, 0x4c, 0x80, + 0x1a, 0x88, 0x4c, 0x80, 0x2e, 0x83, 0x4c, 0x81, + 0x1a, 0x03, 0xcf, 0x18, 0xad, 0x5c, 0x01, 0x89, + 0x5c, 0x05, 0xf0, 0x1b, 0x43, 0x34, 0x0b, 0x96, + 0x34, 0x03, 0xb0, 0x34, 0x70, 0x10, 0xa3, 0xe1, + 0x0d, 0x33, 0x01, 0xe0, 0x09, 0x33, 0x25, 0x86, + 0x4c, 0x0b, 0x84, 0x05, 0x04, 0x99, 0x38, 0x00, + 0x84, 0x38, 0x00, 0x80, 0x38, 0x00, 0x81, 0x38, + 0x00, 0x81, 0x38, 0x00, 0x89, 0x38, 0xe1, 0x8d, + 0x04, 0x81, 0x1a, 0xe0, 0x2f, 0x04, 0x1f, 0x8f, + 0x04, 0x8f, 0x3b, 0x89, 0x1a, 0x05, 0x8d, 0x3b, + 0x81, 0x1e, 0xa2, 0x1a, 0x00, 0x92, 0x1a, 0x00, + 0x83, 0x1a, 0x03, 0x84, 0x04, 0x00, 0xe0, 0x26, + 0x04, 0x01, 0x80, 0x1a, 0x00, 0x9f, 0x1a, 0x99, + 0x4c, 0x85, 0x1a, 0x99, 0x4c, 0x8a, 0x1a, 0x89, + 0x41, 0x80, 0x1a, 0xac, 0x41, 0x81, 0x1a, 0x9e, + 0x34, 0x02, 0x85, 0x34, 0x01, 0x85, 0x34, 0x01, + 0x85, 0x34, 0x01, 0x82, 0x34, 0x02, 0x86, 0x1a, + 0x00, 0x86, 0x1a, 0x09, 0x84, 0x1a, 0x01, 0x8b, + 0x50, 0x00, 0x99, 0x50, 0x00, 0x92, 0x50, 0x00, + 0x81, 0x50, 0x00, 0x8e, 0x50, 0x01, 0x8d, 0x50, + 0x21, 0xe0, 0x1a, 0x50, 0x04, 0x82, 0x1a, 0x03, + 0xac, 0x1a, 0x02, 0x88, 0x1a, 0xce, 0x2e, 0x00, + 0x8c, 0x1a, 0x02, 0x80, 0x2e, 0x2e, 0xac, 0x1a, + 0x80, 0x3b, 0x60, 0x21, 0x9c, 0x52, 0x02, 0xb0, + 0x14, 0x0e, 0x80, 0x3b, 0x9a, 0x1a, 0x03, 0xa3, + 0x72, 0x08, 0x82, 0x72, 0x9a, 0x2b, 0x04, 0xaa, + 0x74, 0x04, 0x9d, 0xa8, 0x00, 0x80, 0xa8, 0xa3, + 0x75, 0x03, 0x8d, 0x75, 0x29, 0xcf, 0x20, 0xaf, + 0x88, 0x9d, 0x7c, 0x01, 0x89, 0x7c, 0x05, 0xa3, + 0x7b, 0x03, 0xa3, 0x7b, 0x03, 0xa7, 0x26, 0x07, + 0xb3, 0x15, 0x0a, 0x80, 0x15, 0x8a, 0xaa, 0x00, + 0x8e, 0xaa, 0x00, 0x86, 0xaa, 0x00, 0x81, 0xaa, + 0x00, 0x8a, 0xaa, 0x00, 0x8e, 0xaa, 0x00, 0x86, + 0xaa, 0x00, 0x81, 0xaa, 0x02, 0xb3, 0xa4, 0x0b, + 0xe0, 0xd6, 0x4f, 0x08, 0x95, 0x4f, 0x09, 0x87, + 0x4f, 0x17, 0x85, 0x4c, 0x00, 0xa9, 0x4c, 0x00, + 0x88, 0x4c, 0x44, 0x85, 0x1d, 0x01, 0x80, 0x1d, + 0x00, 0xab, 0x1d, 0x00, 0x81, 0x1d, 0x02, 0x80, + 0x1d, 0x01, 0x80, 0x1d, 0x95, 0x3a, 0x00, 0x88, + 0x3a, 0x9f, 0x7e, 0x9e, 0x66, 0x07, 0x88, 0x66, + 0x2f, 0x92, 0x37, 0x00, 0x81, 0x37, 0x04, 0x84, + 0x37, 0x9b, 0x81, 0x02, 0x80, 0x81, 0x99, 0x53, + 0x04, 0x80, 0x53, 0x99, 0x8a, 0x25, 0x9f, 0x5f, + 0x97, 0x5e, 0x03, 0x93, 0x5e, 0x01, 0xad, 0x5e, + 0x83, 0x45, 0x00, 0x81, 0x45, 0x04, 0x87, 0x45, + 0x00, 0x82, 0x45, 0x00, 0x9c, 0x45, 0x01, 0x82, + 0x45, 0x03, 0x89, 0x45, 0x06, 0x88, 0x45, 0x06, + 0x9f, 0x77, 0x9f, 0x73, 0x1f, 0xa6, 0x58, 0x03, + 0x8b, 0x58, 0x08, 0xb5, 0x06, 0x02, 0x86, 0x06, + 0x95, 0x3d, 0x01, 0x87, 0x3d, 0x92, 0x3c, 0x04, + 0x87, 0x3c, 0x91, 0x82, 0x06, 0x83, 0x82, 0x0b, + 0x86, 0x82, 0x4f, 0xc8, 0x78, 0x36, 0xb2, 0x71, + 0x0c, 0xb2, 0x71, 0x06, 0x85, 0x71, 0xa7, 0x35, + 0x07, 0x89, 0x35, 0x05, 0xa5, 0x2c, 0x02, 0x9c, + 0x2c, 0x07, 0x81, 0x2c, 0x60, 0x6f, 0x9e, 0x04, + 0x00, 0xa9, 0xad, 0x00, 0x82, 0xad, 0x01, 0x81, + 0xad, 0x0f, 0x85, 0x04, 0x07, 0x88, 0x04, 0x20, + 0x85, 0x04, 0xa7, 0x76, 0x07, 0xa9, 0x8d, 0x15, + 0x99, 0x79, 0x25, 0x9b, 0x19, 0x13, 0x96, 0x27, + 0x08, 0xcd, 0x0f, 0x03, 0xa3, 0x0f, 0x08, 0x80, + 0x0f, 0xc2, 0x3f, 0x09, 0x80, 0x3f, 0x01, 0x98, + 0x8e, 0x06, 0x89, 0x8e, 0x05, 0xb4, 0x16, 0x00, + 0x91, 0x16, 0x07, 0xa6, 0x55, 0x08, 0xdf, 0x87, + 0x00, 0x93, 0x8c, 0x0a, 0x91, 0x47, 0x00, 0xae, + 0x47, 0x3d, 0x86, 0x64, 0x00, 0x80, 0x64, 0x00, + 0x83, 0x64, 0x00, 0x8e, 0x64, 0x00, 0x8a, 0x64, + 0x05, 0xba, 0x49, 0x04, 0x89, 0x49, 0x05, 0x83, + 0x2d, 0x00, 0x87, 0x2d, 0x01, 0x81, 0x2d, 0x01, + 0x95, 0x2d, 0x00, 0x86, 0x2d, 0x00, 0x81, 0x2d, + 0x00, 0x84, 0x2d, 0x00, 0x80, 0x3b, 0x88, 0x2d, + 0x01, 0x81, 0x2d, 0x01, 0x82, 0x2d, 0x01, 0x80, + 0x2d, 0x05, 0x80, 0x2d, 0x04, 0x86, 0x2d, 0x01, + 0x86, 0x2d, 0x02, 0x84, 0x2d, 0x0a, 0x89, 0xa7, + 0x00, 0x80, 0xa7, 0x01, 0x80, 0xa7, 0x00, 0xa5, + 0xa7, 0x00, 0x89, 0xa7, 0x00, 0x80, 0xa7, 0x01, + 0x80, 0xa7, 0x00, 0x83, 0xa7, 0x00, 0x89, 0xa7, + 0x00, 0x81, 0xa7, 0x07, 0x81, 0xa7, 0x1c, 0xdb, + 0x6a, 0x00, 0x84, 0x6a, 0x1d, 0xc7, 0xa2, 0x07, + 0x89, 0xa2, 0x60, 0x45, 0xb5, 0x89, 0x01, 0xa5, + 0x89, 0x21, 0xc4, 0x61, 0x0a, 0x89, 0x61, 0x05, + 0x8c, 0x62, 0x12, 0xb9, 0x9a, 0x05, 0x89, 0x9a, + 0x05, 0x93, 0x65, 0x1b, 0x9a, 0x02, 0x01, 0x8e, + 0x02, 0x03, 0x96, 0x02, 0x60, 0x58, 0xbb, 0x23, + 0x60, 0x03, 0xd2, 0xac, 0x0b, 0x80, 0xac, 0x86, + 0x22, 0x01, 0x80, 0x22, 0x01, 0x87, 0x22, 0x00, + 0x81, 0x22, 0x00, 0x9d, 0x22, 0x00, 0x81, 0x22, + 0x01, 0x8b, 0x22, 0x08, 0x89, 0x22, 0x45, 0x87, + 0x68, 0x01, 0xad, 0x68, 0x01, 0x8a, 0x68, 0x1a, + 0xc7, 0xaf, 0x07, 0xd2, 0x8f, 0x0c, 0x8f, 0x13, + 0xb8, 0x7f, 0x06, 0x89, 0x21, 0x55, 0x87, 0x87, + 0x57, 0xa1, 0x91, 0x0d, 0x89, 0x91, 0x05, 0x88, + 0x0d, 0x00, 0xac, 0x0d, 0x00, 0x8d, 0x0d, 0x09, + 0x9c, 0x0d, 0x02, 0x9f, 0x59, 0x01, 0x95, 0x59, + 0x00, 0x8d, 0x59, 0x48, 0x86, 0x5a, 0x00, 0x81, + 0x5a, 0x00, 0xab, 0x5a, 0x02, 0x80, 0x5a, 0x00, + 0x81, 0x5a, 0x00, 0x88, 0x5a, 0x07, 0x89, 0x5a, + 0x05, 0x85, 0x30, 0x00, 0x81, 0x30, 0x00, 0xa4, + 0x30, 0x00, 0x81, 0x30, 0x00, 0x85, 0x30, 0x06, + 0x89, 0x30, 0x05, 0xab, 0xa5, 0x03, 0x89, 0xa5, + 0x60, 0x95, 0x98, 0x54, 0x06, 0x90, 0x43, 0x00, + 0xa8, 0x43, 0x02, 0x9c, 0x43, 0x54, 0x80, 0x51, + 0x0e, 0xb1, 0x9b, 0x0c, 0x80, 0x9b, 0xe3, 0x39, + 0x1c, 0x60, 0x05, 0xe0, 0x0e, 0x1c, 0x00, 0x84, + 0x1c, 0x0a, 0xe0, 0x63, 0x1c, 0x69, 0xeb, 0xe0, + 0x02, 0x1f, 0x0c, 0xe3, 0xf5, 0x25, 0x09, 0xef, + 0x3a, 0x25, 0x04, 0xe1, 0xe6, 0x03, 0x70, 0x0a, + 0x58, 0xb9, 0x32, 0x66, 0x65, 0xe1, 0xd8, 0x08, + 0x06, 0x9e, 0x63, 0x00, 0x89, 0x63, 0x03, 0x81, + 0x63, 0xce, 0xa3, 0x00, 0x89, 0xa3, 0x05, 0x9d, + 0x09, 0x01, 0x85, 0x09, 0x09, 0xc5, 0x7d, 0x09, + 0x89, 0x7d, 0x00, 0x86, 0x7d, 0x00, 0x94, 0x7d, + 0x04, 0x92, 0x7d, 0x61, 0x4f, 0xb9, 0x4a, 0x60, + 0x65, 0xda, 0x5b, 0x04, 0x98, 0x0c, 0x01, 0x98, + 0x0c, 0x2b, 0xca, 0x60, 0x03, 0xb8, 0x60, 0x06, + 0x90, 0x60, 0x3f, 0x80, 0x9c, 0x80, 0x6c, 0x81, + 0x33, 0x80, 0x48, 0x0a, 0x86, 0x33, 0x08, 0xf0, + 0x0a, 0x9f, 0x9c, 0xe1, 0x75, 0x48, 0x28, 0x80, + 0x48, 0x9e, 0x9c, 0x60, 0x00, 0xe0, 0x12, 0x9c, + 0x70, 0x11, 0x9c, 0x83, 0x41, 0x00, 0x86, 0x41, + 0x00, 0x81, 0x41, 0x00, 0x80, 0x41, 0xe0, 0xbe, + 0x39, 0x82, 0x41, 0x0e, 0x80, 0x39, 0x1c, 0x82, + 0x39, 0x01, 0x80, 0x41, 0x0d, 0x83, 0x41, 0x07, + 0xe1, 0x2b, 0x6c, 0x68, 0xa3, 0xe0, 0x0a, 0x24, + 0x04, 0x8c, 0x24, 0x02, 0x88, 0x24, 0x06, 0x89, + 0x24, 0x01, 0x83, 0x24, 0x83, 0x1a, 0x6e, 0xfb, + 0xe0, 0x9c, 0x1a, 0x02, 0xe1, 0x53, 0x1a, 0x05, + 0x96, 0x1a, 0x0e, 0x90, 0x1a, 0x0e, 0xad, 0x3b, + 0x01, 0x96, 0x3b, 0x08, 0xe0, 0x13, 0x1a, 0x3b, + 0xe0, 0x95, 0x1a, 0x09, 0xa6, 0x1a, 0x01, 0xbd, + 0x1a, 0x82, 0x3b, 0x90, 0x1a, 0x87, 0x3b, 0x81, + 0x1a, 0x86, 0x3b, 0x9d, 0x1a, 0x83, 0x3b, 0xbc, + 0x1a, 0x14, 0xc5, 0x2e, 0x60, 0x19, 0x93, 0x1a, + 0x0b, 0x93, 0x1a, 0x0b, 0xd6, 0x1a, 0x08, 0x98, + 0x1a, 0x60, 0x26, 0xd4, 0x1a, 0x00, 0xc6, 0x1a, + 0x00, 0x81, 0x1a, 0x01, 0x80, 0x1a, 0x01, 0x81, + 0x1a, 0x01, 0x83, 0x1a, 0x00, 0x8b, 0x1a, 0x00, + 0x80, 0x1a, 0x00, 0x86, 0x1a, 0x00, 0xc0, 0x1a, + 0x00, 0x83, 0x1a, 0x01, 0x87, 0x1a, 0x00, 0x86, + 0x1a, 0x00, 0x9b, 0x1a, 0x00, 0x83, 0x1a, 0x00, + 0x84, 0x1a, 0x00, 0x80, 0x1a, 0x02, 0x86, 0x1a, + 0x00, 0xe0, 0xf3, 0x1a, 0x01, 0xe0, 0xc3, 0x1a, + 0x01, 0xb1, 0x1a, 0xe2, 0x2b, 0x8b, 0x0e, 0x84, + 0x8b, 0x00, 0x8e, 0x8b, 0x63, 0xef, 0x9e, 0x4c, + 0x05, 0x85, 0x4c, 0x60, 0x74, 0x86, 0x2a, 0x00, + 0x90, 0x2a, 0x01, 0x86, 0x2a, 0x00, 0x81, 0x2a, + 0x00, 0x84, 0x2a, 0x04, 0xbd, 0x1e, 0x20, 0x80, + 0x1e, 0x60, 0x0f, 0xac, 0x6d, 0x02, 0x8d, 0x6d, + 0x01, 0x89, 0x6d, 0x03, 0x81, 0x6d, 0x60, 0xdf, + 0x9e, 0xa6, 0x10, 0xb9, 0xab, 0x04, 0x80, 0xab, + 0x61, 0x6f, 0xa9, 0x67, 0x60, 0x75, 0xaa, 0x70, + 0x03, 0x80, 0x70, 0x60, 0x5f, 0x9e, 0x99, 0x00, + 0x95, 0x99, 0x07, 0x81, 0x99, 0x60, 0x7f, 0x86, + 0x28, 0x00, 0x83, 0x28, 0x00, 0x81, 0x28, 0x00, + 0x8e, 0x28, 0x00, 0xe0, 0x64, 0x5d, 0x01, 0x8f, + 0x5d, 0x28, 0xcb, 0x01, 0x03, 0x89, 0x01, 0x03, + 0x81, 0x01, 0x62, 0xb0, 0xc3, 0x1a, 0x4b, 0xbc, + 0x1a, 0x60, 0x61, 0x83, 0x04, 0x00, 0x9a, 0x04, + 0x00, 0x81, 0x04, 0x00, 0x80, 0x04, 0x01, 0x80, + 0x04, 0x00, 0x89, 0x04, 0x00, 0x83, 0x04, 0x00, + 0x80, 0x04, 0x00, 0x80, 0x04, 0x05, 0x80, 0x04, + 0x03, 0x80, 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, + 0x04, 0x00, 0x82, 0x04, 0x00, 0x81, 0x04, 0x00, + 0x80, 0x04, 0x01, 0x80, 0x04, 0x00, 0x80, 0x04, + 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, + 0x04, 0x00, 0x81, 0x04, 0x00, 0x80, 0x04, 0x01, + 0x83, 0x04, 0x00, 0x86, 0x04, 0x00, 0x83, 0x04, + 0x00, 0x83, 0x04, 0x00, 0x80, 0x04, 0x00, 0x89, + 0x04, 0x00, 0x90, 0x04, 0x04, 0x82, 0x04, 0x00, + 0x84, 0x04, 0x00, 0x90, 0x04, 0x33, 0x81, 0x04, + 0x60, 0xad, 0xab, 0x1a, 0x03, 0xe0, 0x03, 0x1a, + 0x0b, 0x8e, 0x1a, 0x01, 0x8e, 0x1a, 0x00, 0x8e, + 0x1a, 0x00, 0xa4, 0x1a, 0x09, 0xe0, 0x4d, 0x1a, + 0x37, 0x99, 0x1a, 0x80, 0x39, 0x81, 0x1a, 0x0c, + 0xab, 0x1a, 0x03, 0x88, 0x1a, 0x06, 0x81, 0x1a, + 0x0d, 0x85, 0x1a, 0x60, 0x39, 0xe3, 0x78, 0x1a, + 0x02, 0x90, 0x1a, 0x02, 0x8c, 0x1a, 0x02, 0xe0, + 0x79, 0x1a, 0x05, 0x8b, 0x1a, 0x03, 0x80, 0x1a, + 0x0e, 0x8b, 0x1a, 0x03, 0xb7, 0x1a, 0x07, 0x89, + 0x1a, 0x05, 0xa7, 0x1a, 0x07, 0x9d, 0x1a, 0x01, + 0x8b, 0x1a, 0x03, 0x81, 0x1a, 0x0d, 0x88, 0x1a, + 0x26, 0xe0, 0xf7, 0x1a, 0x07, 0x8d, 0x1a, 0x01, + 0x8c, 0x1a, 0x02, 0x8a, 0x1a, 0x02, 0xb8, 0x1a, + 0x00, 0x80, 0x1a, 0x03, 0x8f, 0x1a, 0x01, 0x8b, + 0x1a, 0x03, 0x89, 0x1a, 0x06, 0xe0, 0x32, 0x1a, + 0x00, 0xe0, 0x06, 0x1a, 0x63, 0xa4, 0xf0, 0x96, + 0x7f, 0x33, 0x1f, 0xf0, 0x00, 0xbd, 0x33, 0x01, + 0xf0, 0x06, 0x2d, 0x33, 0x01, 0xf0, 0x0c, 0xd0, + 0x33, 0x0e, 0xe2, 0x0d, 0x33, 0x69, 0x41, 0xe1, + 0xbd, 0x33, 0x65, 0x81, 0xf0, 0x02, 0xea, 0x33, + 0x04, 0xf0, 0x10, 0xc9, 0x33, 0x7a, 0xbb, 0x26, + 0x80, 0x1a, 0x1d, 0xdf, 0x1a, 0x60, 0x1f, 0xe0, + 0x8f, 0x3b, }; -static const uint8_t unicode_script_ext_table[1253] = { - 0x80, 0x36, 0x00, 0x00, 0x10, 0x06, 0x13, 0x1a, - 0x23, 0x25, 0x28, 0x29, 0x2f, 0x2a, 0x2d, 0x32, - 0x4a, 0x51, 0x53, 0x72, 0x86, 0x81, 0x83, 0x00, - 0x00, 0x07, 0x0b, 0x1d, 0x20, 0x4a, 0x4f, 0x9b, - 0xa1, 0x09, 0x00, 0x00, 0x02, 0x0d, 0x4a, 0x00, - 0x00, 0x02, 0x02, 0x0d, 0x4a, 0x00, 0x00, 0x00, - 0x02, 0x4a, 0x4f, 0x08, 0x00, 0x00, 0x02, 0x4a, - 0x9b, 0x00, 0x00, 0x00, 0x02, 0x0d, 0x4a, 0x25, - 0x00, 0x00, 0x08, 0x17, 0x1a, 0x1d, 0x2d, 0x4a, - 0x72, 0x8e, 0x93, 0x00, 0x08, 0x17, 0x1d, 0x2d, - 0x4a, 0x79, 0x8e, 0x93, 0xa0, 0x00, 0x04, 0x17, - 0x1d, 0x4a, 0x9d, 0x00, 0x05, 0x29, 0x4a, 0x8e, - 0x90, 0x9b, 0x00, 0x0b, 0x14, 0x17, 0x1a, 0x1d, - 0x2a, 0x2d, 0x4a, 0x79, 0x90, 0x9d, 0xa0, 0x00, - 0x06, 0x1a, 0x25, 0x29, 0x2a, 0x40, 0x4a, 0x00, - 0x04, 0x1d, 0x2d, 0x4a, 0x72, 0x00, 0x09, 0x1a, - 0x23, 0x37, 0x4a, 0x72, 0x90, 0x93, 0x9d, 0xa0, - 0x00, 0x0a, 0x05, 0x1d, 0x23, 0x2a, 0x2d, 0x37, - 0x4a, 0x72, 0x90, 0x93, 0x00, 0x02, 0x4a, 0x9d, - 0x00, 0x03, 0x23, 0x4a, 0x90, 0x00, 0x04, 0x17, - 0x1d, 0x4a, 0x79, 0x00, 0x03, 0x17, 0x4a, 0x93, - 0x00, 0x02, 0x4a, 0x8e, 0x00, 0x02, 0x27, 0x4a, - 0x00, 0x00, 0x00, 0x02, 0x4a, 0x8e, 0x00, 0x03, - 0x1d, 0x4a, 0xa0, 0x00, 0x00, 0x00, 0x04, 0x2d, - 0x4a, 0x72, 0xa0, 0x0b, 0x00, 0x00, 0x02, 0x4a, - 0x90, 0x01, 0x00, 0x00, 0x05, 0x17, 0x23, 0x40, - 0x4a, 0x90, 0x00, 0x04, 0x17, 0x23, 0x4a, 0x90, - 0x00, 0x02, 0x4a, 0x90, 0x06, 0x00, 0x00, 0x03, - 0x4a, 0x8e, 0x90, 0x00, 0x02, 0x4a, 0x90, 0x00, - 0x00, 0x00, 0x03, 0x17, 0x4a, 0x90, 0x00, 0x06, - 0x14, 0x17, 0x2a, 0x4a, 0x8e, 0x9b, 0x0f, 0x00, - 0x00, 0x01, 0x2d, 0x01, 0x00, 0x00, 0x01, 0x2d, - 0x11, 0x00, 0x00, 0x02, 0x4a, 0x79, 0x04, 0x00, - 0x00, 0x03, 0x14, 0x4a, 0xa0, 0x03, 0x00, 0x0c, - 0x01, 0x4a, 0x03, 0x00, 0x01, 0x02, 0x1a, 0x2d, - 0x80, 0x8c, 0x00, 0x00, 0x02, 0x1d, 0x72, 0x00, - 0x02, 0x1d, 0x29, 0x01, 0x02, 0x1d, 0x4a, 0x00, - 0x02, 0x1d, 0x29, 0x80, 0x80, 0x00, 0x00, 0x03, - 0x05, 0x28, 0x29, 0x80, 0x01, 0x00, 0x00, 0x07, - 0x04, 0x2b, 0x69, 0x34, 0x90, 0x9a, 0xa8, 0x0d, - 0x00, 0x00, 0x07, 0x04, 0x2b, 0x69, 0x34, 0x90, - 0x9a, 0xa8, 0x00, 0x03, 0x04, 0x90, 0x9a, 0x01, - 0x00, 0x00, 0x08, 0x01, 0x04, 0x2b, 0x69, 0x34, - 0x90, 0x9a, 0xa8, 0x1f, 0x00, 0x00, 0x09, 0x01, - 0x04, 0x55, 0x56, 0x77, 0x80, 0x34, 0x8a, 0x90, - 0x09, 0x00, 0x0a, 0x02, 0x04, 0x90, 0x09, 0x00, - 0x09, 0x03, 0x04, 0x9a, 0xa8, 0x05, 0x00, 0x00, - 0x02, 0x04, 0x90, 0x62, 0x00, 0x00, 0x02, 0x04, - 0x34, 0x81, 0xfb, 0x00, 0x00, 0x0d, 0x0b, 0x20, - 0x2c, 0x2e, 0x30, 0x3f, 0x4a, 0x54, 0x78, 0x85, - 0x97, 0x99, 0x9e, 0x00, 0x0c, 0x0b, 0x20, 0x2c, - 0x2e, 0x30, 0x3f, 0x4a, 0x54, 0x78, 0x97, 0x99, - 0x9e, 0x10, 0x00, 0x00, 0x15, 0x0b, 0x20, 0x22, - 0x2f, 0x58, 0x2c, 0x2e, 0x30, 0x3f, 0x53, 0x54, - 0x66, 0x6e, 0x78, 0x47, 0x89, 0x8f, 0x96, 0x97, - 0x99, 0x9e, 0x00, 0x17, 0x0b, 0x20, 0x22, 0x2f, - 0x58, 0x2c, 0x2e, 0x31, 0x30, 0x3f, 0x4c, 0x53, - 0x54, 0x66, 0x6e, 0x78, 0x47, 0x89, 0x8f, 0x96, - 0x97, 0x99, 0x9e, 0x09, 0x04, 0x20, 0x22, 0x3e, - 0x53, 0x75, 0x00, 0x09, 0x03, 0x0b, 0x15, 0x8f, - 0x75, 0x00, 0x09, 0x02, 0x30, 0x62, 0x75, 0x00, - 0x09, 0x02, 0x2e, 0x45, 0x80, 0x75, 0x00, 0x0d, - 0x02, 0x2c, 0x97, 0x80, 0x71, 0x00, 0x09, 0x03, - 0x3f, 0x66, 0xa2, 0x82, 0xcf, 0x00, 0x09, 0x03, - 0x15, 0x63, 0x93, 0x80, 0x30, 0x00, 0x00, 0x03, - 0x28, 0x29, 0x4a, 0x85, 0x6e, 0x00, 0x02, 0x01, - 0x82, 0x46, 0x00, 0x01, 0x04, 0x11, 0x35, 0x92, - 0x91, 0x80, 0x4a, 0x00, 0x01, 0x02, 0x60, 0x7e, - 0x00, 0x00, 0x00, 0x02, 0x60, 0x7e, 0x84, 0x49, - 0x00, 0x00, 0x04, 0x0b, 0x20, 0x2c, 0x3f, 0x00, - 0x01, 0x20, 0x00, 0x04, 0x0b, 0x20, 0x2c, 0x3f, - 0x00, 0x03, 0x20, 0x2c, 0x3f, 0x00, 0x01, 0x20, - 0x01, 0x02, 0x0b, 0x20, 0x00, 0x02, 0x20, 0x85, - 0x00, 0x02, 0x0b, 0x20, 0x00, 0x02, 0x20, 0x85, - 0x00, 0x06, 0x20, 0x3f, 0x54, 0x78, 0x97, 0x99, - 0x00, 0x01, 0x20, 0x01, 0x02, 0x20, 0x85, 0x01, - 0x01, 0x20, 0x00, 0x02, 0x20, 0x85, 0x00, 0x02, - 0x0b, 0x20, 0x06, 0x01, 0x20, 0x00, 0x02, 0x20, - 0x66, 0x00, 0x02, 0x0b, 0x20, 0x01, 0x01, 0x20, - 0x00, 0x02, 0x0b, 0x20, 0x03, 0x01, 0x20, 0x00, - 0x0b, 0x0b, 0x20, 0x2c, 0x3f, 0x54, 0x66, 0x78, - 0x89, 0x99, 0x9e, 0xa2, 0x00, 0x02, 0x20, 0x2c, - 0x00, 0x04, 0x20, 0x2c, 0x3f, 0xa2, 0x01, 0x02, - 0x0b, 0x20, 0x00, 0x01, 0x0b, 0x01, 0x02, 0x20, - 0x2c, 0x00, 0x01, 0x66, 0x80, 0x44, 0x00, 0x01, - 0x01, 0x2d, 0x35, 0x00, 0x00, 0x03, 0x1d, 0x4a, - 0x90, 0x00, 0x00, 0x00, 0x01, 0x90, 0x81, 0xb3, - 0x00, 0x00, 0x03, 0x4a, 0x60, 0x7e, 0x1e, 0x00, - 0x00, 0x02, 0x01, 0x04, 0x09, 0x00, 0x00, 0x06, - 0x13, 0x28, 0x29, 0x6f, 0x50, 0x76, 0x01, 0x00, - 0x00, 0x04, 0x13, 0x2d, 0x6f, 0x5d, 0x80, 0x11, - 0x00, 0x00, 0x03, 0x20, 0x2c, 0x4a, 0x8c, 0xa5, - 0x00, 0x00, 0x02, 0x1a, 0x4a, 0x17, 0x00, 0x00, - 0x02, 0x06, 0x76, 0x00, 0x07, 0x06, 0x13, 0x28, - 0x6f, 0x3e, 0x51, 0x83, 0x09, 0x00, 0x00, 0x01, - 0x23, 0x03, 0x00, 0x00, 0x03, 0x01, 0x04, 0x6f, - 0x00, 0x00, 0x00, 0x02, 0x1d, 0x29, 0x81, 0x2b, - 0x00, 0x0f, 0x02, 0x32, 0x98, 0x00, 0x00, 0x00, - 0x07, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x60, 0xa9, - 0x00, 0x08, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x60, - 0x7e, 0xa9, 0x00, 0x05, 0x0d, 0x33, 0x32, 0x38, - 0x40, 0x01, 0x00, 0x00, 0x01, 0x32, 0x00, 0x00, - 0x01, 0x08, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x60, - 0x9c, 0xa9, 0x01, 0x09, 0x0d, 0x33, 0x32, 0x38, - 0x40, 0x4f, 0x60, 0x9c, 0xa9, 0x05, 0x06, 0x0d, - 0x33, 0x32, 0x38, 0x40, 0xa9, 0x00, 0x00, 0x00, - 0x05, 0x0d, 0x33, 0x32, 0x38, 0x40, 0x07, 0x06, - 0x0d, 0x33, 0x32, 0x38, 0x40, 0xa9, 0x03, 0x05, - 0x0d, 0x33, 0x32, 0x38, 0x40, 0x09, 0x00, 0x03, - 0x02, 0x0d, 0x32, 0x01, 0x00, 0x00, 0x05, 0x0d, - 0x33, 0x32, 0x38, 0x40, 0x04, 0x02, 0x38, 0x40, - 0x00, 0x00, 0x00, 0x05, 0x0d, 0x33, 0x32, 0x38, - 0x40, 0x03, 0x00, 0x01, 0x03, 0x32, 0x38, 0x40, - 0x01, 0x01, 0x32, 0x58, 0x00, 0x03, 0x02, 0x38, - 0x40, 0x02, 0x00, 0x00, 0x02, 0x38, 0x40, 0x59, - 0x00, 0x00, 0x06, 0x0d, 0x33, 0x32, 0x38, 0x40, - 0xa9, 0x00, 0x02, 0x38, 0x40, 0x80, 0x12, 0x00, - 0x0f, 0x01, 0x32, 0x1f, 0x00, 0x25, 0x01, 0x32, - 0x08, 0x00, 0x00, 0x02, 0x32, 0x98, 0x2f, 0x00, - 0x27, 0x01, 0x32, 0x37, 0x00, 0x30, 0x01, 0x32, - 0x0e, 0x00, 0x0b, 0x01, 0x32, 0x32, 0x00, 0x00, - 0x01, 0x32, 0x57, 0x00, 0x18, 0x01, 0x32, 0x09, - 0x00, 0x04, 0x01, 0x32, 0x5f, 0x00, 0x1e, 0x01, - 0x32, 0xc0, 0x31, 0xef, 0x00, 0x00, 0x02, 0x1d, - 0x29, 0x80, 0x0f, 0x00, 0x07, 0x02, 0x32, 0x4a, - 0x80, 0xa7, 0x00, 0x02, 0x10, 0x20, 0x22, 0x2e, - 0x30, 0x45, 0x3f, 0x3e, 0x53, 0x54, 0x5f, 0x66, - 0x85, 0x47, 0x96, 0x9e, 0xa2, 0x02, 0x0f, 0x20, - 0x22, 0x2e, 0x30, 0x45, 0x3f, 0x3e, 0x53, 0x5f, - 0x66, 0x85, 0x47, 0x96, 0x9e, 0xa2, 0x01, 0x0b, - 0x20, 0x22, 0x2e, 0x30, 0x45, 0x3e, 0x53, 0x5f, - 0x47, 0x96, 0x9e, 0x00, 0x0c, 0x20, 0x22, 0x2e, - 0x30, 0x45, 0x3e, 0x53, 0x5f, 0x85, 0x47, 0x96, - 0x9e, 0x00, 0x0b, 0x20, 0x22, 0x2e, 0x30, 0x45, - 0x3e, 0x53, 0x5f, 0x47, 0x96, 0x9e, 0x80, 0x36, - 0x00, 0x00, 0x03, 0x0b, 0x20, 0xa2, 0x00, 0x00, - 0x00, 0x02, 0x20, 0x97, 0x39, 0x00, 0x00, 0x03, - 0x42, 0x4a, 0x63, 0x80, 0x1f, 0x00, 0x00, 0x02, - 0x10, 0x3d, 0xc0, 0x12, 0xed, 0x00, 0x01, 0x02, - 0x04, 0x69, 0x80, 0x31, 0x00, 0x00, 0x02, 0x04, - 0x9a, 0x09, 0x00, 0x00, 0x02, 0x04, 0x9a, 0x46, - 0x00, 0x01, 0x05, 0x0d, 0x33, 0x32, 0x38, 0x40, - 0x80, 0x99, 0x00, 0x04, 0x06, 0x0d, 0x33, 0x32, - 0x38, 0x40, 0xa9, 0x09, 0x00, 0x00, 0x02, 0x38, - 0x40, 0x2c, 0x00, 0x01, 0x02, 0x38, 0x40, 0x80, - 0xdf, 0x00, 0x01, 0x03, 0x1e, 0x1c, 0x4e, 0x00, - 0x02, 0x1c, 0x4e, 0x03, 0x00, 0x2c, 0x03, 0x1c, - 0x4d, 0x4e, 0x02, 0x00, 0x08, 0x02, 0x1c, 0x4e, - 0x81, 0x1f, 0x00, 0x1b, 0x02, 0x04, 0x1a, 0x87, - 0x75, 0x00, 0x00, 0x02, 0x56, 0x77, 0x87, 0x8d, - 0x00, 0x00, 0x02, 0x2c, 0x97, 0x00, 0x00, 0x00, - 0x02, 0x2c, 0x97, 0x36, 0x00, 0x01, 0x02, 0x2c, - 0x97, 0x8c, 0x12, 0x00, 0x01, 0x02, 0x2c, 0x97, - 0x00, 0x00, 0x00, 0x02, 0x2c, 0x97, 0xc0, 0x5c, - 0x4b, 0x00, 0x03, 0x01, 0x23, 0x96, 0x3b, 0x00, - 0x11, 0x01, 0x32, 0x9e, 0x5d, 0x00, 0x01, 0x01, - 0x32, 0xce, 0xcd, 0x2d, 0x00, +static const uint8_t unicode_script_ext_table[1278] = { + 0x80, 0x36, 0x00, 0x00, 0x10, 0x06, 0x14, 0x1b, + 0x24, 0x26, 0x29, 0x2a, 0x30, 0x2b, 0x2e, 0x33, + 0x4c, 0x53, 0x55, 0x74, 0x88, 0x81, 0x83, 0x00, + 0x00, 0x07, 0x0b, 0x1e, 0x21, 0x4c, 0x51, 0x9f, + 0xa6, 0x09, 0x00, 0x00, 0x02, 0x0e, 0x4c, 0x00, + 0x00, 0x02, 0x02, 0x0e, 0x4c, 0x00, 0x00, 0x00, + 0x02, 0x4c, 0x51, 0x08, 0x00, 0x00, 0x02, 0x4c, + 0x9f, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x4c, 0x25, + 0x00, 0x00, 0x08, 0x18, 0x1b, 0x1e, 0x2e, 0x4c, + 0x74, 0x91, 0x96, 0x00, 0x08, 0x18, 0x1e, 0x2e, + 0x4c, 0x7b, 0x91, 0x96, 0xa4, 0x00, 0x04, 0x18, + 0x1e, 0x4c, 0xa1, 0x00, 0x05, 0x2a, 0x4c, 0x91, + 0x93, 0x9f, 0x00, 0x0b, 0x15, 0x18, 0x1b, 0x1e, + 0x2b, 0x2e, 0x4c, 0x7b, 0x93, 0xa1, 0xa4, 0x00, + 0x06, 0x1b, 0x26, 0x2a, 0x2b, 0x41, 0x4c, 0x00, + 0x05, 0x1e, 0x2e, 0x4c, 0x74, 0xa1, 0x00, 0x09, + 0x1b, 0x24, 0x38, 0x4c, 0x74, 0x93, 0x96, 0xa1, + 0xa4, 0x00, 0x0b, 0x05, 0x1e, 0x24, 0x2b, 0x2e, + 0x38, 0x4c, 0x74, 0x93, 0x96, 0xa1, 0x00, 0x02, + 0x4c, 0xa1, 0x00, 0x03, 0x24, 0x4c, 0x93, 0x00, + 0x04, 0x18, 0x1e, 0x4c, 0x7b, 0x00, 0x03, 0x18, + 0x4c, 0x96, 0x00, 0x02, 0x4c, 0x91, 0x00, 0x02, + 0x28, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x4c, 0x91, + 0x00, 0x03, 0x1e, 0x4c, 0xa4, 0x00, 0x00, 0x00, + 0x04, 0x2e, 0x4c, 0x74, 0xa4, 0x0e, 0x00, 0x00, + 0x06, 0x18, 0x24, 0x41, 0x4c, 0x93, 0xa1, 0x00, + 0x04, 0x18, 0x24, 0x4c, 0x93, 0x00, 0x02, 0x4c, + 0x93, 0x06, 0x00, 0x00, 0x03, 0x4c, 0x91, 0x93, + 0x00, 0x02, 0x4c, 0x93, 0x00, 0x00, 0x00, 0x03, + 0x18, 0x4c, 0x93, 0x00, 0x07, 0x15, 0x18, 0x2b, + 0x4c, 0x91, 0x93, 0x9f, 0x0f, 0x00, 0x00, 0x01, + 0x2e, 0x01, 0x00, 0x00, 0x01, 0x2e, 0x11, 0x00, + 0x00, 0x02, 0x4c, 0x7b, 0x04, 0x00, 0x00, 0x03, + 0x15, 0x4c, 0xa4, 0x03, 0x00, 0x0c, 0x01, 0x4c, + 0x03, 0x00, 0x01, 0x02, 0x1b, 0x2e, 0x80, 0x8c, + 0x00, 0x00, 0x02, 0x1e, 0x74, 0x00, 0x02, 0x1e, + 0x2a, 0x01, 0x02, 0x1e, 0x4c, 0x00, 0x02, 0x1e, + 0x2a, 0x80, 0x80, 0x00, 0x00, 0x03, 0x05, 0x29, + 0x2a, 0x80, 0x01, 0x00, 0x00, 0x07, 0x04, 0x2c, + 0x6b, 0x35, 0x93, 0x9e, 0xad, 0x0d, 0x00, 0x00, + 0x07, 0x04, 0x2c, 0x6b, 0x35, 0x93, 0x9e, 0xad, + 0x00, 0x03, 0x04, 0x93, 0x9e, 0x01, 0x00, 0x00, + 0x08, 0x01, 0x04, 0x2c, 0x6b, 0x35, 0x93, 0x9e, + 0xad, 0x1f, 0x00, 0x00, 0x09, 0x01, 0x04, 0x57, + 0x58, 0x79, 0x82, 0x35, 0x8d, 0x93, 0x09, 0x00, + 0x0a, 0x02, 0x04, 0x93, 0x09, 0x00, 0x09, 0x03, + 0x04, 0x9e, 0xad, 0x05, 0x00, 0x00, 0x02, 0x04, + 0x93, 0x62, 0x00, 0x00, 0x02, 0x04, 0x35, 0x81, + 0xfb, 0x00, 0x00, 0x0f, 0x0b, 0x21, 0x2d, 0x2f, + 0x31, 0x40, 0x4c, 0x56, 0x68, 0x6a, 0x7a, 0x87, + 0x9b, 0x9d, 0xa2, 0x00, 0x0d, 0x0b, 0x21, 0x2d, + 0x2f, 0x31, 0x40, 0x4c, 0x56, 0x6a, 0x7a, 0x9b, + 0x9d, 0xa2, 0x10, 0x00, 0x00, 0x15, 0x0b, 0x21, + 0x23, 0x30, 0x5a, 0x2d, 0x2f, 0x31, 0x40, 0x55, + 0x56, 0x68, 0x70, 0x7a, 0x49, 0x8c, 0x92, 0x9a, + 0x9b, 0x9d, 0xa2, 0x00, 0x17, 0x0b, 0x21, 0x23, + 0x30, 0x5a, 0x2d, 0x2f, 0x32, 0x31, 0x40, 0x4e, + 0x55, 0x56, 0x68, 0x70, 0x7a, 0x49, 0x8c, 0x92, + 0x9a, 0x9b, 0x9d, 0xa2, 0x09, 0x04, 0x21, 0x23, + 0x3f, 0x55, 0x75, 0x00, 0x09, 0x03, 0x0b, 0x16, + 0x92, 0x75, 0x00, 0x09, 0x02, 0x31, 0x64, 0x75, + 0x00, 0x09, 0x02, 0x2f, 0x47, 0x80, 0x75, 0x00, + 0x0d, 0x02, 0x2d, 0x9b, 0x80, 0x71, 0x00, 0x09, + 0x03, 0x40, 0x68, 0xa7, 0x82, 0xcf, 0x00, 0x09, + 0x03, 0x16, 0x65, 0x96, 0x80, 0x30, 0x00, 0x00, + 0x03, 0x29, 0x2a, 0x4c, 0x85, 0x6e, 0x00, 0x02, + 0x01, 0x84, 0x46, 0x00, 0x01, 0x04, 0x12, 0x36, + 0x95, 0x94, 0x80, 0x4a, 0x00, 0x01, 0x02, 0x62, + 0x80, 0x00, 0x00, 0x00, 0x02, 0x62, 0x80, 0x84, + 0x49, 0x00, 0x00, 0x04, 0x0b, 0x21, 0x2d, 0x40, + 0x00, 0x01, 0x21, 0x00, 0x04, 0x0b, 0x21, 0x2d, + 0x40, 0x00, 0x03, 0x21, 0x2d, 0x40, 0x00, 0x01, + 0x21, 0x00, 0x05, 0x0b, 0x21, 0x6a, 0x9d, 0xa2, + 0x00, 0x03, 0x0b, 0x21, 0x9d, 0x00, 0x03, 0x21, + 0x6a, 0x87, 0x00, 0x04, 0x0b, 0x21, 0x6a, 0x9d, + 0x00, 0x02, 0x21, 0x87, 0x00, 0x06, 0x21, 0x40, + 0x56, 0x7a, 0x9b, 0x9d, 0x00, 0x01, 0x21, 0x01, + 0x02, 0x21, 0x87, 0x01, 0x01, 0x21, 0x00, 0x02, + 0x21, 0x87, 0x00, 0x02, 0x0b, 0x21, 0x00, 0x03, + 0x21, 0x6a, 0xa2, 0x05, 0x01, 0x21, 0x00, 0x03, + 0x21, 0x68, 0x6a, 0x00, 0x03, 0x0b, 0x21, 0x87, + 0x00, 0x02, 0x21, 0x6a, 0x00, 0x01, 0x21, 0x00, + 0x04, 0x0b, 0x21, 0x6a, 0x87, 0x03, 0x01, 0x21, + 0x00, 0x0b, 0x0b, 0x21, 0x2d, 0x40, 0x56, 0x68, + 0x7a, 0x8c, 0x9d, 0xa2, 0xa7, 0x00, 0x02, 0x21, + 0x2d, 0x00, 0x04, 0x21, 0x2d, 0x40, 0xa7, 0x01, + 0x02, 0x0b, 0x21, 0x00, 0x01, 0x0b, 0x01, 0x02, + 0x21, 0x2d, 0x00, 0x01, 0x68, 0x80, 0x44, 0x00, + 0x01, 0x01, 0x2e, 0x35, 0x00, 0x00, 0x03, 0x1e, + 0x4c, 0x93, 0x00, 0x00, 0x00, 0x01, 0x93, 0x81, + 0xb3, 0x00, 0x00, 0x03, 0x4c, 0x62, 0x80, 0x1e, + 0x00, 0x00, 0x02, 0x01, 0x04, 0x09, 0x00, 0x00, + 0x06, 0x14, 0x29, 0x2a, 0x71, 0x52, 0x78, 0x01, + 0x00, 0x00, 0x04, 0x14, 0x2e, 0x71, 0x5f, 0x80, + 0x11, 0x00, 0x00, 0x03, 0x21, 0x2d, 0x4c, 0x8c, + 0xa5, 0x00, 0x00, 0x02, 0x1b, 0x4c, 0x17, 0x00, + 0x00, 0x02, 0x06, 0x78, 0x00, 0x07, 0x06, 0x14, + 0x29, 0x71, 0x3f, 0x53, 0x85, 0x09, 0x00, 0x00, + 0x01, 0x24, 0x03, 0x00, 0x00, 0x03, 0x01, 0x04, + 0x71, 0x00, 0x00, 0x00, 0x02, 0x1e, 0x2a, 0x81, + 0x2b, 0x00, 0x0f, 0x02, 0x33, 0x9c, 0x00, 0x00, + 0x00, 0x07, 0x0e, 0x34, 0x33, 0x39, 0x41, 0x62, + 0xae, 0x00, 0x08, 0x0e, 0x34, 0x33, 0x39, 0x41, + 0x62, 0x80, 0xae, 0x00, 0x05, 0x0e, 0x34, 0x33, + 0x39, 0x41, 0x01, 0x00, 0x00, 0x01, 0x33, 0x00, + 0x00, 0x01, 0x08, 0x0e, 0x34, 0x33, 0x39, 0x41, + 0x62, 0xa0, 0xae, 0x01, 0x09, 0x0e, 0x34, 0x33, + 0x39, 0x41, 0x51, 0x62, 0xa0, 0xae, 0x05, 0x06, + 0x0e, 0x34, 0x33, 0x39, 0x41, 0xae, 0x00, 0x00, + 0x00, 0x05, 0x0e, 0x34, 0x33, 0x39, 0x41, 0x07, + 0x06, 0x0e, 0x34, 0x33, 0x39, 0x41, 0xae, 0x03, + 0x05, 0x0e, 0x34, 0x33, 0x39, 0x41, 0x09, 0x00, + 0x03, 0x02, 0x0e, 0x33, 0x01, 0x00, 0x00, 0x05, + 0x0e, 0x34, 0x33, 0x39, 0x41, 0x04, 0x02, 0x39, + 0x41, 0x00, 0x00, 0x00, 0x05, 0x0e, 0x34, 0x33, + 0x39, 0x41, 0x03, 0x00, 0x01, 0x03, 0x33, 0x39, + 0x41, 0x01, 0x01, 0x33, 0x58, 0x00, 0x03, 0x02, + 0x39, 0x41, 0x02, 0x00, 0x00, 0x02, 0x39, 0x41, + 0x59, 0x00, 0x00, 0x06, 0x0e, 0x34, 0x33, 0x39, + 0x41, 0xae, 0x00, 0x02, 0x39, 0x41, 0x80, 0x12, + 0x00, 0x0f, 0x01, 0x33, 0x1f, 0x00, 0x25, 0x01, + 0x33, 0x08, 0x00, 0x00, 0x02, 0x33, 0x9c, 0x2f, + 0x00, 0x27, 0x01, 0x33, 0x37, 0x00, 0x30, 0x01, + 0x33, 0x0e, 0x00, 0x0b, 0x01, 0x33, 0x32, 0x00, + 0x00, 0x01, 0x33, 0x57, 0x00, 0x18, 0x01, 0x33, + 0x09, 0x00, 0x04, 0x01, 0x33, 0x5f, 0x00, 0x1e, + 0x01, 0x33, 0xc0, 0x31, 0xef, 0x00, 0x00, 0x02, + 0x1e, 0x2a, 0x80, 0x0f, 0x00, 0x07, 0x02, 0x33, + 0x4c, 0x80, 0xa7, 0x00, 0x02, 0x10, 0x21, 0x23, + 0x2f, 0x31, 0x47, 0x40, 0x3f, 0x55, 0x56, 0x61, + 0x68, 0x87, 0x49, 0x9a, 0xa2, 0xa7, 0x02, 0x0f, + 0x21, 0x23, 0x2f, 0x31, 0x47, 0x40, 0x3f, 0x55, + 0x61, 0x68, 0x87, 0x49, 0x9a, 0xa2, 0xa7, 0x01, + 0x0b, 0x21, 0x23, 0x2f, 0x31, 0x47, 0x3f, 0x55, + 0x61, 0x49, 0x9a, 0xa2, 0x00, 0x0c, 0x21, 0x23, + 0x2f, 0x31, 0x47, 0x3f, 0x55, 0x61, 0x87, 0x49, + 0x9a, 0xa2, 0x00, 0x0b, 0x21, 0x23, 0x2f, 0x31, + 0x47, 0x3f, 0x55, 0x61, 0x49, 0x9a, 0xa2, 0x80, + 0x36, 0x00, 0x00, 0x03, 0x0b, 0x21, 0xa7, 0x00, + 0x00, 0x00, 0x02, 0x21, 0x9b, 0x39, 0x00, 0x00, + 0x03, 0x44, 0x4c, 0x65, 0x80, 0x1f, 0x00, 0x00, + 0x02, 0x11, 0x3e, 0xc0, 0x12, 0xed, 0x00, 0x01, + 0x02, 0x04, 0x6b, 0x80, 0x31, 0x00, 0x00, 0x02, + 0x04, 0x9e, 0x09, 0x00, 0x00, 0x02, 0x04, 0x9e, + 0x46, 0x00, 0x01, 0x05, 0x0e, 0x34, 0x33, 0x39, + 0x41, 0x80, 0x99, 0x00, 0x04, 0x06, 0x0e, 0x34, + 0x33, 0x39, 0x41, 0xae, 0x09, 0x00, 0x00, 0x02, + 0x39, 0x41, 0x2c, 0x00, 0x01, 0x02, 0x39, 0x41, + 0x80, 0xdf, 0x00, 0x01, 0x03, 0x1f, 0x1d, 0x50, + 0x00, 0x02, 0x1d, 0x50, 0x03, 0x00, 0x2c, 0x03, + 0x1d, 0x4f, 0x50, 0x02, 0x00, 0x08, 0x02, 0x1d, + 0x50, 0x81, 0x1f, 0x00, 0x1b, 0x02, 0x04, 0x1b, + 0x87, 0x75, 0x00, 0x00, 0x02, 0x58, 0x79, 0x87, + 0x8d, 0x00, 0x00, 0x02, 0x2d, 0x9b, 0x00, 0x00, + 0x00, 0x02, 0x2d, 0x9b, 0x36, 0x00, 0x01, 0x02, + 0x2d, 0x9b, 0x8c, 0x12, 0x00, 0x01, 0x02, 0x2d, + 0x9b, 0x00, 0x00, 0x00, 0x02, 0x2d, 0x9b, 0xc0, + 0x5c, 0x4b, 0x00, 0x03, 0x01, 0x24, 0x96, 0x3b, + 0x00, 0x11, 0x01, 0x33, 0x9e, 0x5d, 0x00, 0x01, + 0x01, 0x33, 0xce, 0xcd, 0x2d, 0x00, }; static const uint8_t unicode_prop_Hyphen_table[28] = { @@ -3788,7 +3821,7 @@ static const uint8_t unicode_prop_Other_Math_table[200] = { 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, }; -static const uint8_t unicode_prop_Other_Alphabetic_table[443] = { +static const uint8_t unicode_prop_Other_Alphabetic_table[452] = { 0x43, 0x44, 0x80, 0x9c, 0x8c, 0x42, 0x3f, 0x8d, 0x00, 0x01, 0x01, 0x00, 0xc7, 0x8a, 0xaf, 0x8c, 0x06, 0x8f, 0x80, 0xe4, 0x33, 0x19, 0x0b, 0x80, @@ -3824,8 +3857,8 @@ static const uint8_t unicode_prop_Other_Alphabetic_table[443] = { 0xb1, 0x00, 0x11, 0x0c, 0x80, 0xab, 0x24, 0x80, 0x40, 0xec, 0x87, 0x60, 0x4f, 0x32, 0x80, 0x48, 0x56, 0x84, 0x46, 0x85, 0x10, 0x0c, 0x83, 0x43, - 0x13, 0x83, 0xc0, 0x80, 0x41, 0x40, 0x81, 0xce, - 0x80, 0x41, 0x02, 0x82, 0xb4, 0x8d, 0xac, 0x81, + 0x13, 0x83, 0xc0, 0x80, 0x41, 0x40, 0x81, 0xcc, + 0x82, 0x41, 0x02, 0x82, 0xb4, 0x8d, 0xac, 0x81, 0x8a, 0x82, 0xac, 0x88, 0x88, 0x80, 0xbc, 0x82, 0xa3, 0x8b, 0x91, 0x81, 0xb8, 0x82, 0xaf, 0x8c, 0x8d, 0x81, 0xdb, 0x88, 0x08, 0x28, 0x08, 0x40, @@ -3836,27 +3869,28 @@ static const uint8_t unicode_prop_Other_Alphabetic_table[443] = { 0xe9, 0x8a, 0xe6, 0x8d, 0x41, 0x00, 0x8c, 0x40, 0xf6, 0x28, 0x09, 0x0a, 0x00, 0x80, 0x40, 0x8d, 0x31, 0x2b, 0x80, 0x9b, 0x89, 0xa9, 0x20, 0x83, - 0x91, 0x8a, 0xad, 0x8d, 0x41, 0x96, 0x38, 0x86, - 0xd2, 0x95, 0x80, 0x8d, 0xf9, 0x2a, 0x00, 0x08, - 0x10, 0x02, 0x80, 0xc1, 0x20, 0x08, 0x83, 0x41, - 0x5b, 0x83, 0x88, 0x08, 0x80, 0xaf, 0x32, 0x82, - 0x60, 0x41, 0xdc, 0x90, 0x4e, 0x1f, 0x00, 0xb6, - 0x33, 0xdc, 0x81, 0x60, 0x4c, 0xab, 0x80, 0x60, - 0x23, 0x60, 0x30, 0x90, 0x0e, 0x01, 0x04, 0xe3, - 0x80, 0x48, 0xb6, 0x80, 0x47, 0xe7, 0x99, 0x85, - 0x99, 0x85, 0x99, + 0x91, 0x8a, 0xad, 0x8d, 0x40, 0xc7, 0x87, 0x40, + 0xc6, 0x38, 0x86, 0xd2, 0x95, 0x80, 0x8d, 0xf9, + 0x2a, 0x00, 0x08, 0x10, 0x02, 0x80, 0xc1, 0x20, + 0x08, 0x83, 0x41, 0x5b, 0x83, 0x88, 0x08, 0x80, + 0xaf, 0x32, 0x82, 0x60, 0x41, 0xdc, 0x90, 0x4e, + 0x1f, 0x00, 0xb6, 0x33, 0xdc, 0x81, 0x60, 0x4c, + 0xab, 0x80, 0x60, 0x23, 0x60, 0x30, 0x90, 0x0e, + 0x01, 0x04, 0xe3, 0x80, 0x46, 0x52, 0x01, 0x06, + 0x0c, 0x80, 0x42, 0x50, 0x80, 0x47, 0xe7, 0x99, + 0x85, 0x99, 0x85, 0x99, }; -static const uint8_t unicode_prop_Other_Lowercase_table[69] = { +static const uint8_t unicode_prop_Other_Lowercase_table[68] = { 0x40, 0xa9, 0x80, 0x8e, 0x80, 0x41, 0xf4, 0x88, 0x31, 0x9d, 0x84, 0xdf, 0x80, 0xb3, 0x80, 0x4d, 0x80, 0x80, 0x4c, 0x2e, 0xbe, 0x8c, 0x80, 0xa1, 0xa4, 0x42, 0xb0, 0x80, 0x8c, 0x80, 0x8f, 0x8c, 0x40, 0xd2, 0x8f, 0x43, 0x4f, 0x99, 0x47, 0x91, 0x81, 0x60, 0x7a, 0x1d, 0x81, 0x40, 0xd1, 0x80, - 0x40, 0x80, 0x12, 0x81, 0x43, 0x61, 0x83, 0x88, - 0x80, 0x60, 0x5c, 0x15, 0x01, 0x10, 0xa9, 0x80, - 0x88, 0x60, 0xd8, 0x74, 0xbd, + 0xff, 0x1a, 0x81, 0x43, 0x61, 0x83, 0x88, 0x80, + 0x60, 0x5c, 0x15, 0x01, 0x10, 0xa9, 0x80, 0x88, + 0x60, 0xd8, 0x74, 0xbd, }; static const uint8_t unicode_prop_Other_Uppercase_table[15] = { @@ -3931,7 +3965,7 @@ static const uint8_t unicode_prop_Changes_When_Casefolded1_table[29] = { 0x89, 0x10, 0x81, 0x8d, 0x80, }; -static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[450] = { +static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[449] = { 0x40, 0x9f, 0x06, 0x00, 0x01, 0x00, 0x01, 0x12, 0x10, 0x82, 0xf3, 0x80, 0x8b, 0x80, 0x40, 0x84, 0x01, 0x01, 0x80, 0xa2, 0x01, 0x80, 0x40, 0xbb, @@ -3963,32 +3997,32 @@ static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[450] = { 0xa9, 0x80, 0xb4, 0x00, 0x82, 0xdf, 0x09, 0x80, 0xde, 0x80, 0xb0, 0xdd, 0x82, 0x8d, 0xdf, 0x9e, 0x80, 0xa7, 0x87, 0xae, 0x80, 0x41, 0x7f, 0x60, - 0x72, 0x9b, 0x81, 0x40, 0xd1, 0x80, 0x40, 0x80, - 0x12, 0x81, 0x43, 0x61, 0x83, 0x88, 0x80, 0x60, - 0x4d, 0x95, 0x41, 0x0d, 0x08, 0x00, 0x81, 0x89, - 0x00, 0x00, 0x09, 0x82, 0xc3, 0x81, 0xe9, 0xc2, - 0x00, 0x97, 0x04, 0x00, 0x01, 0x01, 0x80, 0xeb, - 0xa0, 0x41, 0x6a, 0x91, 0xbf, 0x81, 0xb5, 0xa7, - 0x8c, 0x82, 0x99, 0x95, 0x94, 0x81, 0x8b, 0x80, - 0x92, 0x03, 0x1a, 0x00, 0x80, 0x40, 0x86, 0x08, - 0x80, 0x9f, 0x99, 0x40, 0x83, 0x15, 0x0d, 0x0d, - 0x0a, 0x16, 0x06, 0x80, 0x88, 0x47, 0x87, 0x20, - 0xa9, 0x80, 0x88, 0x60, 0xb4, 0xe4, 0x83, 0x50, - 0x31, 0xa3, 0x44, 0x63, 0x86, 0x8d, 0x87, 0xbf, - 0x85, 0x42, 0x3e, 0xd4, 0x80, 0xc6, 0x01, 0x08, - 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, - 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, - 0x16, 0x80, 0x41, 0x53, 0x81, 0x41, 0x23, 0x81, - 0xb1, 0x48, 0x2f, 0xbd, 0x4d, 0x91, 0x18, 0x9a, - 0x01, 0x00, 0x08, 0x80, 0x89, 0x03, 0x00, 0x00, - 0x28, 0x18, 0x00, 0x00, 0x02, 0x01, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x06, - 0x03, 0x03, 0x00, 0x80, 0x89, 0x80, 0x90, 0x22, - 0x04, 0x80, 0x90, 0x42, 0x43, 0x8a, 0x84, 0x9e, - 0x80, 0x9f, 0x99, 0x82, 0xa2, 0x80, 0xee, 0x82, - 0x8c, 0xab, 0x83, 0x88, 0x31, 0x49, 0x9d, 0x89, - 0x60, 0xfc, 0x05, 0x42, 0x1d, 0x6b, 0x05, 0xe1, - 0x4f, 0xff, + 0x72, 0x9b, 0x81, 0x40, 0xd1, 0x80, 0xff, 0x1a, + 0x81, 0x43, 0x61, 0x83, 0x88, 0x80, 0x60, 0x4d, + 0x95, 0x41, 0x0d, 0x08, 0x00, 0x81, 0x89, 0x00, + 0x00, 0x09, 0x82, 0xc3, 0x81, 0xe9, 0xc2, 0x00, + 0x97, 0x04, 0x00, 0x01, 0x01, 0x80, 0xeb, 0xa0, + 0x41, 0x6a, 0x91, 0xbf, 0x81, 0xb5, 0xa7, 0x8c, + 0x82, 0x99, 0x95, 0x94, 0x81, 0x8b, 0x80, 0x92, + 0x03, 0x1a, 0x00, 0x80, 0x40, 0x86, 0x08, 0x80, + 0x9f, 0x99, 0x40, 0x83, 0x15, 0x0d, 0x0d, 0x0a, + 0x16, 0x06, 0x80, 0x88, 0x47, 0x87, 0x20, 0xa9, + 0x80, 0x88, 0x60, 0xb4, 0xe4, 0x83, 0x50, 0x31, + 0xa3, 0x44, 0x63, 0x86, 0x8d, 0x87, 0xbf, 0x85, + 0x42, 0x3e, 0xd4, 0x80, 0xc6, 0x01, 0x08, 0x09, + 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, 0x03, + 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, 0x16, + 0x80, 0x41, 0x53, 0x81, 0x41, 0x23, 0x81, 0xb1, + 0x48, 0x2f, 0xbd, 0x4d, 0x91, 0x18, 0x9a, 0x01, + 0x00, 0x08, 0x80, 0x89, 0x03, 0x00, 0x00, 0x28, + 0x18, 0x00, 0x00, 0x02, 0x01, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x06, 0x03, + 0x03, 0x00, 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, + 0x80, 0x90, 0x42, 0x43, 0x8a, 0x84, 0x9e, 0x80, + 0x9f, 0x99, 0x82, 0xa2, 0x80, 0xee, 0x82, 0x8c, + 0xab, 0x83, 0x88, 0x31, 0x49, 0x9d, 0x89, 0x60, + 0xfc, 0x05, 0x42, 0x1d, 0x6b, 0x05, 0xe1, 0x4f, + 0xff, }; static const uint8_t unicode_prop_ASCII_Hex_Digit_table[5] = { @@ -4017,65 +4051,66 @@ static const uint8_t unicode_prop_Deprecated_table[23] = { 0x42, 0xb8, 0x81, 0x6d, 0xdc, 0xd5, 0x80, }; -static const uint8_t unicode_prop_Diacritic_table[438] = { +static const uint8_t unicode_prop_Diacritic_table[447] = { 0xdd, 0x00, 0x80, 0xc6, 0x05, 0x03, 0x01, 0x81, 0x41, 0xf6, 0x40, 0x9e, 0x07, 0x25, 0x90, 0x0b, 0x80, 0x88, 0x81, 0x40, 0xfc, 0x84, 0x40, 0xd0, - 0x80, 0xb6, 0x90, 0x80, 0x9a, 0x00, 0x01, 0x00, - 0x40, 0x85, 0x3b, 0x81, 0x40, 0x85, 0x0b, 0x0a, - 0x82, 0xc2, 0x9a, 0xda, 0x8a, 0xb9, 0x8a, 0xa1, - 0x81, 0xfd, 0x87, 0xa8, 0x89, 0x8f, 0x9b, 0xbc, - 0x80, 0x8f, 0x02, 0x83, 0x9b, 0x80, 0xc9, 0x80, - 0x8f, 0x80, 0xed, 0x80, 0x8f, 0x80, 0xed, 0x80, - 0x8f, 0x80, 0xae, 0x82, 0xbb, 0x80, 0x8f, 0x06, - 0x80, 0xf6, 0x80, 0xed, 0x80, 0x8f, 0x80, 0xed, - 0x80, 0x8f, 0x80, 0xec, 0x81, 0x8f, 0x80, 0xfb, - 0x80, 0xee, 0x80, 0x8b, 0x28, 0x80, 0xea, 0x80, - 0x8c, 0x84, 0xca, 0x81, 0x9a, 0x00, 0x00, 0x03, - 0x81, 0xc1, 0x10, 0x81, 0xbd, 0x80, 0xef, 0x00, - 0x81, 0xa7, 0x0b, 0x84, 0x98, 0x30, 0x80, 0x89, - 0x81, 0x42, 0xc0, 0x82, 0x43, 0xb3, 0x81, 0x9d, - 0x80, 0x40, 0x93, 0x8a, 0x88, 0x80, 0x41, 0x5a, - 0x82, 0x41, 0x23, 0x80, 0x93, 0x39, 0x80, 0xaf, - 0x8e, 0x81, 0x8a, 0xe7, 0x80, 0x8e, 0x80, 0xa5, - 0x88, 0xb5, 0x81, 0xb9, 0x80, 0x8a, 0x81, 0xc1, - 0x81, 0xbf, 0x85, 0xd1, 0x98, 0x18, 0x28, 0x0a, - 0xb1, 0xbe, 0xd8, 0x8b, 0xa4, 0x8a, 0x41, 0xbc, - 0x00, 0x82, 0x8a, 0x82, 0x8c, 0x82, 0x8c, 0x82, - 0x8c, 0x81, 0x4c, 0xef, 0x82, 0x41, 0x3c, 0x80, - 0x41, 0xf9, 0x85, 0xe8, 0x83, 0xde, 0x80, 0x60, - 0x75, 0x71, 0x80, 0x8b, 0x08, 0x80, 0x9b, 0x81, - 0xd1, 0x81, 0x8d, 0xa1, 0xe5, 0x82, 0xec, 0x81, - 0x8b, 0x80, 0xa4, 0x80, 0x40, 0x96, 0x80, 0x9a, - 0x91, 0xb8, 0x83, 0xa3, 0x80, 0xde, 0x80, 0x8b, - 0x80, 0xa3, 0x80, 0x40, 0x94, 0x82, 0xc0, 0x83, - 0xb2, 0x80, 0xe3, 0x84, 0x88, 0x82, 0xff, 0x81, - 0x60, 0x4f, 0x2f, 0x80, 0x43, 0x00, 0x8f, 0x41, - 0x0d, 0x00, 0x80, 0xae, 0x80, 0xac, 0x81, 0xc2, - 0x80, 0x42, 0xfb, 0x80, 0x44, 0x9e, 0x28, 0xa9, - 0x80, 0x88, 0x42, 0x7c, 0x13, 0x80, 0x40, 0xa4, - 0x81, 0x42, 0x3a, 0x85, 0xa5, 0x80, 0x99, 0x84, - 0x41, 0x8e, 0x82, 0xc5, 0x8a, 0xb0, 0x83, 0x40, - 0xbf, 0x80, 0xa8, 0x80, 0xc7, 0x81, 0xf7, 0x81, - 0xbd, 0x80, 0xcb, 0x80, 0x88, 0x82, 0xe7, 0x81, - 0x40, 0xb1, 0x81, 0xcf, 0x81, 0x8f, 0x80, 0x97, - 0x32, 0x84, 0xd8, 0x10, 0x81, 0x8c, 0x81, 0xde, - 0x02, 0x80, 0xfa, 0x81, 0x40, 0xfa, 0x81, 0xfd, - 0x80, 0xf5, 0x81, 0xf2, 0x80, 0x41, 0x0c, 0x81, - 0x41, 0x01, 0x0b, 0x80, 0x40, 0x9b, 0x80, 0xd2, - 0x80, 0x91, 0x80, 0xd0, 0x80, 0x41, 0xa4, 0x80, - 0x41, 0x01, 0x00, 0x81, 0xd0, 0x80, 0x41, 0xa8, - 0x81, 0x96, 0x80, 0x54, 0xeb, 0x8e, 0x60, 0x2c, - 0xd8, 0x80, 0x49, 0xbf, 0x84, 0xba, 0x86, 0x42, - 0x33, 0x81, 0x42, 0x21, 0x90, 0xcf, 0x81, 0x60, - 0x3f, 0xfd, 0x18, 0x30, 0x81, 0x5f, 0x00, 0xad, - 0x81, 0x96, 0x42, 0x1f, 0x12, 0x2f, 0x39, 0x86, - 0x9d, 0x83, 0x4e, 0x81, 0xbd, 0x40, 0xc1, 0x86, - 0x41, 0x76, 0x80, 0xbc, 0x83, 0x42, 0xfd, 0x81, - 0x42, 0xdf, 0x86, 0xec, 0x10, 0x82, + 0x80, 0xb6, 0xac, 0x00, 0x01, 0x01, 0x00, 0x40, + 0x82, 0x3b, 0x81, 0x40, 0x85, 0x0b, 0x0a, 0x82, + 0xc2, 0x9a, 0xda, 0x8a, 0xb9, 0x8a, 0xa1, 0x81, + 0xfd, 0x87, 0xa8, 0x89, 0x8f, 0x9b, 0xbc, 0x80, + 0x8f, 0x02, 0x83, 0x9b, 0x80, 0xc9, 0x80, 0x8f, + 0x80, 0xed, 0x80, 0x8f, 0x80, 0xed, 0x80, 0x8f, + 0x80, 0xae, 0x82, 0xbb, 0x80, 0x8f, 0x06, 0x80, + 0xf6, 0x80, 0xed, 0x80, 0x8f, 0x80, 0xed, 0x80, + 0x8f, 0x80, 0xec, 0x81, 0x8f, 0x80, 0xfb, 0x80, + 0xee, 0x80, 0x8b, 0x28, 0x80, 0xea, 0x80, 0x8c, + 0x84, 0xca, 0x81, 0x9a, 0x00, 0x00, 0x03, 0x81, + 0xc1, 0x10, 0x81, 0xbd, 0x80, 0xef, 0x00, 0x81, + 0xa7, 0x0b, 0x84, 0x98, 0x30, 0x80, 0x89, 0x81, + 0x42, 0xc0, 0x82, 0x43, 0xb3, 0x81, 0x9d, 0x80, + 0x40, 0x93, 0x8a, 0x88, 0x80, 0x41, 0x5a, 0x82, + 0x41, 0x23, 0x80, 0x93, 0x39, 0x80, 0xaf, 0x8e, + 0x81, 0x8a, 0x82, 0x8e, 0x81, 0x8b, 0xc7, 0x80, + 0x8e, 0x80, 0xa5, 0x88, 0xb5, 0x81, 0xb9, 0x80, + 0x8a, 0x81, 0xc1, 0x81, 0xbf, 0x85, 0xd1, 0x98, + 0x18, 0x28, 0x0a, 0xb1, 0xbe, 0xaf, 0xa3, 0x84, + 0x8b, 0xa4, 0x8a, 0x41, 0xbc, 0x00, 0x82, 0x8a, + 0x82, 0x8c, 0x82, 0x8c, 0x82, 0x8c, 0x81, 0x4c, + 0xef, 0x82, 0x41, 0x3c, 0x80, 0x41, 0xf9, 0x85, + 0xe8, 0x83, 0xde, 0x80, 0x60, 0x75, 0x71, 0x80, + 0x8b, 0x08, 0x80, 0x9b, 0x81, 0xd1, 0x81, 0x8d, + 0xa1, 0xe5, 0x82, 0xe5, 0x05, 0x81, 0x8b, 0x80, + 0xa4, 0x80, 0x40, 0x96, 0x80, 0x9a, 0x91, 0xb8, + 0x83, 0xa3, 0x80, 0xde, 0x80, 0x8b, 0x80, 0xa3, + 0x80, 0x40, 0x94, 0x82, 0xc0, 0x83, 0xb2, 0x80, + 0xe3, 0x84, 0x88, 0x82, 0xff, 0x81, 0x60, 0x4f, + 0x2f, 0x80, 0x43, 0x00, 0x8f, 0x41, 0x0d, 0x00, + 0x80, 0xae, 0x80, 0xac, 0x81, 0xc2, 0x80, 0x42, + 0xfb, 0x80, 0x44, 0x9e, 0x28, 0xa9, 0x80, 0x88, + 0x42, 0x7c, 0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, + 0x3a, 0x85, 0xa5, 0x80, 0x99, 0x84, 0x41, 0x8b, + 0x01, 0x82, 0xc5, 0x8a, 0xb0, 0x83, 0x40, 0xbf, + 0x80, 0xa8, 0x80, 0xc7, 0x81, 0xf7, 0x81, 0xbd, + 0x80, 0xcb, 0x80, 0x88, 0x82, 0xe7, 0x81, 0x40, + 0xb1, 0x81, 0xcf, 0x81, 0x8f, 0x80, 0x97, 0x32, + 0x84, 0xd8, 0x10, 0x81, 0x8c, 0x81, 0xde, 0x02, + 0x80, 0xfa, 0x81, 0x40, 0xfa, 0x81, 0xfd, 0x80, + 0xf5, 0x81, 0xf2, 0x80, 0x41, 0x0c, 0x81, 0x41, + 0x01, 0x0b, 0x80, 0x40, 0x9b, 0x80, 0xd2, 0x80, + 0x91, 0x80, 0xd0, 0x80, 0x41, 0xa4, 0x80, 0x41, + 0x01, 0x00, 0x81, 0xd0, 0x80, 0xc0, 0x80, 0x41, + 0x66, 0x81, 0x96, 0x80, 0x54, 0xeb, 0x8e, 0x60, + 0x2c, 0xd8, 0x80, 0x49, 0xbf, 0x84, 0xba, 0x86, + 0x42, 0x33, 0x81, 0x42, 0x21, 0x90, 0xcf, 0x81, + 0x60, 0x3f, 0xfd, 0x18, 0x30, 0x81, 0x5f, 0x00, + 0xad, 0x81, 0x96, 0x42, 0x1f, 0x12, 0x2f, 0x39, + 0x86, 0x9d, 0x83, 0x4e, 0x81, 0xbd, 0x40, 0xc1, + 0x86, 0x41, 0x76, 0x80, 0xbc, 0x83, 0x42, 0xfd, + 0x81, 0x42, 0xdf, 0x86, 0xec, 0x10, 0x82, }; -static const uint8_t unicode_prop_Extender_table[111] = { +static const uint8_t unicode_prop_Extender_table[116] = { 0x40, 0xb6, 0x80, 0x42, 0x17, 0x81, 0x43, 0x6d, 0x80, 0x41, 0xb8, 0x80, 0x42, 0x75, 0x80, 0x40, 0x88, 0x80, 0xd8, 0x80, 0x42, 0xef, 0x80, 0xfe, @@ -4087,9 +4122,10 @@ static const uint8_t unicode_prop_Extender_table[111] = { 0x94, 0x81, 0x60, 0x54, 0x7a, 0x80, 0x48, 0x0f, 0x81, 0x45, 0xca, 0x80, 0x9a, 0x03, 0x80, 0x44, 0xc6, 0x80, 0x41, 0x24, 0x80, 0xf3, 0x81, 0x41, - 0xf1, 0x82, 0x44, 0xce, 0x80, 0x60, 0x50, 0xa8, - 0x81, 0x44, 0x9b, 0x08, 0x80, 0x60, 0x71, 0x57, - 0x81, 0x44, 0xb0, 0x80, 0x43, 0x53, 0x82, + 0xf1, 0x82, 0x44, 0xce, 0x80, 0x43, 0x3f, 0x80, + 0x60, 0x4d, 0x67, 0x81, 0x44, 0x9b, 0x08, 0x80, + 0x8d, 0x81, 0x60, 0x71, 0x47, 0x81, 0x44, 0xb0, + 0x80, 0x43, 0x53, 0x82, }; static const uint8_t unicode_prop_Hex_Digit_table[12] = { @@ -4109,16 +4145,16 @@ static const uint8_t unicode_prop_IDS_Trinary_Operator_table[4] = { 0x60, 0x2f, 0xf1, 0x81, }; -static const uint8_t unicode_prop_Ideographic_table[72] = { +static const uint8_t unicode_prop_Ideographic_table[71] = { 0x60, 0x30, 0x05, 0x81, 0x98, 0x88, 0x8d, 0x82, 0x43, 0xc4, 0x59, 0xbf, 0xbf, 0x60, 0x51, 0xff, 0x60, 0x58, 0xff, 0x41, 0x6d, 0x81, 0xe9, 0x60, - 0x75, 0x09, 0x80, 0x9a, 0x57, 0xf7, 0x87, 0x44, - 0xd5, 0xa8, 0x89, 0x60, 0x24, 0x66, 0x41, 0x8b, - 0x60, 0x4d, 0x03, 0x60, 0xa6, 0xdf, 0x9f, 0x50, - 0x39, 0x85, 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d, - 0x5d, 0x30, 0x8e, 0x42, 0x6d, 0x49, 0xa1, 0x42, - 0x1d, 0x45, 0xe1, 0x53, 0x4a, 0x84, 0x50, 0x5f, + 0x75, 0x09, 0x80, 0x8c, 0x84, 0x88, 0x5c, 0xd5, + 0xa8, 0x9f, 0xe0, 0xf2, 0x60, 0x23, 0x7c, 0x41, + 0x8b, 0x60, 0x4d, 0x03, 0x60, 0xa6, 0xdf, 0x9f, + 0x51, 0x1d, 0x81, 0x56, 0x8d, 0x81, 0x5d, 0x30, + 0x8e, 0x42, 0x6d, 0x49, 0xa1, 0x42, 0x1d, 0x45, + 0xe1, 0x53, 0x4a, 0x84, 0x60, 0x21, 0x29, }; static const uint8_t unicode_prop_Join_Control_table[4] = { @@ -4258,13 +4294,13 @@ static const uint8_t unicode_prop_Terminal_Punctuation_table[264] = { 0x81, 0x60, 0x4e, 0x05, 0x80, 0x5d, 0xe6, 0x83, }; -static const uint8_t unicode_prop_Unified_Ideograph_table[48] = { +static const uint8_t unicode_prop_Unified_Ideograph_table[46] = { 0x60, 0x33, 0xff, 0x59, 0xbf, 0xbf, 0x60, 0x51, 0xff, 0x60, 0x5a, 0x0d, 0x08, 0x00, 0x81, 0x89, 0x00, 0x00, 0x09, 0x82, 0x61, 0x05, 0xd5, 0x60, - 0xa6, 0xdf, 0x9f, 0x50, 0x39, 0x85, 0x40, 0xdd, - 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x8e, 0x42, - 0x6d, 0x51, 0xa1, 0x53, 0x4a, 0x84, 0x50, 0x5f, + 0xa6, 0xdf, 0x9f, 0x51, 0x1d, 0x81, 0x56, 0x8d, + 0x81, 0x5d, 0x30, 0x8e, 0x42, 0x6d, 0x51, 0xa1, + 0x53, 0x4a, 0x84, 0x60, 0x21, 0x29, }; static const uint8_t unicode_prop_Variation_Selector_table[13] = { @@ -4297,7 +4333,7 @@ static const uint8_t unicode_prop_Bidi_Mirrored_table[173] = { 0x80, 0xb8, 0x80, 0xb8, 0x80, }; -static const uint8_t unicode_prop_Emoji_table[238] = { +static const uint8_t unicode_prop_Emoji_table[239] = { 0xa2, 0x05, 0x04, 0x89, 0xee, 0x03, 0x80, 0x5f, 0x8c, 0x80, 0x8b, 0x80, 0x40, 0xd7, 0x80, 0x95, 0x80, 0xd9, 0x85, 0x8e, 0x81, 0x41, 0x6e, 0x81, @@ -4323,11 +4359,11 @@ static const uint8_t unicode_prop_Emoji_table[238] = { 0xbe, 0x8a, 0x28, 0x97, 0x31, 0x0f, 0x8b, 0x01, 0x19, 0x03, 0x81, 0x8c, 0x09, 0x07, 0x81, 0x88, 0x04, 0x82, 0x8b, 0x17, 0x11, 0x00, 0x03, 0x05, - 0x02, 0x05, 0xd5, 0xaf, 0xc5, 0x27, 0x0a, 0x83, + 0x02, 0x05, 0xd5, 0xaf, 0xc5, 0x27, 0x0b, 0x82, 0x89, 0x10, 0x01, 0x10, 0x81, 0x89, 0x40, 0xe2, 0x8b, 0x18, 0x41, 0x1a, 0xae, 0x80, 0x89, 0x80, - 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x89, 0x84, 0xb7, - 0x86, 0x8e, 0x81, 0x8a, 0x85, 0x88, + 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x8a, 0x82, 0xb8, + 0x00, 0x83, 0x8f, 0x81, 0x8b, 0x83, 0x89, }; static const uint8_t unicode_prop_Emoji_Component_table[28] = { @@ -4353,7 +4389,7 @@ static const uint8_t unicode_prop_Emoji_Modifier_Base_table[71] = { 0x10, 0x8c, 0x40, 0xe4, 0x82, 0xa9, 0x88, }; -static const uint8_t unicode_prop_Emoji_Presentation_table[144] = { +static const uint8_t unicode_prop_Emoji_Presentation_table[145] = { 0x60, 0x23, 0x19, 0x81, 0x40, 0xcc, 0x1a, 0x01, 0x80, 0x42, 0x08, 0x81, 0x94, 0x81, 0xb1, 0x8b, 0xaa, 0x80, 0x92, 0x80, 0x8c, 0x07, 0x81, 0x90, @@ -4368,33 +4404,46 @@ static const uint8_t unicode_prop_Emoji_Presentation_table[144] = { 0x1c, 0x8b, 0x90, 0x10, 0x82, 0xc6, 0x00, 0x80, 0x40, 0xba, 0x81, 0xbe, 0x8c, 0x18, 0x97, 0x91, 0x80, 0x99, 0x81, 0x8c, 0x80, 0xd5, 0xd4, 0xaf, - 0xc5, 0x28, 0x12, 0x0a, 0x1b, 0x8a, 0x0e, 0x88, + 0xc5, 0x28, 0x12, 0x0b, 0x13, 0x8a, 0x0e, 0x88, 0x40, 0xe2, 0x8b, 0x18, 0x41, 0x1a, 0xae, 0x80, - 0x89, 0x80, 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x89, - 0x84, 0xb7, 0x86, 0x8e, 0x81, 0x8a, 0x85, 0x88, + 0x89, 0x80, 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x8a, + 0x82, 0xb8, 0x00, 0x83, 0x8f, 0x81, 0x8b, 0x83, + 0x89, }; -static const uint8_t unicode_prop_Extended_Pictographic_table[156] = { +static const uint8_t unicode_prop_Extended_Pictographic_table[254] = { 0x40, 0xa8, 0x03, 0x80, 0x5f, 0x8c, 0x80, 0x8b, 0x80, 0x40, 0xd7, 0x80, 0x95, 0x80, 0xd9, 0x85, - 0x8e, 0x81, 0x41, 0x6e, 0x81, 0x8b, 0x80, 0xde, - 0x80, 0xc5, 0x80, 0x98, 0x8a, 0x1a, 0x40, 0xc6, - 0x80, 0x40, 0xe6, 0x81, 0x89, 0x80, 0x88, 0x80, - 0xb9, 0x18, 0x28, 0x8b, 0x80, 0xf1, 0x89, 0xf5, - 0x81, 0x8a, 0x00, 0x00, 0x28, 0x10, 0x28, 0x89, + 0x8e, 0x81, 0x41, 0x6e, 0x81, 0x8b, 0x80, 0x40, + 0xa5, 0x80, 0x98, 0x8a, 0x1a, 0x40, 0xc6, 0x80, + 0x40, 0xe6, 0x81, 0x89, 0x80, 0x88, 0x80, 0xb9, + 0x18, 0x84, 0x88, 0x01, 0x01, 0x09, 0x03, 0x01, + 0x00, 0x09, 0x02, 0x02, 0x0f, 0x14, 0x00, 0x04, + 0x8b, 0x8a, 0x09, 0x00, 0x08, 0x80, 0x91, 0x01, + 0x81, 0x91, 0x28, 0x00, 0x0a, 0x0c, 0x01, 0x0b, + 0x81, 0x8a, 0x0c, 0x09, 0x04, 0x08, 0x00, 0x81, + 0x93, 0x0c, 0x28, 0x19, 0x03, 0x01, 0x01, 0x28, + 0x01, 0x00, 0x00, 0x05, 0x02, 0x05, 0x80, 0x89, 0x81, 0x8e, 0x01, 0x03, 0x00, 0x03, 0x10, 0x80, - 0x8a, 0x84, 0xac, 0x82, 0x88, 0x80, 0x8d, 0x80, + 0x8a, 0x81, 0xaf, 0x82, 0x88, 0x80, 0x8d, 0x80, 0x8d, 0x80, 0x41, 0x73, 0x81, 0x41, 0xce, 0x82, 0x92, 0x81, 0xb2, 0x03, 0x80, 0x44, 0xd9, 0x80, 0x8b, 0x80, 0x42, 0x58, 0x00, 0x80, 0x61, 0xbd, - 0x65, 0x40, 0xff, 0x8c, 0x82, 0x9e, 0x80, 0xbb, - 0x85, 0x8b, 0x81, 0x8d, 0x01, 0x89, 0x91, 0xb8, - 0x9a, 0x8e, 0x89, 0x80, 0x93, 0x01, 0x88, 0x03, - 0x88, 0x41, 0xb1, 0x84, 0x41, 0x3d, 0x87, 0x41, - 0x09, 0xaf, 0xff, 0xf3, 0x8b, 0xd4, 0xaa, 0x8b, + 0x69, 0x80, 0xa6, 0x83, 0xe3, 0x8b, 0x8e, 0x81, + 0x8e, 0x80, 0x8d, 0x81, 0xa4, 0x89, 0xef, 0x81, + 0x8b, 0x81, 0x8d, 0x01, 0x89, 0x92, 0xb7, 0x9a, + 0x8e, 0x89, 0x80, 0x93, 0x01, 0x88, 0x03, 0x88, + 0x96, 0x85, 0x40, 0xbb, 0x81, 0xef, 0x09, 0x02, + 0x81, 0xd2, 0x0a, 0x03, 0x84, 0x40, 0xfd, 0x80, + 0xbe, 0x8a, 0x28, 0x97, 0x31, 0x0f, 0x8b, 0x01, + 0x19, 0x03, 0x81, 0x8c, 0x09, 0x07, 0x81, 0x88, + 0x04, 0x82, 0x8b, 0x17, 0x11, 0x00, 0x03, 0x05, + 0x02, 0x05, 0xd5, 0xaf, 0xc5, 0x27, 0x81, 0x90, + 0x10, 0x05, 0x81, 0x8c, 0x40, 0xd9, 0xa5, 0x8b, 0x83, 0xb7, 0x87, 0x89, 0x85, 0xa7, 0x87, 0x9d, - 0xd1, 0x8b, 0xae, 0x80, 0x89, 0x80, 0x41, 0xb8, - 0x40, 0xff, 0x43, 0xfd, + 0x81, 0x8b, 0x19, 0x8d, 0x88, 0xa6, 0x8b, 0xae, + 0x80, 0x89, 0x80, 0x40, 0xb8, 0xd7, 0x87, 0x8d, + 0x40, 0x91, 0x40, 0xff, 0x43, 0xfd, }; static const uint8_t unicode_prop_Default_Ignorable_Code_Point_table[51] = { diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libunicode.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libunicode.c index a621c523..09a76a72 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libunicode.c +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/libunicode.c @@ -959,7 +959,7 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, is_compat = n_type >> 1; dbuf_init2(dbuf, opaque, realloc_func); - if (dbuf_realloc(dbuf, sizeof(int) * src_len)) + if (dbuf_claim(dbuf, sizeof(int) * src_len)) goto fail; /* common case: latin1 is unaffected by NFC */ diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/lre-test.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/lre-test.c new file mode 100755 index 00000000..3285db9a --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/lre-test.c @@ -0,0 +1,52 @@ +#ifdef NDEBUG +#undef NDEBUG +#endif +#include +#include +#include +#include "libregexp.h" + +bool lre_check_stack_overflow(void *opaque, size_t alloca_size) +{ + return false; +} + +int lre_check_timeout(void *opaque) +{ + return 0; +} + +void *lre_realloc(void *opaque, void *ptr, size_t size) +{ + if (size == 0) { + free(ptr); + return NULL; + } + return realloc(ptr, size); +} + +// https://github.com/quickjs-ng/quickjs/issues/1375 +static void oob_save_index(void) +{ + // Bytecode with REOP_save_start index=100, but capture_count=1. + // Without validation this causes a heap-buffer-overflow in lre_exec_backtrack. + uint8_t bc[] = { + 0x00, 0x00, // RE_HEADER_FLAGS = 0 + 0x01, // RE_HEADER_CAPTURE_COUNT = 1 + 0x00, // RE_HEADER_STACK_SIZE = 0 + 0x04, 0x00, 0x00, 0x00, // RE_HEADER_BYTECODE_LEN = 4 (little-endian) + 0x05, // REOP_any + 0x0C, 0x64, // REOP_save_start, index=100 + 0x0B, // REOP_match + }; + + uint8_t *capture[2] = {NULL, NULL}; + int ret = lre_exec(capture, bc, (const uint8_t *)"a", 0, 1, 0, NULL); + assert(ret < 0); +} + +int main(void) +{ + oob_save_index(); + return 0; +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/meson.build b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/meson.build index 1c178513..b7b1638f 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/meson.build +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/meson.build @@ -1,11 +1,10 @@ project( 'quickjs-ng', 'c', - version: '0.11.0', + version: '0.15.1', default_options: [ 'c_std=gnu11,c11', 'warning_level=3', - 'default_library=static', ], license: 'MIT', license_files: 'LICENSE', @@ -15,6 +14,8 @@ project( host_system = host_machine.system() cc = meson.get_compiler('c') +add_project_arguments('-DQUICKJS_NG_BUILD', language: 'c') + qjs_gcc_warning_args = [ '-Wno-unsafe-buffer-usage', '-Wno-sign-conversion', @@ -33,9 +34,11 @@ qjs_gcc_warning_args = [ '-Wno-array-bounds', '-Wno-format-truncation', ] -qjs_gcc_args = [ - '-funsigned-char', -] +qjs_gcc_args = [] + +if host_system != 'sunos' + qjs_gcc_args += '-funsigned-char' +endif if host_system == 'darwin' # https://github.com/quickjs-ng/quickjs/issues/453 @@ -131,7 +134,6 @@ qjs_sys_deps += dependency('threads', required: false) qjs_sys_deps += dependency('dl', required: false) qjs_srcs = files( - 'cutils.c', 'dtoa.c', 'libregexp.c', 'libunicode.c', @@ -147,6 +149,10 @@ qjs_libc_hdrs = files('quickjs-libc.h') if qjs_libc qjs_hdrs += qjs_libc_hdrs + add_project_arguments( + '-DQJS_BUILD_LIBC', + language: 'c' + ) endif qjs_parser = get_option('parser') @@ -161,29 +167,14 @@ if not qjs_parser qjs_c_args += ['-DQJS_DISABLE_PARSER'] endif -qjs_libc_lib = static_library( - 'quickjs-libc', - qjs_libc_srcs, - - dependencies: qjs_sys_deps, - c_args: qjs_c_args, - gnu_symbol_visibility: 'hidden', -) - qjs_lib = library( 'qjs', qjs_srcs, - - # export public headers - generator( - find_program('cp', 'xcopy'), - output: ['@PLAINNAME@'], - arguments: ['@INPUT@', '@OUTPUT@'], - ).process(qjs_hdrs), + qjs_libc ? qjs_libc_srcs : [], dependencies: qjs_sys_deps, - link_whole: qjs_libc ? qjs_libc_lib : [], c_args: qjs_c_args, + c_shared_args: ['-DBUILDING_QJS_SHARED'], gnu_symbol_visibility: 'hidden', install: true, @@ -194,13 +185,57 @@ qjs_export_variables = [ f'have_parser=@qjs_parser@' ] +# This note is only of interest on Windows. +# Be conservative here: only pass -DUSING_QJS_SHARED iff default_library == +# 'shared', thus qjs is guaranteed to be a DLL. Not passing -DUSING_QJS_SHARED if +# qjs is a DLL is not harmful, but passing the definition for DLL qjs is desired. +# Conversely, if -DUSING_QJS_SHARED is passed for static qjs, the consumers +# will not compile. +qjs_dep_args = get_option('default_library') == 'shared' ? ['-DUSING_QJS_SHARED'] : [] + qjs_dep = declare_dependency( + compile_args: qjs_dep_args, link_with: qjs_lib, dependencies: qjs_sys_deps, - include_directories: qjs_lib.private_dir_include(), + include_directories: include_directories('.'), variables: qjs_export_variables, ) +if host_system != 'windows' + qjs_module_dep = declare_dependency( + compile_args: [qjs_dep_args, '-DQUICKJS_NG_MODULE_BUILD'], + include_directories: include_directories('.'), + ) +else + qjs_module_dep = declare_dependency( + compile_args: [qjs_dep_args, '-DQUICKJS_NG_MODULE_BUILD'], + include_directories: include_directories('.'), + # Windows can't resolve symbols at runtime thus we explicitly link to qjs. + dependencies: qjs_dep, + ) +endif + +if qjs_libc + qjs_libc_dep = declare_dependency( + include_directories: include_directories('.'), + dependencies: qjs_dep, + ) +else + qjs_libc_lib = static_library( + 'quickjs-libc', + qjs_libc_srcs, + + c_args: qjs_c_args, + dependencies: [qjs_sys_deps, qjs_dep], + gnu_symbol_visibility: 'hidden', + ) + qjs_libc_dep = declare_dependency( + link_with: qjs_libc_lib, + # Pick up quickjs-libc.h. + include_directories: include_directories('.'), + ) +endif + if host_system == 'emscripten' qjs_wasm_export_name = 'getQuickJs' executable( @@ -257,6 +292,8 @@ import('pkgconfig').generate( url: 'https://github.com/quickjs-ng/quickjs', version: meson.project_version(), variables: qjs_export_variables, + # Export -DUSING_QJS_SHARED, if needed, in the pkgconfig file. + extra_cflags: qjs_dep_args, ) if not qjs_parser @@ -272,9 +309,7 @@ qjsc_exe = executable( qjsc_srcs, c_args: qjs_c_args, - link_with: qjs_libc ? [] : qjs_libc_lib, - dependencies: qjs_dep, - + dependencies: [qjs_dep, qjs_libc_dep], install: true, ) @@ -298,8 +333,7 @@ qjs_exe = executable( qjs_exe_srcs, c_args: qjs_c_args, - link_with: qjs_libc ? [] : qjs_libc_lib, - dependencies: [qjs_dep, mimalloc_dep], + dependencies: [qjs_dep, qjs_libc_dep, mimalloc_dep], export_dynamic: true, install: true, @@ -379,10 +413,9 @@ if tests.allowed() run262_exe = executable( 'run-test262', 'run-test262.c', - qjs_libc_srcs, c_args: qjs_c_args, - dependencies: qjs_dep, + dependencies: [qjs_dep, qjs_libc_dep] ) test( @@ -488,16 +521,29 @@ if tests.allowed() ), ) + # LRE test + test( + 'lre', + executable( + 'lre-test', + 'lre-test.c', + 'libregexp.c', + 'libunicode.c', + + c_args: qjs_c_args, + build_by_default: false, + ), + ) + # Function.toString() test test( 'function_source', executable( 'function_source', 'gen/function_source.c', - qjs_libc_srcs, c_args: qjs_c_args, - dependencies: qjs_dep, + dependencies: [qjs_dep, qjs_libc_dep], build_by_default: false, ), ) @@ -506,7 +552,6 @@ endif # Unicode generator unicode_gen = executable( 'unicode_gen', - 'cutils.c', 'unicode_gen.c', c_args: qjs_c_args, @@ -602,34 +647,38 @@ alias_target('codegen', ) if examples.allowed() + if host_system == 'windows' and get_option('default_library') != 'shared' + warning('Binary modules used with static qjs on Windows.') + warning( + 'There might be runtime errors when the modules are used due to', + 'two copies of qjs in memory.' + ) + warning('Please use "-Ddefault_library=shared" if possible.') + endif executable( 'hello', 'gen/hello.c', - qjs_libc_srcs, c_args: qjs_c_args, - dependencies: qjs_dep, + dependencies: [qjs_dep, qjs_libc_dep] ) executable( 'hello_module', 'gen/hello_module.c', - qjs_libc_srcs, c_args: qjs_c_args, - dependencies: qjs_dep, + dependencies: [qjs_dep, qjs_libc_dep] ) subdir('examples') executable( 'test_fib', - 'examples/fib.c', 'gen/test_fib.c', - qjs_libc_srcs, c_args: qjs_c_args, - dependencies: qjs_dep, + dependencies: [qjs_dep, qjs_libc_dep], export_dynamic: true, ) endif diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/qjs-wasi-reactor.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/qjs-wasi-reactor.c new file mode 100755 index 00000000..91d74eb4 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/qjs-wasi-reactor.c @@ -0,0 +1,208 @@ +/* + * QuickJS WASI Reactor Mode + * + * In reactor mode, QuickJS exports functions that can be called repeatedly + * by the host instead of running main() once and blocking in the event loop. + * + * Copyright (c) 2017-2021 Fabrice Bellard + * Copyright (c) 2017-2021 Charlie Gordon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* Include qjs.c to get access to static functions like eval_buf, eval_file, + * parse_limit, and JS_NewCustomContext */ +#include "qjs.c" + +static JSRuntime *reactor_rt = NULL; +static JSContext *reactor_ctx = NULL; + +int qjs_init_argv(int argc, char **argv); + +__attribute__((export_name("qjs_init"))) +int qjs_init(void) +{ + static char *empty_argv[] = { "qjs", NULL }; + return qjs_init_argv(1, empty_argv); +} + +__attribute__((export_name("qjs_init_argv"))) +int qjs_init_argv(int argc, char **argv) +{ + int optind = 1; + char *expr = NULL; + int module = -1; + int load_std = 0; + char *include_list[32]; + int i, include_count = 0; + int64_t memory_limit = -1; + int64_t stack_size = -1; + + if (reactor_rt) + return -1; /* already initialized */ + + /* Parse options (subset of main()) */ + while (optind < argc && *argv[optind] == '-') { + char *arg = argv[optind] + 1; + const char *longopt = ""; + char *optarg = NULL; + if (!*arg) + break; + optind++; + if (*arg == '-') { + longopt = arg + 1; + optarg = strchr(longopt, '='); + if (optarg) + *optarg++ = '\0'; + arg += strlen(arg); + if (!*longopt) + break; + } + for (; *arg || *longopt; longopt = "") { + char opt = *arg; + if (opt) { + arg++; + if (!optarg && *arg) + optarg = arg; + } + if (opt == 'e' || !strcmp(longopt, "eval")) { + if (!optarg) { + if (optind >= argc) + return -1; + optarg = argv[optind++]; + } + expr = optarg; + break; + } + if (opt == 'I' || !strcmp(longopt, "include")) { + if (optind >= argc || include_count >= countof(include_list)) + return -1; + include_list[include_count++] = argv[optind++]; + continue; + } + if (opt == 'm' || !strcmp(longopt, "module")) { + module = 1; + continue; + } + if (!strcmp(longopt, "std")) { + load_std = 1; + continue; + } + if (!strcmp(longopt, "memory-limit")) { + if (!optarg) { + if (optind >= argc) + return -1; + optarg = argv[optind++]; + } + memory_limit = parse_limit(optarg); + break; + } + if (!strcmp(longopt, "stack-size")) { + if (!optarg) { + if (optind >= argc) + return -1; + optarg = argv[optind++]; + } + stack_size = parse_limit(optarg); + break; + } + break; /* ignore unknown options */ + } + } + + reactor_rt = JS_NewRuntime(); + if (!reactor_rt) + return -1; + if (memory_limit >= 0) + JS_SetMemoryLimit(reactor_rt, (size_t)memory_limit); + if (stack_size >= 0) + JS_SetMaxStackSize(reactor_rt, (size_t)stack_size); + + js_std_set_worker_new_context_func(JS_NewCustomContext); + js_std_init_handlers(reactor_rt); + + reactor_ctx = JS_NewCustomContext(reactor_rt); + if (!reactor_ctx) { + js_std_free_handlers(reactor_rt); + JS_FreeRuntime(reactor_rt); + reactor_rt = NULL; + return -1; + } + + JS_SetModuleLoaderFunc2(reactor_rt, NULL, js_module_loader, + js_module_check_attributes, NULL); + JS_SetHostPromiseRejectionTracker(reactor_rt, js_std_promise_rejection_tracker, NULL); + js_std_add_helpers(reactor_ctx, argc - optind, argv + optind); + + if (load_std) { + const char *str = + "import * as bjson from 'qjs:bjson';\n" + "import * as std from 'qjs:std';\n" + "import * as os from 'qjs:os';\n" + "globalThis.bjson = bjson;\n" + "globalThis.std = std;\n" + "globalThis.os = os;\n"; + if (eval_buf(reactor_ctx, str, strlen(str), "", JS_EVAL_TYPE_MODULE)) + goto fail; + } + + for (i = 0; i < include_count; i++) { + if (eval_file(reactor_ctx, include_list[i], 0)) + goto fail; + } + + if (expr) { + if (eval_buf(reactor_ctx, expr, strlen(expr), "", + module == 1 ? JS_EVAL_TYPE_MODULE : 0)) + goto fail; + } else if (optind < argc) { + if (eval_file(reactor_ctx, argv[optind], module)) + goto fail; + } + + return 0; + +fail: + js_std_free_handlers(reactor_rt); + JS_FreeContext(reactor_ctx); + JS_FreeRuntime(reactor_rt); + reactor_rt = NULL; + reactor_ctx = NULL; + return -1; +} + +__attribute__((export_name("qjs_get_context"))) +JSContext *qjs_get_context(void) +{ + return reactor_ctx; +} + +__attribute__((export_name("qjs_destroy"))) +void qjs_destroy(void) +{ + if (reactor_ctx) { + js_std_free_handlers(reactor_rt); + JS_FreeContext(reactor_ctx); + reactor_ctx = NULL; + } + if (reactor_rt) { + JS_FreeRuntime(reactor_rt); + reactor_rt = NULL; + } +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/qjs.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/qjs.c index 4aed6837..96533910 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/qjs.c +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/qjs.c @@ -45,16 +45,23 @@ extern const uint32_t qjsc_repl_size; extern const uint8_t qjsc_standalone[]; extern const uint32_t qjsc_standalone_size; +#if defined(EMSCRIPTEN) || defined(__wasi__) +// Standalone executables (the --compile option and detecting/running an +// executable with appended bytecode) can't work in these environments. +#define emscripten_or_wasi 1 +#else +#define emscripten_or_wasi 0 +#endif + +static int qjs__argc; +static char **qjs__argv; + // Must match standalone.js #define TRAILER_SIZE 12 static const char trailer_magic[] = "quickjs2"; static const int trailer_magic_size = sizeof(trailer_magic) - 1; static const int trailer_size = TRAILER_SIZE; -static int qjs__argc; -static char **qjs__argv; - - static bool is_standalone(const char *exe) { FILE *exe_f = fopen(exe, "rb"); @@ -372,11 +379,12 @@ static const JSMallocFunctions mi_mf = { #define PROG_NAME "qjs" -void help(void) +void help(int exit_status) { printf("QuickJS-ng version %s\n" "usage: " PROG_NAME " [options] [file [args]]\n" "-h --help list options\n" + "-v --version print version string and then exit\n" "-e --eval EXPR evaluate EXPR\n" "-i --interactive go to interactive mode\n" "-C --script load as JS classic script (default=autodetect)\n" @@ -385,32 +393,34 @@ void help(void) " --std make 'std', 'os' and 'bjson' available to script\n" "-T --trace trace memory allocation\n" "-d --dump dump the memory usage stats\n" - "-D --dump-flags flags for dumping debug data (see DUMP_* defines)\n" - "-c --compile FILE compile the given JS file as a standalone executable\n" - "-o --out FILE output file for standalone executables\n" - " --exe select the executable to use as the base, defaults to the current one\n" - " --memory-limit n limit the memory usage to 'n' Kbytes\n" + "-D --dump-flags flags for dumping debug data (see DUMP_* defines)\n", + JS_GetVersion()); + if (!emscripten_or_wasi) + printf("-c --compile FILE compile the given JS file as a standalone executable\n" + "-o --out FILE output file for standalone executables\n" + " --exe select the executable to use as the base, defaults to the current one\n"); + printf(" --memory-limit n limit the memory usage to 'n' Kbytes\n" " --stack-size n limit the stack size to 'n' Kbytes\n" - "-q --quit just instantiate the interpreter and quit\n", JS_GetVersion()); - exit(1); + "-q --quit just instantiate the interpreter and quit\n"); + exit(exit_status); } int main(int argc, char **argv) { JSRuntime *rt; JSContext *ctx; - JSValue ret = JS_UNDEFINED; struct trace_malloc_data trace_data = { NULL }; int r = 0; int optind = 1; + JSValue ret = JS_UNDEFINED; char exebuf[JS__PATH_MAX]; size_t exebuf_size = sizeof(exebuf); char *compile_file = NULL; char *exe = NULL; - char *expr = NULL; - char *dump_flags_str = NULL; char *out = NULL; int standalone = 0; + char *expr = NULL; + char *dump_flags_str = NULL; int interactive = 0; int dump_memory = 0; int dump_flags = 0; @@ -428,8 +438,8 @@ int main(int argc, char **argv) qjs__argv = argv; /* check if this is a standalone executable */ - - if (!js_exepath(exebuf, &exebuf_size) && is_standalone(exebuf)) { + if (!emscripten_or_wasi && + !js_exepath(exebuf, &exebuf_size) && is_standalone(exebuf)) { standalone = 1; goto start; } @@ -441,7 +451,7 @@ int main(int argc, char **argv) the script */ while (optind < argc && *argv[optind] == '-') { char *arg = argv[optind] + 1; - const char *longopt = ""; + char *longopt = ""; char *optarg = NULL; /* a single - is not an option, it also stops argument scanning */ if (!*arg) @@ -465,8 +475,11 @@ int main(int argc, char **argv) optarg = arg; } if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) { - help(); - continue; + help(0); + } + if (opt == 'v' || !strcmp(longopt, "version")) { + printf("%s\n",JS_GetVersion()); + return 0; } if (opt == 'e' || !strcmp(longopt, "eval")) { if (!optarg) { @@ -545,7 +558,8 @@ int main(int argc, char **argv) stack_size = parse_limit(optarg); break; } - if (opt == 'c' || !strcmp(longopt, "compile")) { + if (!emscripten_or_wasi && + (opt == 'c' || !strcmp(longopt, "compile"))) { if (!optarg) { if (optind >= argc) { fprintf(stderr, "qjs: missing file for -c\n"); @@ -556,7 +570,7 @@ int main(int argc, char **argv) compile_file = optarg; break; } - if (opt == 'o' || !strcmp(longopt, "out")) { + if (!emscripten_or_wasi && (opt == 'o' || !strcmp(longopt, "out"))) { if (!optarg) { if (optind >= argc) { fprintf(stderr, "qjs: missing file for -o\n"); @@ -567,7 +581,7 @@ int main(int argc, char **argv) out = optarg; break; } - if (!strcmp(longopt, "exe")) { + if (!emscripten_or_wasi && !strcmp(longopt, "exe")) { if (!optarg) { if (optind >= argc) { fprintf(stderr, "qjs: missing file for --exe\n"); @@ -583,12 +597,12 @@ int main(int argc, char **argv) } else { fprintf(stderr, "qjs: unknown option '--%s'\n", longopt); } - help(); + help(1); } } - if (compile_file && !out) - help(); + if (!emscripten_or_wasi && compile_file && !out) + help(1); start: @@ -621,7 +635,7 @@ int main(int argc, char **argv) } /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); + JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL); /* exit on unhandled promise rejections */ JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker, NULL); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/qjsc.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/qjsc.c index 395bcb34..635ed270 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/qjsc.c +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/qjsc.c @@ -1,9 +1,9 @@ /* * QuickJS command line compiler * - * Copyright (c) 2018-2024 Fabrice Bellard - * Copyright (c) 2023-2025 Ben Noordhuis - * Copyright (c) 2023-2025 Saúl Ibarra Corretgé + * Copyright (c) 2018-2026 Fabrice Bellard + * Copyright (c) 2023-2026 Ben Noordhuis + * Copyright (c) 2023-2026 Saúl Ibarra Corretgé * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -419,7 +419,7 @@ int main(int argc, char **argv) while (optind < argc && *argv[optind] == '-') { char *arg = argv[optind] + 1; - const char *longopt = ""; + char *longopt = ""; char *optarg = NULL; /* a single - is not an option, it also stops argument scanning */ if (!*arg) @@ -645,7 +645,7 @@ int main(int argc, char **argv) } /* add the module loader */ - fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n"); + fprintf(fo, " JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL);\n"); fprintf(fo, " ctx = JS_NewCustomContext(rt);\n" diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-atom.h b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-atom.h index 2a123284..6b8dde84 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-atom.h +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-atom.h @@ -63,6 +63,7 @@ DEF(export, "export") DEF(extends, "extends") DEF(import, "import") DEF(super, "super") +DEF(using, "using") /* FutureReservedWords when parsing strict mode code */ DEF(implements, "implements") DEF(interface, "interface") @@ -84,6 +85,8 @@ DEF(length, "length") DEF(message, "message") DEF(cause, "cause") DEF(errors, "errors") +DEF(error, "error") +DEF(suppressed, "suppressed") DEF(stack, "stack") DEF(name, "name") DEF(toString, "toString") @@ -116,6 +119,10 @@ DEF(_ret_, "") DEF(_var_, "") DEF(_arg_var_, "") DEF(_with_, "") +DEF(_using_dispose_, "") +DEF(use, "use") +DEF(dispose, "dispose") +DEF(disposeAsync, "disposeAsync") DEF(lastIndex, "lastIndex") DEF(target, "target") DEF(index, "index") @@ -144,6 +151,7 @@ DEF(flags, "flags") DEF(global, "global") DEF(unicode, "unicode") DEF(raw, "raw") +DEF(rawJSON, "rawJSON") DEF(new_target, "new.target") DEF(this_active_func, "this.active_func") DEF(home_object, "") @@ -178,6 +186,8 @@ DEF(timed_out, "timed-out") DEF(ok, "ok") DEF(toJSON, "toJSON") DEF(maxByteLength, "maxByteLength") +DEF(zip, "zip") +DEF(zipKeyed, "zipKeyed") /* class names */ DEF(Object, "Object") DEF(Array, "Array") @@ -245,6 +255,9 @@ DEF(URIError, "URIError") DEF(InternalError, "InternalError") DEF(DOMException, "DOMException") DEF(CallSite, "CallSite") +DEF(DisposableStack, "DisposableStack") +DEF(AsyncDisposableStack, "AsyncDisposableStack") +DEF(SuppressedError, "SuppressedError") /* private symbols */ DEF(Private_brand, "") /* symbols */ @@ -261,5 +274,7 @@ DEF(Symbol_hasInstance, "Symbol.hasInstance") DEF(Symbol_species, "Symbol.species") DEF(Symbol_unscopables, "Symbol.unscopables") DEF(Symbol_asyncIterator, "Symbol.asyncIterator") +DEF(Symbol_dispose, "Symbol.dispose") +DEF(Symbol_asyncDispose, "Symbol.asyncDispose") #endif /* DEF */ diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-libc.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-libc.c index 2c7ac770..6926733e 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-libc.c +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-libc.c @@ -73,6 +73,11 @@ typedef sig_t sighandler_t; #define environ (*_NSGetEnviron()) #endif +#ifdef __sun +typedef void (*sighandler_t)(int); +extern char **environ; +#endif + #if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) typedef sig_t sighandler_t; extern char **environ; @@ -222,10 +227,11 @@ static void js_set_thread_state(JSRuntime *rt, JSThreadState *ts) js_std_cmd(/*SetOpaque*/1, rt, ts); } -#ifdef __GNUC__ +// Non-CL Clang on Windows does not define __GNUC__ +#if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" -#endif // __GNUC__ +#endif // __GNUC__ || __clang__ static JSValue js_printf_internal(JSContext *ctx, int argc, JSValueConst *argv, FILE *fp) { @@ -441,9 +447,9 @@ static JSValue js_printf_internal(JSContext *ctx, dbuf_free(&dbuf); return JS_EXCEPTION; } -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic pop // ignored "-Wformat-nonliteral" -#endif // __GNUC__ +#endif // __GNUC__ || __clang__ uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename) { @@ -783,42 +789,176 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, return 0; } -JSModuleDef *js_module_loader(JSContext *ctx, - const char *module_name, void *opaque) +static int default_module_init(JSContext *ctx, JSModuleDef *m) { - JSModuleDef *m; + JSValue val; + val = JS_GetModulePrivateValue(ctx, m); + JS_SetModuleExport(ctx, m, "default", val); + return 0; +} - if (js__has_suffix(module_name, QJS_NATIVE_MODULE_SUFFIX)) { - m = js_module_loader_so(ctx, module_name); - } else { - size_t buf_len; - uint8_t *buf; - JSValue func_val; - - buf = js_load_file(ctx, &buf_len, module_name); - if (!buf) { - JS_ThrowReferenceError(ctx, "could not load module filename '%s'", - module_name); - return NULL; +/* in order to conform with the specification, only the keys should be + tested and not the associated values. */ +int js_module_check_attributes(JSContext *ctx, void *opaque, + JSValueConst attributes) +{ + JSPropertyEnum *tab; + uint32_t i, len; + int ret; + const char *cstr; + size_t cstr_len; + + if (JS_GetOwnPropertyNames(ctx, &tab, &len, attributes, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK)) + return -1; + ret = 0; + for(i = 0; i < len; i++) { + cstr = JS_AtomToCStringLen(ctx, &cstr_len, tab[i].atom); + if (!cstr) { + ret = -1; + break; + } + if (!(cstr_len == 4 && !memcmp(cstr, "type", cstr_len))) { + JS_ThrowTypeError(ctx, "import attribute '%s' is not supported", cstr); + ret = -1; } + JS_FreeCString(ctx, cstr); + if (ret) + break; + } + JS_FreePropertyEnum(ctx, tab, len); + return ret; +} - /* compile the module */ - func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name, - JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); - js_free(ctx, buf); - if (JS_IsException(func_val)) +// js_free_array_buffer to avoid a name conflict with js_array_buffer_free +// from quickjs.c in the amalgamation build +static void js_free_array_buffer(JSRuntime *rt, void *opaque, void *ptr) +{ + js_free_rt(rt, ptr); +} + +enum { + JS_IMPORT_TYPE_JS, + JS_IMPORT_TYPE_JSON, + JS_IMPORT_TYPE_TEXT, + JS_IMPORT_TYPE_BYTES, +}; + +/* return > 0 if the attributes indicate a JSON module, 0 otherwise, -1 on error */ +static int js_module_import_type(JSContext *ctx, JSValueConst attributes) +{ + JSValue str; + const char *cstr; + size_t len; + int res; + + if (JS_IsUndefined(attributes)) + return JS_IMPORT_TYPE_JS; + str = JS_GetPropertyStr(ctx, attributes, "type"); + if (JS_IsException(str)) + return -1; + if (!JS_IsString(str)) { + JS_FreeValue(ctx, str); + return JS_IMPORT_TYPE_JS; + } + cstr = JS_ToCStringLen(ctx, &len, str); + JS_FreeValue(ctx, str); + if (!cstr) + return -1; + if (len == 4 && !memcmp(cstr, "json", len)) { + res = JS_IMPORT_TYPE_JSON; + } else if (len == 4 && !memcmp(cstr, "text", len)) { + res = JS_IMPORT_TYPE_TEXT; + } else if (len == 5 && !memcmp(cstr, "bytes", len)) { + res = JS_IMPORT_TYPE_BYTES; + } else { + /* unknown type - throw error */ + JS_ThrowTypeError(ctx, "unsupported module type: '%s'", cstr); + res = -1; + } + JS_FreeCString(ctx, cstr); + return res; +} + +JSModuleDef *js_module_load(JSContext *ctx, const char *module_name, + void *opaque, JSValueConst attributes, + JSLoadFileFunc *load_file) +{ + JSModuleDef *m; + JSValue val; + size_t buf_len; + char *buf; + int type; + + type = js_module_import_type(ctx, attributes); + if (type < 0) + return NULL; + if (type != JS_IMPORT_TYPE_BYTES) + if (js__has_suffix(module_name, ".json")) + type = JS_IMPORT_TYPE_JSON; + buf = (char *)load_file(ctx, &buf_len, module_name); + if (!buf) { + JS_ThrowReferenceError(ctx, "could not load module filename '%s'", + module_name); + return NULL; + } + switch (type) { + case JS_IMPORT_TYPE_JS: + val = JS_Eval(ctx, buf, buf_len, module_name, + JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); + break; + case JS_IMPORT_TYPE_JSON: + val = JS_ParseJSON(ctx, buf, buf_len, module_name); + break; + case JS_IMPORT_TYPE_TEXT: + val = JS_NewStringLen(ctx, buf, buf_len); + break; + case JS_IMPORT_TYPE_BYTES: + val = JS_NewUint8Array(ctx, (uint8_t *)buf, buf_len, + js_free_array_buffer, NULL, /*is_shared*/false); + if (!JS_IsException(val)) { + JSValue abuf = JS_GetTypedArrayBuffer(ctx, val, NULL, NULL, NULL); + JS_SetImmutableArrayBuffer(abuf, /*immutable*/true); + JS_FreeValue(ctx, abuf); + buf = NULL; + } + break; + default: + val = JS_ThrowInternalError(ctx, "unhandled import type"); + break; + } + js_free(ctx, buf); + if (JS_IsException(val)) + return NULL; + if (type == JS_IMPORT_TYPE_JS) { + if (js_module_set_import_meta(ctx, val, true, false) < 0) { + JS_FreeValue(ctx, val); return NULL; - if (js_module_set_import_meta(ctx, func_val, true, false) < 0) { - JS_FreeValue(ctx, func_val); + } + // the module is already referenced, so we must free it + m = JS_VALUE_GET_PTR(val); + JS_FreeValue(ctx, val); + } else { + m = JS_NewCModule(ctx, module_name, default_module_init); + if (!m) { + JS_FreeValue(ctx, val); return NULL; } - /* the module is already referenced, so we must free it */ - m = JS_VALUE_GET_PTR(func_val); - JS_FreeValue(ctx, func_val); + // only export the "default" symbol which will contain the string + // or JSON object + JS_AddModuleExport(ctx, m, "default"); + JS_SetModulePrivateValue(ctx, m, val); } return m; } +JSModuleDef *js_module_loader(JSContext *ctx, const char *module_name, + void *opaque, JSValueConst attributes) +{ + if (js__has_suffix(module_name, QJS_NATIVE_MODULE_SUFFIX)) + return js_module_loader_so(ctx, module_name); + return js_module_load(ctx, module_name, opaque, attributes, js_load_file); +} + static JSValue js_std_exit(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -1045,19 +1185,27 @@ static bool is_stdio(FILE *f) return f == stdin || f == stdout || f == stderr; } +static void safe_close(FILE *f, bool is_popen) +{ + if (!f) + return; + if (is_stdio(f)) + return; + if (is_popen) { +#if !defined(__wasi__) + pclose(f); +#endif + } else { + fclose(f); + } +} + static void js_std_file_finalizer(JSRuntime *rt, JSValueConst val) { JSThreadState *ts = js_get_thread_state(rt); JSSTDFile *s = JS_GetOpaque(val, ts->std_file_class_id); if (s) { - if (s->f && !is_stdio(s->f)) { -#if !defined(__wasi__) - if (s->is_popen) - pclose(s->f); - else -#endif - fclose(s->f); - } + safe_close(s->f, s->is_popen); js_free_rt(rt, s); } } @@ -1086,16 +1234,18 @@ static JSValue js_new_std_file(JSContext *ctx, FILE *f, bool is_popen) JSValue obj; obj = JS_NewObjectClass(ctx, ts->std_file_class_id); if (JS_IsException(obj)) - return obj; + goto exception; s = js_mallocz(ctx, sizeof(*s)); - if (!s) { - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } + if (!s) + goto exception; s->is_popen = is_popen; s->f = f; JS_SetOpaque(obj, s); return obj; +exception: + safe_close(f, is_popen); + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; } static void js_set_error_object(JSContext *ctx, JSValueConst obj, int err) @@ -1401,25 +1551,41 @@ static JSValue js_std_file_read_write(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { FILE *f = js_std_file_get(ctx, this_val); + bool is_write = (magic != 0); uint64_t pos, len; size_t size, ret; + const char *str; uint8_t *buf; if (!f) return JS_EXCEPTION; - if (JS_ToIndex(ctx, &pos, argv[1])) + pos = 0; + if (argc > 1 && JS_ToIndex(ctx, &pos, argv[1])) return JS_EXCEPTION; - if (JS_ToIndex(ctx, &len, argv[2])) + len = 0; + if (argc > 2 && JS_ToIndex(ctx, &len, argv[2])) return JS_EXCEPTION; - buf = JS_GetArrayBuffer(ctx, &size, argv[0]); + if (is_write && JS_IsString(argv[0])) { + str = JS_ToCStringLen(ctx, &size, argv[0]); + buf = (void *)str; + } else { + str = NULL; + buf = JS_GetArrayBuffer(ctx, &size, argv[0]); + } if (!buf) return JS_EXCEPTION; + if (pos > size) + pos = size; + if (argc < 3) + len = size - pos; if (pos + len > size) - return JS_ThrowRangeError(ctx, "read/write array buffer overflow"); - if (magic) + len = size - pos; + if (is_write) { ret = fwrite(buf + pos, 1, len, f); - else + } else { ret = fread(buf + pos, 1, len, f); + } + JS_FreeCString(ctx, str); return JS_NewInt64(ctx, ret); } @@ -1791,8 +1957,8 @@ static const JSCFunctionListEntry js_std_file_proto_funcs[] = { JS_CFUNC_DEF("fileno", 0, js_std_file_fileno ), JS_CFUNC_DEF("error", 0, js_std_file_error ), JS_CFUNC_DEF("clearerr", 0, js_std_file_clearerr ), - JS_CFUNC_MAGIC_DEF("read", 3, js_std_file_read_write, 0 ), - JS_CFUNC_MAGIC_DEF("write", 3, js_std_file_read_write, 1 ), + JS_CFUNC_MAGIC_DEF("read", 1, js_std_file_read_write, 0 ), + JS_CFUNC_MAGIC_DEF("write", 1, js_std_file_read_write, 1 ), JS_CFUNC_DEF("getline", 0, js_std_file_getline ), JS_CFUNC_MAGIC_DEF("readAsArrayBuffer", 0, js_std_file_readAs, 0 ), JS_CFUNC_MAGIC_DEF("readAsString", 0, js_std_file_readAs, 1 ), @@ -2474,7 +2640,7 @@ static void js_waker_signal(JSWaker *w) ret = write(w->write_fd, "", 1); if (ret == 1) break; - if (ret < 0 && (errno != EAGAIN || errno != EINTR)) + if (ret < 0 && errno != EAGAIN && errno != EINTR) break; } } @@ -2565,8 +2731,13 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx, #endif // USE_WORKER +/* flags for js_os_poll_internal */ +#define JS_OS_POLL_RUN_TIMERS (1 << 0) +#define JS_OS_POLL_WORKERS (1 << 1) +#define JS_OS_POLL_SIGNALS (1 << 2) + #if defined(_WIN32) -static int js_os_poll(JSContext *ctx) +static int js_os_poll_internal(JSContext *ctx, int timeout_ms, int flags) { JSRuntime *rt = JS_GetRuntime(ctx); JSThreadState *ts = js_get_thread_state(rt); @@ -2577,13 +2748,17 @@ static int js_os_poll(JSContext *ctx) /* XXX: handle signals if useful */ - if (js_os_run_timers(rt, ctx, ts, &min_delay)) - return -1; - if (min_delay == 0) - return 0; // expired timer - if (min_delay < 0) - if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->port_list)) - return -1; /* no more events */ + min_delay = timeout_ms; + + if (flags & JS_OS_POLL_RUN_TIMERS) { + if (js_os_run_timers(rt, ctx, ts, &min_delay)) + return -1; + if (min_delay == 0) + return 0; // expired timer + if (min_delay < 0) + if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->port_list)) + return -1; /* no more events */ + } count = 0; list_for_each(el, &ts->os_rw_handlers) { @@ -2594,13 +2769,15 @@ static int js_os_poll(JSContext *ctx) break; } - list_for_each(el, &ts->port_list) { - JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); - if (JS_IsNull(port->on_message_func)) - continue; - handles[count++] = port->recv_pipe->waker.handle; - if (count == (int)countof(handles)) - break; + if (flags & JS_OS_POLL_WORKERS) { + list_for_each(el, &ts->port_list) { + JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); + if (JS_IsNull(port->on_message_func)) + continue; + handles[count++] = port->recv_pipe->waker.handle; + if (count == (int)countof(handles)) + break; + } } if (count > 0) { @@ -2608,7 +2785,7 @@ static int js_os_poll(JSContext *ctx) if (min_delay != -1) timeout = min_delay; ret = WaitForMultipleObjects(count, handles, FALSE, timeout); - if (ret < count) { + if (ret < (DWORD)count) { list_for_each(el, &ts->os_rw_handlers) { rh = list_entry(el, JSOSRWHandler, link); if (rh->fd == 0 && !JS_IsNull(rh->rw_func[0])) { @@ -2617,25 +2794,42 @@ static int js_os_poll(JSContext *ctx) } } - list_for_each(el, &ts->port_list) { - JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); - if (!JS_IsNull(port->on_message_func)) { - JSWorkerMessagePipe *ps = port->recv_pipe; - if (ps->waker.handle == handles[ret]) { - if (handle_posted_message(rt, ctx, port)) - goto done; + if (flags & JS_OS_POLL_WORKERS) { + list_for_each(el, &ts->port_list) { + JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); + if (!JS_IsNull(port->on_message_func)) { + JSWorkerMessagePipe *ps = port->recv_pipe; + if (ps->waker.handle == handles[ret]) { + if (handle_posted_message(rt, ctx, port)) + goto done; + } } } } } - } else { + } else if (min_delay > 0) { Sleep(min_delay); } done: return 0; } -#else // !defined(_WIN32) + static int js_os_poll(JSContext *ctx) +{ + return js_os_poll_internal(ctx, -1, + JS_OS_POLL_RUN_TIMERS | JS_OS_POLL_WORKERS | JS_OS_POLL_SIGNALS); +} + +int js_std_poll_io(JSContext *ctx, int timeout_ms) +{ + int ret = js_os_poll_internal(ctx, timeout_ms, 0); + /* map return codes: -1 on error stays -1, negative from handler becomes -2 */ + if (ret < -1) + return -2; + return ret; +} +#else // !defined(_WIN32) +static int js_os_poll_internal(JSContext *ctx, int timeout_ms, int flags) { JSRuntime *rt = JS_GetRuntime(ctx); JSThreadState *ts = js_get_thread_state(rt); @@ -2644,8 +2838,11 @@ static int js_os_poll(JSContext *ctx) struct list_head *el; struct pollfd *pfd, *pfds, pfds_local[64]; + min_delay = timeout_ms; + /* only check signals in the main thread */ - if (!ts->recv_pipe && + if ((flags & JS_OS_POLL_SIGNALS) && + !ts->recv_pipe && unlikely(os_pending_signals != 0)) { JSOSSignalHandler *sh; uint64_t mask; @@ -2660,13 +2857,15 @@ static int js_os_poll(JSContext *ctx) } } - if (js_os_run_timers(rt, ctx, ts, &min_delay)) - return -1; - if (min_delay == 0) - return 0; // expired timer - if (min_delay < 0) - if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->port_list)) - return -1; /* no more events */ + if (flags & JS_OS_POLL_RUN_TIMERS) { + if (js_os_run_timers(rt, ctx, ts, &min_delay)) + return -1; + if (min_delay == 0) + return 0; // expired timer + if (min_delay < 0) + if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->port_list)) + return -1; /* no more events */ + } nfds = 0; list_for_each(el, &ts->os_rw_handlers) { @@ -2675,12 +2874,28 @@ static int js_os_poll(JSContext *ctx) } #ifdef USE_WORKER - list_for_each(el, &ts->port_list) { - JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); - nfds += !JS_IsNull(port->on_message_func); + if (flags & JS_OS_POLL_WORKERS) { + list_for_each(el, &ts->port_list) { + JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); + nfds += !JS_IsNull(port->on_message_func); + } } #endif // USE_WORKER + if (nfds == 0) { + if (min_delay > 0) { + struct timespec ts_sleep = { + .tv_sec = min_delay / 1000, + .tv_nsec = (min_delay % 1000) * 1000000L + }; + uint64_t mask = os_pending_signals; + while (nanosleep(&ts_sleep, &ts_sleep) + && errno == EINTR + && mask == os_pending_signals); + } + return 0; + } + pfd = pfds = pfds_local; if (nfds > (int)countof(pfds_local)) { pfd = pfds = js_malloc(ctx, nfds * sizeof(*pfd)); @@ -2697,11 +2912,13 @@ static int js_os_poll(JSContext *ctx) } #ifdef USE_WORKER - list_for_each(el, &ts->port_list) { - JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); - if (!JS_IsNull(port->on_message_func)) { - JSWorkerMessagePipe *ps = port->recv_pipe; - *pfd++ = (struct pollfd){ps->waker.read_fd, POLLIN, 0}; + if (flags & JS_OS_POLL_WORKERS) { + list_for_each(el, &ts->port_list) { + JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); + if (!JS_IsNull(port->on_message_func)) { + JSWorkerMessagePipe *ps = port->recv_pipe; + *pfd++ = (struct pollfd){ps->waker.read_fd, POLLIN, 0}; + } } } #endif // USE_WORKER @@ -2711,6 +2928,10 @@ static int js_os_poll(JSContext *ctx) // i.e., it's probably good enough for now ret = 0; nfds = poll(pfds, nfds, min_delay); + if (nfds < 0) { + ret = -1; + goto done; + } for (pfd = pfds; nfds-- > 0; pfd++) { rh = find_rh(ts, pfd->fd); if (rh) { @@ -2726,8 +2947,9 @@ static int js_os_poll(JSContext *ctx) goto done; /* must stop because the list may have been modified */ } - } else { + } #ifdef USE_WORKER + else if (flags & JS_OS_POLL_WORKERS) { list_for_each(el, &ts->port_list) { JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); if (!JS_IsNull(port->on_message_func)) { @@ -2738,32 +2960,42 @@ static int js_os_poll(JSContext *ctx) } } } -#endif // USE_WORKER } +#endif // USE_WORKER } done: if (pfds != pfds_local) js_free(ctx, pfds); return ret; } -#endif // defined(_WIN32) +static int js_os_poll(JSContext *ctx) +{ + return js_os_poll_internal(ctx, -1, + JS_OS_POLL_RUN_TIMERS | JS_OS_POLL_WORKERS | JS_OS_POLL_SIGNALS); +} + +int js_std_poll_io(JSContext *ctx, int timeout_ms) +{ + int ret = js_os_poll_internal(ctx, timeout_ms, 0); + /* map return codes: -1 on error stays -1, negative from handler becomes -2 */ + if (ret < -1) + return -2; + return ret; +} +#endif // defined(_WIN32) static JSValue make_obj_error(JSContext *ctx, JSValue obj, int err) { - JSValue arr; + JSValue vals[2]; + if (JS_IsException(obj)) return obj; - arr = JS_NewArray(ctx); - if (JS_IsException(arr)) - return JS_EXCEPTION; - JS_DefinePropertyValueUint32(ctx, arr, 0, obj, - JS_PROP_C_W_E); - JS_DefinePropertyValueUint32(ctx, arr, 1, JS_NewInt32(ctx, err), - JS_PROP_C_W_E); - return arr; + vals[0] = obj; + vals[1] = JS_NewInt32(ctx, err); + return JS_NewArrayFrom(ctx, countof(vals), vals); } static JSValue make_string_error(JSContext *ctx, @@ -2909,6 +3141,53 @@ static JSValue js_os_readdir(JSContext *ctx, JSValueConst this_val, #endif } +#if !defined(_WIN32) && !defined(__wasi__) +#define PAT "XXXXXX" +#define PSZ (sizeof(PAT)-1) +static JSValue js_os_mkdstemp(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, int magic) +{ + char pat_s[32] = "tmp"PAT, *pat = pat_s; + const char *s; + size_t k, n; + JSValue val; + int err; + + if (argc > 0) { + s = JS_ToCStringLen(ctx, &n, argv[0]); + if (!s) + return JS_EXCEPTION; + k = n; + if (n < PSZ || memcmp(&s[n-PSZ], PAT, PSZ)) + k += PSZ; + if (k >= sizeof(pat_s)) + pat = js_malloc(ctx, k+1); + if (pat) { + memcpy(pat, s, n); + if (n < k) + memcpy(&pat[n], PAT, PSZ); + pat[k] = '\0'; + } + JS_FreeCString(ctx, s); + if (!pat) + return JS_EXCEPTION; + } + if (magic == 'd') { + err = 0; + if (!mkdtemp(pat)) + err = -errno; + } else { + err = js_get_errno(mkstemp(pat)); + } + val = JS_NewString(ctx, pat); + if (pat != pat_s) + js_free(ctx, pat); + return make_obj_error(ctx, val, err); +} +#undef PSZ +#undef PAT +#endif // !defined(_WIN32) && !defined(__wasi__) + #if !defined(_WIN32) static int64_t timespec_to_ms(const struct timespec *tv) { @@ -3654,6 +3933,7 @@ typedef struct { uint64_t buf[]; } JSSABHeader; +static JSRuntime *(*js_worker_new_runtime_func)(void); static JSContext *(*js_worker_new_context_func)(JSRuntime *rt); static int atomic_add_int(int *ptr, int v) @@ -3777,20 +4057,25 @@ static JSClassDef js_worker_class = { static void worker_func(void *opaque) { + JSRuntime *(*new_runtime_func)(void); + JSContext *(*new_context_func)(JSRuntime *); WorkerFuncArgs *args = opaque; JSRuntime *rt; JSThreadState *ts; JSContext *ctx; JSValue val; - rt = JS_NewRuntime(); + new_runtime_func = js_worker_new_runtime_func; + if (!new_runtime_func) + new_runtime_func = JS_NewRuntime; + rt = new_runtime_func(); if (rt == NULL) { fprintf(stderr, "JS_NewRuntime failure"); exit(1); } js_std_init_handlers(rt); - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); + JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL); /* set the pipe to communicate with the parent */ ts = js_get_thread_state(rt); @@ -3799,9 +4084,13 @@ static void worker_func(void *opaque) /* function pointer to avoid linking the whole JS_NewContext() if not needed */ - ctx = js_worker_new_context_func(rt); + new_context_func = js_worker_new_context_func; + if (!new_context_func) + new_context_func = JS_NewContext; + ctx = new_context_func(rt); if (ctx == NULL) { fprintf(stderr, "JS_NewContext failure"); + exit(1); } JS_SetCanBlock(rt, true); @@ -4062,6 +4351,13 @@ static const JSCFunctionListEntry js_worker_proto_funcs[] = { #endif /* USE_WORKER */ +void js_std_set_worker_new_runtime_func(JSRuntime *(*func)(void)) +{ +#ifdef USE_WORKER + js_worker_new_runtime_func = func; +#endif +} + void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)) { #ifdef USE_WORKER @@ -4155,6 +4451,10 @@ static const JSCFunctionListEntry js_os_funcs[] = { JS_CFUNC_DEF("chdir", 0, js_os_chdir ), JS_CFUNC_DEF("mkdir", 1, js_os_mkdir ), JS_CFUNC_DEF("readdir", 1, js_os_readdir ), +#if !defined(_WIN32) && !defined(__wasi__) + JS_CFUNC_MAGIC_DEF("mkdtemp", 0, js_os_mkdstemp, 'd' ), + JS_CFUNC_MAGIC_DEF("mkstemp", 0, js_os_mkdstemp, 's' ), +#endif /* st_mode constants */ OS_FLAG(S_IFMT), OS_FLAG(S_IFIFO), @@ -4420,22 +4720,41 @@ static void js_dump_obj(JSContext *ctx, FILE *f, JSValueConst val) } } +#define JS_DUMP_ERROR_MAX_CAUSE_DEPTH 10 + static void js_std_dump_error1(JSContext *ctx, JSValueConst exception_val) { - JSValue val; + JSValue val, current; bool is_error; - - is_error = JS_IsError(exception_val); - js_dump_obj(ctx, stderr, exception_val); - if (is_error) { - val = JS_GetPropertyStr(ctx, exception_val, "stack"); - } else { - js_std_cmd(/*ErrorBackTrace*/2, ctx, &val); - } - if (!JS_IsUndefined(val)) { - js_dump_obj(ctx, stderr, val); - JS_FreeValue(ctx, val); + int depth; + + current = JS_DupValue(ctx, exception_val); + for (depth = 0; ; depth++) { + is_error = JS_IsError(current); + js_dump_obj(ctx, stderr, current); + if (is_error) { + val = JS_GetPropertyStr(ctx, current, "stack"); + } else if (depth == 0) { + js_std_cmd(/*ErrorBackTrace*/2, ctx, &val); + } else { + val = JS_UNDEFINED; + } + if (!JS_IsUndefined(val)) { + js_dump_obj(ctx, stderr, val); + JS_FreeValue(ctx, val); + } + if (!is_error || depth >= JS_DUMP_ERROR_MAX_CAUSE_DEPTH) + break; + val = JS_GetPropertyStr(ctx, current, "cause"); + if (JS_IsUndefined(val)) { + JS_FreeValue(ctx, val); + break; + } + fputs("Caused by: ", stderr); + JS_FreeValue(ctx, current); + current = val; } + JS_FreeValue(ctx, current); } void js_std_dump_error(JSContext *ctx) @@ -4535,6 +4854,39 @@ int js_std_loop(JSContext *ctx) return JS_HasException(ctx); } +int js_std_loop_once(JSContext *ctx) +{ + JSRuntime *rt = JS_GetRuntime(ctx); + JSThreadState *ts = js_get_thread_state(rt); + JSContext *ctx1; + int err, min_delay; + + /* execute all pending jobs */ + for(;;) { + err = JS_ExecutePendingJob(rt, &ctx1); + if (err < 0) + return -2; /* error */ + if (err == 0) + break; + } + + /* run at most one expired timer */ + if (js_os_run_timers(rt, ctx, ts, &min_delay) < 0) + return -2; /* error in timer callback */ + + /* check if more work is pending */ + if (JS_IsJobPending(rt)) + return 0; /* more microtasks pending */ + + if (min_delay == 0) + return 0; /* timer ready to fire immediately */ + + if (min_delay > 0) + return min_delay; /* next timer delay in ms */ + + return -1; /* idle, no pending work */ +} + /* Wait for a promise and execute pending jobs while waiting for it. Return the promise result or JS_EXCEPTION in case of promise rejection. */ @@ -4625,6 +4977,7 @@ static JSValue js_bjson_read(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; if (JS_ToInt32(ctx, &flags, argv[3])) return JS_EXCEPTION; + flags &= ~JS_READ_OBJ_SAB; buf = JS_GetArrayBuffer(ctx, &size, argv[0]); if (!buf) return JS_EXCEPTION; @@ -4644,6 +4997,7 @@ static JSValue js_bjson_write(JSContext *ctx, JSValueConst this_val, if (JS_ToInt32(ctx, &flags, argv[1])) return JS_EXCEPTION; + flags &= ~JS_WRITE_OBJ_SAB; buf = JS_WriteObject(ctx, &len, argv[0], flags); if (!buf) return JS_EXCEPTION; @@ -4659,10 +5013,8 @@ static const JSCFunctionListEntry js_bjson_funcs[] = { #define DEF(x) JS_PROP_INT32_DEF(#x, JS_##x, JS_PROP_CONFIGURABLE) DEF(READ_OBJ_BYTECODE), DEF(READ_OBJ_REFERENCE), - DEF(READ_OBJ_SAB), DEF(WRITE_OBJ_BYTECODE), DEF(WRITE_OBJ_REFERENCE), - DEF(WRITE_OBJ_SAB), DEF(WRITE_OBJ_STRIP_DEBUG), DEF(WRITE_OBJ_STRIP_SOURCE), #undef DEF diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-libc.h b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-libc.h index 6af5a639..fd91a2f6 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-libc.h +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-libc.h @@ -25,6 +25,7 @@ #define QUICKJS_LIBC_H #include +#include #include #include @@ -34,40 +35,50 @@ extern "C" { #endif -#if defined(__GNUC__) || defined(__clang__) -#define JS_EXTERN __attribute__((visibility("default"))) -#else -#define JS_EXTERN /* nothing */ -#endif - -JS_EXTERN JSModuleDef *js_init_module_std(JSContext *ctx, - const char *module_name); -JS_EXTERN JSModuleDef *js_init_module_os(JSContext *ctx, - const char *module_name); -JS_EXTERN JSModuleDef *js_init_module_bjson(JSContext *ctx, - const char *module_name); -JS_EXTERN void js_std_add_helpers(JSContext *ctx, int argc, char **argv); -JS_EXTERN int js_std_loop(JSContext *ctx); -JS_EXTERN JSValue js_std_await(JSContext *ctx, JSValue obj); -JS_EXTERN void js_std_init_handlers(JSRuntime *rt); -JS_EXTERN void js_std_free_handlers(JSRuntime *rt); -JS_EXTERN void js_std_dump_error(JSContext *ctx); -JS_EXTERN uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, +typedef uint8_t *JSLoadFileFunc(JSContext *ctx, size_t *pbuf_len, const char *filename); -JS_EXTERN int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, - bool use_realpath, bool is_main); -JS_EXTERN JSModuleDef *js_module_loader(JSContext *ctx, - const char *module_name, void *opaque); -JS_EXTERN void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, - size_t buf_len, int flags); -JS_EXTERN void js_std_promise_rejection_tracker(JSContext *ctx, - JSValueConst promise, - JSValueConst reason, - bool is_handled, - void *opaque); -JS_EXTERN void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)); -#undef JS_EXTERN +JS_LIBC_EXTERN JSModuleDef *js_init_module_std(JSContext *ctx, + const char *module_name); +JS_LIBC_EXTERN JSModuleDef *js_init_module_os(JSContext *ctx, + const char *module_name); +JS_LIBC_EXTERN JSModuleDef *js_init_module_bjson(JSContext *ctx, + const char *module_name); +JS_LIBC_EXTERN void js_std_add_helpers(JSContext *ctx, int argc, char **argv); +JS_LIBC_EXTERN int js_std_loop(JSContext *ctx); +JS_LIBC_EXTERN int js_std_loop_once(JSContext *ctx); +JS_LIBC_EXTERN int js_std_poll_io(JSContext *ctx, int timeout_ms); +JS_LIBC_EXTERN JSValue js_std_await(JSContext *ctx, JSValue obj); +JS_LIBC_EXTERN void js_std_init_handlers(JSRuntime *rt); +JS_LIBC_EXTERN void js_std_free_handlers(JSRuntime *rt); +JS_LIBC_EXTERN void js_std_dump_error(JSContext *ctx); +JS_LIBC_EXTERN uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, + const char *filename); +JS_LIBC_EXTERN int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, + bool use_realpath, bool is_main); +JS_LIBC_EXTERN JSModuleDef *js_module_loader(JSContext *ctx, + const char *module_name, void *opaque, + JSValueConst attributes); +// like js_module_loader but does not load .so objects and the file reader +// is pluggable; js_module_loader is implemented in terms of js_module_load +JS_LIBC_EXTERN JSModuleDef *js_module_load(JSContext *ctx, const char *module_name, + void *opaque, JSValueConst attributes, + JSLoadFileFunc *load_file); +JS_LIBC_EXTERN int js_module_check_attributes(JSContext *ctx, void *opaque, + JSValueConst attributes); +JS_LIBC_EXTERN void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, + size_t buf_len, int flags); +JS_LIBC_EXTERN void js_std_promise_rejection_tracker(JSContext *ctx, + JSValueConst promise, + JSValueConst reason, + bool is_handled, + void *opaque); +// Defaults to JS_NewRuntime, no-op if compiled without worker support. +// Call before creating the first worker thread. +JS_LIBC_EXTERN void js_std_set_worker_new_runtime_func(JSRuntime *(*func)(void)); +// Defaults to JS_NewContext, no-op if compiled without worker support. +// Call before creating the first worker thread. +JS_LIBC_EXTERN void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)); #ifdef __cplusplus } /* extern "C" { */ diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-opcode.h b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-opcode.h index bd5be754..ec2a5ad9 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-opcode.h +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs-opcode.h @@ -122,14 +122,12 @@ DEF( apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */ DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a bytecode string */ DEF( get_super, 1, 1, 1, none) -DEF( import, 1, 1, 1, none) /* dynamic module import */ +DEF( import, 1, 2, 1, none) /* dynamic module import */ -DEF( check_var, 5, 0, 1, atom) /* check if a variable exists */ DEF( get_var_undef, 5, 0, 1, atom) /* push undefined if the variable does not exist */ DEF( get_var, 5, 0, 1, atom) /* throw an exception if the variable does not exist */ DEF( put_var, 5, 1, 0, atom) /* must come after get_var */ DEF( put_var_init, 5, 1, 0, atom) /* must come after put_var. Used to initialize a global lexical variable */ -DEF( put_var_strict, 5, 2, 0, atom) /* for strict mode variable write */ DEF( get_ref_value, 1, 2, 3, none) DEF( put_ref_value, 1, 3, 0, none) @@ -189,6 +187,7 @@ DEF( gosub, 5, 0, 0, label) /* used to execute the finally block */ DEF( ret, 1, 1, 0, none) /* used to return from the finally block */ DEF( nip_catch, 1, 2, 1, none) /* catch ... a -> a */ +DEF( check_object, 1, 1, 1, none) DEF( to_object, 1, 1, 1, none) //DEF( to_string, 1, 1, 1, none) DEF( to_propkey, 1, 1, 1, none) @@ -211,7 +210,6 @@ DEF( for_of_start, 1, 1, 3, none) DEF(for_await_of_start, 1, 1, 3, none) DEF( for_in_next, 1, 1, 3, none) DEF( for_of_next, 2, 3, 5, u8) -DEF(iterator_check_object, 1, 1, 1, none) DEF(iterator_get_value_done, 1, 1, 2, none) DEF( iterator_close, 1, 3, 0, none) DEF( iterator_next, 1, 4, 4, none) @@ -265,6 +263,12 @@ DEF( strict_neq, 1, 2, 1, none) DEF(is_undefined_or_null, 1, 1, 1, none) DEF( private_in, 1, 2, 1, none) DEF(push_bigint_i32, 5, 0, 1, i32) +DEF( using_dispose_init, 1, 0, 1, none) +DEF( using_dispose, 3, 1, 1, loc) +DEF(using_dispose_async, 3, 0, 1, loc) +DEF(using_dispose_merge, 1, 2, 1, none) +DEF( using_dispose_end, 1, 1, 0, none) +DEF( using_check, 2, 1, 2, u8) /* must be the last non short and non temporary opcode */ DEF( nop, 1, 0, 0, none) @@ -290,6 +294,8 @@ def(get_field_opt_chain, 5, 1, 1, atom) /* emitted in phase 1, removed in phase def(get_array_el_opt_chain, 1, 2, 1, none) /* emitted in phase 1, removed in phase 2 */ def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */ +def( dispose_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */ + def( source_loc, 9, 0, 0, u32x2) /* emitted in phase 1, removed in phase 3 */ DEF( push_minus1, 1, 0, 1, none_int) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs.c index c6815fb3..3fbf113e 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs.c +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs.c @@ -1,10 +1,10 @@ /* * QuickJS Javascript Engine * - * Copyright (c) 2017-2025 Fabrice Bellard + * Copyright (c) 2017-2026 Fabrice Bellard * Copyright (c) 2017-2025 Charlie Gordon - * Copyright (c) 2023-2025 Ben Noordhuis - * Copyright (c) 2023-2025 Saúl Ibarra Corretgé + * Copyright (c) 2023-2026 Ben Noordhuis + * Copyright (c) 2023-2026 Saúl Ibarra Corretgé * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -40,7 +40,6 @@ #include #endif #include -#include #include #include "cutils.h" @@ -65,10 +64,15 @@ #define NO_TM_GMTOFF #endif +#if defined(__sun) +#include +#define NO_TM_GMTOFF +#endif + // atomic_store etc. are completely busted in recent versions of tcc; // somehow the compiler forgets to load |ptr| into %rdi when calling // the __atomic_*() helpers in its lib/stdatomic.c and lib/atomic.S -#if !defined(__TINYC__) && !defined(EMSCRIPTEN) && !defined(__wasi__) && !__STDC_NO_ATOMICS__ +#if !defined(__TINYC__) && !defined(EMSCRIPTEN) && !defined(__wasi__) && !__STDC_NO_ATOMICS__ && !defined(__DJGPP) #include "quickjs-c-atomics.h" #define CONFIG_ATOMICS #endif @@ -138,6 +142,7 @@ enum { JS_CLASS_BYTECODE_FUNCTION, /* u.func */ JS_CLASS_BOUND_FUNCTION, /* u.bound_function */ JS_CLASS_C_FUNCTION_DATA, /* u.c_function_data_record */ + JS_CLASS_C_CLOSURE, /* u.c_closure_record */ JS_CLASS_GENERATOR_FUNCTION, /* u.func */ JS_CLASS_FOR_IN_ITERATOR, /* u.for_in_iterator */ JS_CLASS_REGEXP, /* u.regexp */ @@ -171,6 +176,7 @@ enum { JS_CLASS_STRING_ITERATOR, /* u.array_iterator_data */ JS_CLASS_REGEXP_STRING_ITERATOR, /* u.regexp_string_iterator_data */ JS_CLASS_GENERATOR, /* u.generator_data */ + JS_CLASS_DISPOSABLE_STACK, JS_CLASS_PROXY, /* u.proxy_data */ JS_CLASS_PROMISE, /* u.promise_data */ JS_CLASS_PROMISE_RESOLVE_FUNCTION, /* u.promise_function_data */ @@ -181,10 +187,12 @@ enum { JS_CLASS_ASYNC_FROM_SYNC_ITERATOR, /* u.async_from_sync_iterator_data */ JS_CLASS_ASYNC_GENERATOR_FUNCTION, /* u.func */ JS_CLASS_ASYNC_GENERATOR, /* u.async_generator_data */ + JS_CLASS_ASYNC_DISPOSABLE_STACK, JS_CLASS_WEAK_REF, JS_CLASS_FINALIZATION_REGISTRY, JS_CLASS_DOM_EXCEPTION, JS_CLASS_CALL_SITE, + JS_CLASS_RAWJSON, JS_CLASS_INIT_COUNT, /* last entry for predefined classes */ }; @@ -203,6 +211,7 @@ typedef enum JSErrorEnum { JS_URI_ERROR, JS_INTERNAL_ERROR, JS_AGGREGATE_ERROR, + JS_SUPPRESSED_ERROR, JS_NATIVE_ERROR_COUNT, /* number of different NativeError objects */ JS_PLAIN_ERROR = JS_NATIVE_ERROR_COUNT @@ -215,13 +224,24 @@ typedef enum JSErrorEnum { // more profitable to ref slice than to copy #define JS_STRING_SLICE_LEN_MAX 1024 // in bytes +/* strings <= this length are not concatenated using ropes. if too + small, the rope memory overhead becomes high. */ +#define JS_STRING_ROPE_SHORT_LEN 512 +/* specific threshold for initial rope use */ +#define JS_STRING_ROPE_SHORT2_LEN 8192 +/* rope depth at which we rebalance */ +#define JS_STRING_ROPE_MAX_DEPTH 60 + #define __exception __attribute__((warn_unused_result)) typedef struct JSShape JSShape; typedef struct JSString JSString; typedef struct JSString JSAtomStruct; +typedef struct JSStringRope JSStringRope; +#define JS_VALUE_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v)) #define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v)) +#define JS_VALUE_GET_STRING_ROPE(v) ((JSStringRope *)JS_VALUE_GET_PTR(v)) typedef enum { JS_GC_PHASE_NONE, @@ -305,8 +325,17 @@ struct JSRuntime { struct list_head job_list; /* list of JSJobEntry.link */ - JSModuleNormalizeFunc *module_normalize_func; - JSModuleLoaderFunc *module_loader_func; + bool module_normalize_has_attr; + union { + JSModuleNormalizeFunc *module_normalize_func; + JSModuleNormalizeFunc2 *module_normalize_func2; + } normalize_u; + bool module_loader_has_attr; + union { + JSModuleLoaderFunc *module_loader_func; + JSModuleLoaderFunc2 *module_loader_func2; + } u; + JSModuleCheckSupportedImportAttributes *module_check_attrs; void *module_loader_opaque; /* timestamp for internal use in module evaluation */ int64_t module_async_evaluation_next_timestamp; @@ -342,11 +371,12 @@ typedef struct JSStackFrame { JSValue cur_func; /* current function, JS_UNDEFINED if the frame is detached */ JSValue *arg_buf; /* arguments */ JSValue *var_buf; /* variables */ - struct list_head var_ref_list; /* list of JSVarRef.link */ + struct JSVarRef **var_refs; /* references to arguments or local variables */ uint8_t *cur_pc; /* only used in bytecode functions : PC of the instruction after the call */ - uint32_t arg_count : 31; - uint32_t is_strict_mode : 1; + uint16_t var_ref_count; /* number of var refs */ + uint16_t arg_count; + bool is_strict_mode; /* only used in generators. Current stack pointer value. NULL if the function is running. */ JSValue *cur_sp; @@ -367,7 +397,8 @@ typedef enum { struct JSGCObjectHeader { int ref_count; /* must come first, 32-bit */ JSGCObjectTypeEnum gc_obj_type : 4; - uint8_t mark : 4; /* used by the GC */ + uint8_t mark : 1; /* used by the GC */ + uint8_t dummy0 : 3; uint8_t dummy1; /* not used by the GC */ uint16_t dummy2; /* not used by the GC */ struct list_head link; @@ -380,11 +411,19 @@ typedef struct JSVarRef { int __gc_ref_count; /* corresponds to header.ref_count */ uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */ uint8_t is_detached; + uint8_t is_lexical; /* only used with global variables */ + uint8_t is_const; /* only used with global variables */ }; }; JSValue *pvalue; /* pointer to the value, either on the stack or to 'value' */ - JSValue value; /* used when the variable is no longer on the stack */ + union { + JSValue value; /* used when is_detached = true */ + struct { + uint16_t var_ref_idx; /* index in JSStackFrame.var_refs[] */ + JSStackFrame *stack_frame; + }; /* used when is_detached = false */ + }; } JSVarRef; typedef struct JSRefCountHeader { @@ -431,6 +470,8 @@ typedef enum { enum { JS_BUILTIN_ARRAY_FROMASYNC = 1, + JS_BUILTIN_ITERATOR_ZIP, + JS_BUILTIN_ITERATOR_ZIP_KEYED, }; /* must be large enough to have a negligible runtime cost and small @@ -443,9 +484,21 @@ struct JSContext { struct list_head link; uint16_t binary_object_count; - int binary_object_size; + uint32_t binary_object_size : 31; + + /* true if the array prototype is "normal": + - no small index properties which are get/set or non writable + - its prototype is Object.prototype + - Object.prototype has no small index properties which are get/set or non writable + - the prototype of Object.prototype is null (always true as it is immutable) + */ + uint8_t std_array_prototype : 1; JSShape *array_shape; /* initial shape for Array objects */ + JSShape *arguments_shape; /* shape for arguments objects */ + JSShape *mapped_arguments_shape; /* shape for mapped arguments objects */ + JSShape *regexp_shape; /* shape for regexp objects */ + JSShape *regexp_result_shape; /* shape for regexp result objects */ JSValue *class_proto; JSValue function_proto; @@ -557,20 +610,21 @@ typedef enum { typedef enum { JS_STRING_KIND_NORMAL, JS_STRING_KIND_SLICE, + JS_STRING_KIND_INDIRECT, } JSStringKind; -#define JS_ATOM_HASH_MASK ((1 << 29) - 1) +#define JS_ATOM_HASH_MASK ((1 << 28) - 1) struct JSString { JSRefCountHeader header; /* must come first, 32-bit */ uint32_t len : 31; - uint8_t is_wide_char : 1; /* 0 = 8 bits, 1 = 16 bits characters */ + uint32_t is_wide_char : 1; /* 0 = 8 bits, 1 = 16 bits characters */ /* for JS_ATOM_TYPE_SYMBOL: hash = 0, atom_type = 3, for JS_ATOM_TYPE_PRIVATE: hash = 1, atom_type = 3 XXX: could change encoding to have one more bit in hash */ - uint32_t hash : 29; - uint8_t kind : 1; - uint8_t atom_type : 2; /* != 0 if atom, JS_ATOM_TYPE_x */ + uint32_t hash : 28; + uint32_t kind : 2; + uint32_t atom_type : 2; /* != 0 if atom, JS_ATOM_TYPE_x */ uint32_t hash_next; /* atom_index for JS_ATOM_TYPE_SYMBOL */ JSWeakRefRecord *first_weak_ref; #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS @@ -583,9 +637,19 @@ typedef struct JSStringSlice { uint32_t start; // in bytes, not characters } JSStringSlice; +struct JSStringRope { + JSRefCountHeader header; /* must come first, 32-bit */ + uint32_t len; + uint8_t is_wide_char; /* 0 = 8 bits, 1 = 16 bits characters */ + uint8_t depth; /* max depth of the rope tree */ + JSValue left; + JSValue right; /* might be the empty string */ +}; + static inline void *strv(JSString *p) { JSStringSlice *slice; + void **indirect; switch (p->kind) { case JS_STRING_KIND_NORMAL: @@ -593,6 +657,9 @@ static inline void *strv(JSString *p) case JS_STRING_KIND_SLICE: slice = (void *)&p[1]; return (char *)&slice->parent[1] + slice->start; + case JS_STRING_KIND_INDIRECT: + indirect = (void *)&p[1]; + return *indirect; } abort(); return NULL; @@ -608,14 +675,25 @@ static inline uint16_t *str16(JSString *p) return strv(p); } +typedef enum { + JS_CLOSURE_LOCAL, /* 'var_idx' is the index of a local variable in the parent function */ + JS_CLOSURE_ARG, /* 'var_idx' is the index of an argument variable in the parent function */ + JS_CLOSURE_REF, /* 'var_idx' is the index of a closure variable in the parent function */ + JS_CLOSURE_GLOBAL_REF, /* 'var_idx' is the index of a closure variable in the parent + function referencing a global variable */ + JS_CLOSURE_GLOBAL_DECL, /* global variable declaration (eval code only) */ + JS_CLOSURE_GLOBAL, /* global variable (eval code only) */ + JS_CLOSURE_MODULE_DECL, /* definition of a module variable (eval code only) */ + JS_CLOSURE_MODULE_IMPORT, /* definition of a module import (eval code only) */ +} JSClosureTypeEnum; + typedef struct JSClosureVar { - uint8_t is_local : 1; - uint8_t is_arg : 1; - uint8_t is_const : 1; - uint8_t is_lexical : 1; + uint8_t closure_type : 3; /* see JSClosureTypeEnum */ + uint8_t is_lexical : 1; /* lexical variable */ + uint8_t is_const : 1; /* const variable (is_lexical = 1 if is_const = 1) */ uint8_t var_kind : 4; /* see JSVarKindEnum */ - /* 8 bits available */ - uint16_t var_idx; /* is_local = true: index to a normal variable of the + /* 7 bits available */ + uint16_t var_idx; /* JS_CLOSURE_LOCAL/JS_CLOSURE_ARG: index to a normal variable of the parent function. otherwise: index to a closure variable of the parent function */ JSAtom var_name; @@ -627,6 +705,10 @@ typedef struct JSClosureVar { typedef struct JSVarScope { int parent; /* index into fd->scopes of the enclosing scope */ int first; /* index into fd->vars of the last variable in this scope */ + uint8_t has_using : 1; /* scope has using declarations */ + uint8_t is_await_using : 1; /* scope has await using declarations */ + int using_label_catch; /* label for catch handler (-1 if none) */ + int using_label_end; /* label for end of disposal block (-1 if none) */ } JSVarScope; typedef enum { @@ -642,6 +724,10 @@ typedef enum { JS_VAR_PRIVATE_GETTER, JS_VAR_PRIVATE_SETTER, /* must come after JS_VAR_PRIVATE_GETTER */ JS_VAR_PRIVATE_GETTER_SETTER, /* must come after JS_VAR_PRIVATE_SETTER */ + JS_VAR_USING, /* using declaration variable */ + JS_VAR_USING_METHOD, /* hidden local holding the cached dispose method + for the preceding JS_VAR_USING var (always + allocated immediately after it). */ } JSVarKindEnum; /* XXX: could use a different structure in bytecode functions to save @@ -664,14 +750,17 @@ typedef struct JSVarDef { uint8_t is_captured : 1; uint8_t is_static_private : 1; /* only used during private class field parsing */ uint8_t var_kind : 4; /* see JSVarKindEnum */ + /* if is_captured = true, provides the index of the corresponding + JSVarRef on stack */ + uint16_t var_ref_idx; /* only used during compilation: function pool index for lexical variables with var_kind = JS_VAR_FUNCTION_DECL/JS_VAR_NEW_FUNCTION_DECL or scope level of the definition of the 'var' variables (they have scope_level = 0) */ - int func_pool_idx : 24; /* only used during compilation : index in - the constant pool for hoisted function - definition */ + int func_pool_idx; /* only used during compilation : index in + the constant pool for hoisted function + definition */ } JSVarDef; /* for the encoding of the pc2line table */ @@ -711,10 +800,11 @@ typedef struct JSFunctionBytecode { uint16_t var_count; uint16_t defined_arg_count; /* for length function property */ uint16_t stack_size; /* maximum stack size */ + uint16_t var_ref_count; /* number of local variable references */ + uint16_t closure_var_count; + int cpool_count; JSContext *realm; /* function realm */ JSValue *cpool; /* constant pool (self pointer) */ - int cpool_count; - int closure_var_count; JSAtom filename; int line_num; int col_num; @@ -772,6 +862,7 @@ typedef struct JSArrayBuffer { int byte_length; /* 0 if detached */ int max_byte_length; /* -1 if not resizable; >= byte_length otherwise */ uint8_t detached; + uint8_t immutable; uint8_t shared; /* if shared, the array buffer cannot be detached */ uint8_t *data; /* NULL if detached */ struct list_head array_list; @@ -807,6 +898,7 @@ typedef struct JSAsyncFunctionData { typedef struct JSReqModuleEntry { JSAtom module_name; JSModuleDef *module; /* used using resolution */ + JSValue attributes; /* JS_UNDEFINED or an object containing the attributes as key/value */ } JSReqModuleEntry; typedef enum JSExportTypeEnum { @@ -893,6 +985,7 @@ struct JSModuleDef { bool eval_has_exception; JSValue eval_exception; JSValue meta_obj; /* for import.meta */ + JSValue private_value; /* private value for C modules */ }; typedef struct JSJobEntry { @@ -923,7 +1016,6 @@ typedef struct JSProperty { #define JS_PROP_INITIAL_SIZE 2 #define JS_PROP_INITIAL_HASH_SIZE 4 /* must be a power of two */ -#define JS_ARRAY_INITIAL_SIZE 2 typedef struct JSShapeProperty { uint32_t hash_next : 26; /* 0 if last in list */ @@ -938,10 +1030,6 @@ struct JSShape { /* true if the shape is inserted in the shape hash table. If not, JSShape.hash is not valid */ uint8_t is_hashed; - /* If true, the shape may have small array index properties 'n' with 0 - <= n <= 2^31-1. If false, the shape is guaranteed not to have - small array index properties */ - uint8_t has_small_array_index; uint32_t hash; /* current hash value */ uint32_t prop_hash_mask; int prop_size; /* allocated properties */ @@ -957,12 +1045,13 @@ struct JSObject { JSGCObjectHeader header; struct { int __gc_ref_count; /* corresponds to header.ref_count */ - uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */ + uint8_t __gc_mark : 7; /* corresponds to header.mark/gc_obj_type */ + uint8_t is_prototype : 1; /* object may be used as prototype */ uint8_t extensible : 1; uint8_t free_mark : 1; /* only used when freeing objects with cycles */ uint8_t is_exotic : 1; /* true if object has exotic property handlers */ - uint8_t fast_array : 1; /* true if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS and typed arrays) */ + uint8_t fast_array : 1; /* true if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, JS_CLASS_MAPPED_ARGUMENTS and typed arrays) */ uint8_t is_constructor : 1; /* true if object is a constructor function */ uint8_t is_uncatchable_error : 1; /* if true, error is not catchable */ uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */ @@ -980,6 +1069,7 @@ struct JSObject { void *opaque; struct JSBoundFunction *bound_function; /* JS_CLASS_BOUND_FUNCTION */ struct JSCFunctionDataRecord *c_function_data_record; /* JS_CLASS_C_FUNCTION_DATA */ + struct JSCClosureRecord *c_closure_record; /* JS_CLASS_C_CLOSURE */ struct JSForInIterator *for_in_iterator; /* JS_CLASS_FOR_IN_ITERATOR */ struct JSArrayBuffer *array_buffer; /* JS_CLASS_ARRAY_BUFFER, JS_CLASS_SHARED_ARRAY_BUFFER */ struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_DATAVIEW */ @@ -1011,13 +1101,14 @@ struct JSObject { int16_t magic; } cfunc; /* array part for fast arrays and typed arrays */ - struct { /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ + struct { /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, JS_CLASS_MAPPED_ARGUMENTS, JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ union { - uint32_t size; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ + uint32_t size; /* JS_CLASS_ARRAY */ struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ } u1; union { JSValue *values; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ + JSVarRef **var_refs; /* JS_CLASS_MAPPED_ARGUMENTS */ void *ptr; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ int8_t *int8_ptr; /* JS_CLASS_INT8_ARRAY */ uint8_t *uint8_ptr; /* JS_CLASS_UINT8_ARRAY, JS_CLASS_UINT8C_ARRAY */ @@ -1055,7 +1146,7 @@ enum { #undef DEF JS_ATOM_END, }; -#define JS_ATOM_LAST_KEYWORD JS_ATOM_super +#define JS_ATOM_LAST_KEYWORD JS_ATOM_using #define JS_ATOM_LAST_STRICT_KEYWORD JS_ATOM_yield static const char js_atom_init[] = @@ -1120,6 +1211,8 @@ static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen, JSValue val, bool is_array_ctor); static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj, JSValueConst val, int flags, int scope_idx); +static JSValue js_new_suppressed_error(JSContext *ctx, JSValueConst error, + JSValueConst suppressed); static __maybe_unused void JS_DumpString(JSRuntime *rt, JSString *p); static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt); static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p); @@ -1133,6 +1226,9 @@ static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val, static void js_array_finalizer(JSRuntime *rt, JSValueConst val); static void js_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); +static void js_mapped_arguments_finalizer(JSRuntime *rt, JSValueConst val); +static void js_mapped_arguments_mark(JSRuntime *rt, JSValueConst val, + JS_MarkFunc *mark_func); static void js_object_data_finalizer(JSRuntime *rt, JSValueConst val); static void js_object_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); @@ -1187,6 +1283,9 @@ static void js_promise_mark(JSRuntime *rt, JSValueConst val, static void js_promise_resolve_function_finalizer(JSRuntime *rt, JSValueConst val); static void js_promise_resolve_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); +static void js_disposable_stack_finalizer(JSRuntime *rt, JSValueConst val); +static void js_disposable_stack_mark(JSRuntime *rt, JSValueConst val, + JS_MarkFunc *mark_func); #define HINT_STRING 0 #define HINT_NUMBER 1 @@ -1223,14 +1322,15 @@ typedef enum JSStrictEqModeEnum { JS_EQ_SAME_VALUE_ZERO, } JSStrictEqModeEnum; -static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, +static bool js_strict_eq2(JSContext *ctx, JSValueConst op1, JSValueConst op2, JSStrictEqModeEnum eq_mode); -static bool js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2); +static bool js_strict_eq(JSContext *ctx, JSValueConst op1, JSValueConst op2); static bool js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2); static bool js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2); static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val); static JSProperty *add_property(JSContext *ctx, JSObject *p, JSAtom prop, int prop_flags); +static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags); static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val); static JSValue JS_ThrowStackOverflow(JSContext *ctx); static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx); @@ -1268,12 +1368,17 @@ static JSValue js_typed_array_constructor_ta(JSContext *ctx, JSValueConst src_obj, int classid, uint32_t len); static bool is_typed_array(JSClassID class_id); +static bool typed_array_is_immutable(JSObject *p); static bool typed_array_is_oob(JSObject *p); static uint32_t typed_array_length(JSObject *p); +static int typed_array_init(JSContext *ctx, JSValue obj, JSValue buffer, + uint64_t offset, uint64_t len, bool track_rab); static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx); +static JSValue JS_ThrowTypeErrorImmutableArrayBuffer(JSContext *ctx); static JSValue JS_ThrowTypeErrorArrayBufferOOB(JSContext *ctx); static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx, bool is_arg); +static JSVarRef *js_create_var_ref(JSContext *ctx, bool is_gc_object); static JSValue js_call_generator_function(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv, @@ -1289,7 +1394,8 @@ static void js_free_module_def(JSContext *ctx, JSModuleDef *m); static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m, JS_MarkFunc *mark_func); static JSValue js_import_meta(JSContext *ctx); -static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier); +static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier, + JSValueConst options); static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref); static JSValue js_new_promise_capability(JSContext *ctx, JSValue *resolving_funcs, @@ -1313,10 +1419,14 @@ static bool JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val); static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val); static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, JSObject *p, JSAtom prop); +static int JS_GetOwnPropertyFlagsInternal(JSContext *ctx, int *pflags, + JSObject *p, JSAtom prop); +static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1, + int flags, int kind); static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc); static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s, JS_MarkFunc *mark_func); -static void JS_AddIntrinsicBasicObjects(JSContext *ctx); +static int JS_AddIntrinsicBasicObjects(JSContext *ctx); static void js_free_shape(JSRuntime *rt, JSShape *sh); static void js_free_shape_null(JSRuntime *rt, JSShape *sh); static int js_shape_prepare_update(JSContext *ctx, JSObject *p, @@ -1343,6 +1453,12 @@ static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val, static JSValue js_call_c_function_data(JSContext *ctx, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst *argv, int flags); +static void js_c_closure_finalizer(JSRuntime *rt, JSValueConst val); +static JSValue js_call_c_closure(JSContext *ctx, JSValueConst func_obj, + JSValueConst this_val, + int argc, JSValueConst *argv, int flags); +static JSAtom JS_ValueToAtomInternal(JSContext *ctx, JSValueConst val, + int flags); static JSAtom js_symbol_to_atom(JSContext *ctx, JSValueConst val); static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h, JSGCObjectTypeEnum type); @@ -1353,6 +1469,8 @@ static JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque); static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque); +static JSValue JS_NewObjectProtoList(JSContext *ctx, JSValueConst proto, + const JSCFunctionListEntry *fields, int n_fields); static void js_set_uncatchable_error(JSContext *ctx, JSValueConst val, bool flag); @@ -1360,7 +1478,7 @@ static void js_set_uncatchable_error(JSContext *ctx, JSValueConst val, static JSValue js_new_callsite(JSContext *ctx, JSCallSiteData *csd); static void js_new_callsite_data(JSContext *ctx, JSCallSiteData *csd, JSStackFrame *sf); static void js_new_callsite_data2(JSContext *ctx, JSCallSiteData *csd, const char *filename, int line_num, int col_num); -static void _JS_AddIntrinsicCallSite(JSContext *ctx); +static int _JS_AddIntrinsicCallSite(JSContext *ctx); static void JS_SetOpaqueInternal(JSValueConst obj, void *opaque); @@ -1427,6 +1545,12 @@ static JSValue js_number(double d) return js_float64(d); } +static JSValue __JS_NewShortBigInt(JSContext *ctx, int32_t d) +{ + (void)&ctx; + return JS_MKVAL(JS_TAG_SHORT_BIG_INT, d); +} + JSValue JS_NewNumber(JSContext *ctx, double d) { return js_number(d); @@ -1514,7 +1638,8 @@ void *js_malloc_rt(JSRuntime *rt, size_t size) JSMallocState *s; /* Do not allocate zero bytes: behavior is platform dependent */ - assert(size != 0); + if (unlikely(size == 0)) + return NULL; s = &rt->malloc_state; /* When malloc_limit is 0 (unlimited), malloc_limit - 1 will be SIZE_MAX. */ @@ -1538,8 +1663,13 @@ void js_free_rt(JSRuntime *rt, void *ptr) return; s = &rt->malloc_state; + size_t free_size = rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD; + if (unlikely(free_size > s->malloc_size)) { + printf("js_free_rt: malloc_size underflow: freeing %zu but only %zu tracked\n", free_size, s->malloc_size); + abort(); + } s->malloc_count--; - s->malloc_size -= rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD; + s->malloc_size -= free_size; rt->mf.js_free(s->opaque, ptr); } @@ -1739,13 +1869,14 @@ static JSClassShortDef const js_std_class_def[] = { { JS_ATOM_Boolean, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BOOLEAN */ { JS_ATOM_Symbol, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_SYMBOL */ { JS_ATOM_Arguments, js_array_finalizer, js_array_mark }, /* JS_CLASS_ARGUMENTS */ - { JS_ATOM_Arguments, NULL, NULL }, /* JS_CLASS_MAPPED_ARGUMENTS */ + { JS_ATOM_Arguments, js_mapped_arguments_finalizer, js_mapped_arguments_mark }, /* JS_CLASS_MAPPED_ARGUMENTS */ { JS_ATOM_Date, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_DATE */ { JS_ATOM_Object, NULL, NULL }, /* JS_CLASS_MODULE_NS */ { JS_ATOM_Function, js_c_function_finalizer, js_c_function_mark }, /* JS_CLASS_C_FUNCTION */ { JS_ATOM_Function, js_bytecode_function_finalizer, js_bytecode_function_mark }, /* JS_CLASS_BYTECODE_FUNCTION */ { JS_ATOM_Function, js_bound_function_finalizer, js_bound_function_mark }, /* JS_CLASS_BOUND_FUNCTION */ { JS_ATOM_Function, js_c_function_data_finalizer, js_c_function_data_mark }, /* JS_CLASS_C_FUNCTION_DATA */ + { JS_ATOM_Function, js_c_closure_finalizer, NULL}, /* JS_CLASS_C_CLOSURE */ { JS_ATOM_GeneratorFunction, js_bytecode_function_finalizer, js_bytecode_function_mark }, /* JS_CLASS_GENERATOR_FUNCTION */ { JS_ATOM_ForInIterator, js_for_in_iterator_finalizer, js_for_in_iterator_mark }, /* JS_CLASS_FOR_IN_ITERATOR */ { JS_ATOM_RegExp, js_regexp_finalizer, NULL }, /* JS_CLASS_REGEXP */ @@ -1779,6 +1910,7 @@ static JSClassShortDef const js_std_class_def[] = { { JS_ATOM_String_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_STRING_ITERATOR */ { JS_ATOM_RegExp_String_Iterator, js_regexp_string_iterator_finalizer, js_regexp_string_iterator_mark }, /* JS_CLASS_REGEXP_STRING_ITERATOR */ { JS_ATOM_Generator, js_generator_finalizer, js_generator_mark }, /* JS_CLASS_GENERATOR */ + { JS_ATOM_DisposableStack, js_disposable_stack_finalizer, js_disposable_stack_mark }, /* JS_CLASS_DISPOSABLE_STACK */ }; static int init_class_range(JSRuntime *rt, JSClassShortDef const *tab, @@ -1865,11 +1997,13 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque) countof(js_std_class_def)) < 0) goto fail; rt->class_array[JS_CLASS_ARGUMENTS].exotic = &js_arguments_exotic_methods; + rt->class_array[JS_CLASS_MAPPED_ARGUMENTS].exotic = &js_arguments_exotic_methods; rt->class_array[JS_CLASS_STRING].exotic = &js_string_exotic_methods; rt->class_array[JS_CLASS_MODULE_NS].exotic = &js_module_ns_exotic_methods; rt->class_array[JS_CLASS_C_FUNCTION].call = js_call_c_function; rt->class_array[JS_CLASS_C_FUNCTION_DATA].call = js_call_c_function_data; + rt->class_array[JS_CLASS_C_CLOSURE].call = js_call_c_closure; rt->class_array[JS_CLASS_BOUND_FUNCTION].call = js_call_bound_function; rt->class_array[JS_CLASS_GENERATOR_FUNCTION].call = js_call_generator_function; if (init_shape_hash(rt)) @@ -2028,6 +2162,14 @@ bool JS_IsJobPending(JSRuntime *rt) return !list_empty(&rt->job_list); } +JSContext *JS_GetPendingJobContext(JSRuntime *rt) +{ + if (JS_IsJobPending(rt)) { + return list_entry(rt->job_list.next, JSJobEntry, link)->ctx; + } + return NULL; +} + /* return < 0 if exception, 0 if no job pending, 1 if a job was executed successfully. the context of the job is stored in '*pctx' */ int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx) @@ -2116,15 +2258,22 @@ static inline void js_free_string(JSRuntime *rt, JSString *str) static inline void js_free_string0(JSRuntime *rt, JSString *str) { + JSStringSlice *slice; + if (str->atom_type) { JS_FreeAtomStruct(rt, str); } else { #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS list_del(&str->link); #endif - if (str->kind == JS_STRING_KIND_SLICE) { - JSStringSlice *slice = (void *)&str[1]; + switch (str->kind) { + case JS_STRING_KIND_SLICE: + slice = (void *)&str[1]; js_free_string(rt, slice->parent); // safe, recurses only 1 level + break; + case JS_STRING_KIND_INDIRECT: + js_free_rt(rt, strv(str)); + break; } js_free_rt(rt, str); } @@ -2139,6 +2288,7 @@ void JS_SetRuntimeInfo(JSRuntime *rt, const char *s) void JS_FreeRuntime(JSRuntime *rt) { struct list_head *el, *el1; + bool leak = false; int i; rt->in_free = true; @@ -2179,6 +2329,7 @@ void JS_FreeRuntime(JSRuntime *rt) header_done = true; } JS_DumpGCObject(rt, p); + leak = true; } } @@ -2255,6 +2406,7 @@ void JS_FreeRuntime(JSRuntime *rt) } else { printf("\n"); } + leak = true; } } } @@ -2303,6 +2455,7 @@ void JS_FreeRuntime(JSRuntime *rt) } if (rt->rt_info) printf("\n"); + leak = true; } #endif @@ -2322,14 +2475,20 @@ void JS_FreeRuntime(JSRuntime *rt) printf("Memory leak: %zd bytes lost in %zd block%s\n", s->malloc_size - sizeof(JSRuntime), s->malloc_count - 1, &"s"[s->malloc_count == 2]); + leak = true; } } #endif + leak &= check_dump_flag(rt, JS_ABORT_ON_LEAKS); + { JSMallocState *ms = &rt->malloc_state; rt->mf.js_free(ms->opaque, rt); } + + if (leak) + abort(); } JSContext *JS_NewContextRaw(JSRuntime *rt) @@ -2364,32 +2523,35 @@ JSContext *JS_NewContextRaw(JSRuntime *rt) ctx->error_stack_trace_limit = js_int32(10); init_list_head(&ctx->loaded_modules); - JS_AddIntrinsicBasicObjects(ctx); + if (JS_AddIntrinsicBasicObjects(ctx)) { + JS_FreeContext(ctx); + return NULL; + } return ctx; } JSContext *JS_NewContext(JSRuntime *rt) { JSContext *ctx; - ctx = JS_NewContextRaw(rt); if (!ctx) return NULL; - JS_AddIntrinsicBaseObjects(ctx); - JS_AddIntrinsicDate(ctx); - JS_AddIntrinsicEval(ctx); - JS_AddIntrinsicRegExp(ctx); - JS_AddIntrinsicJSON(ctx); - JS_AddIntrinsicProxy(ctx); - JS_AddIntrinsicMapSet(ctx); - JS_AddIntrinsicTypedArrays(ctx); - JS_AddIntrinsicPromise(ctx); - JS_AddIntrinsicBigInt(ctx); - JS_AddIntrinsicWeakRef(ctx); - JS_AddIntrinsicDOMException(ctx); - - JS_AddPerformance(ctx); + if (JS_AddIntrinsicBaseObjects(ctx) || + JS_AddIntrinsicDate(ctx) || + JS_AddIntrinsicEval(ctx) || + JS_AddIntrinsicRegExp(ctx) || + JS_AddIntrinsicJSON(ctx) || + JS_AddIntrinsicProxy(ctx) || + JS_AddIntrinsicMapSet(ctx) || + JS_AddIntrinsicTypedArrays(ctx) || + JS_AddIntrinsicPromise(ctx) || + JS_AddIntrinsicWeakRef(ctx) || + JS_AddIntrinsicAToB(ctx) || + JS_AddPerformance(ctx)) { + JS_FreeContext(ctx); + return NULL; + } return ctx; } @@ -2497,6 +2659,18 @@ static void JS_MarkContext(JSRuntime *rt, JSContext *ctx, if (ctx->array_shape) mark_func(rt, &ctx->array_shape->header); + + if (ctx->arguments_shape) + mark_func(rt, &ctx->arguments_shape->header); + + if (ctx->mapped_arguments_shape) + mark_func(rt, &ctx->mapped_arguments_shape->header); + + if (ctx->regexp_shape) + mark_func(rt, &ctx->regexp_shape->header); + + if (ctx->regexp_result_shape) + mark_func(rt, &ctx->regexp_result_shape->header); } void JS_FreeContext(JSContext *ctx) @@ -2567,6 +2741,10 @@ void JS_FreeContext(JSContext *ctx) JS_FreeValue(ctx, ctx->function_proto); js_free_shape_null(ctx->rt, ctx->array_shape); + js_free_shape_null(ctx->rt, ctx->arguments_shape); + js_free_shape_null(ctx->rt, ctx->mapped_arguments_shape); + js_free_shape_null(ctx->rt, ctx->regexp_shape); + js_free_shape_null(ctx->rt, ctx->regexp_result_shape); list_del(&ctx->link); remove_gc_object(&ctx->header); @@ -2707,6 +2885,17 @@ static uint32_t hash_string(JSString *str, uint32_t h) return h; } +static uint32_t hash_string_rope(JSValueConst val, uint32_t h) +{ + if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) { + return hash_string(JS_VALUE_GET_STRING(val), h); + } else { + JSStringRope *r = JS_VALUE_GET_STRING_ROPE(val); + h = hash_string_rope(r->left, h); + return hash_string_rope(r->right, h); + } +} + static __maybe_unused void JS_DumpString(JSRuntime *rt, JSString *p) { int i, c, sep; @@ -2813,7 +3002,7 @@ static int JS_InitAtoms(JSRuntime *rt) rt->atom_count = 0; rt->atom_size = 0; rt->atom_free_index = 0; - if (JS_ResizeAtomHash(rt, 256)) /* there are at least 195 predefined atoms */ + if (JS_ResizeAtomHash(rt, 512)) /* there are at least 504 predefined atoms */ return -1; p = js_atom_init; @@ -2832,7 +3021,7 @@ static int JS_InitAtoms(JSRuntime *rt) return 0; } -static JSAtom JS_DupAtomRT(JSRuntime *rt, JSAtom v) +JSAtom JS_DupAtomRT(JSRuntime *rt, JSAtom v) { JSAtomStruct *p; @@ -2955,9 +3144,9 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) /* alloc new with size progression 3/2: 4 6 9 13 19 28 42 63 94 141 211 316 474 711 1066 1599 2398 3597 5395 8092 - preallocating space for predefined atoms (at least 195). + preallocating space for predefined atoms (at least 504). */ - new_size = max_int(211, rt->atom_size * 3 / 2); + new_size = max_int(711, rt->atom_size * 3 / 2); if (new_size > JS_ATOM_MAX) goto fail; /* XXX: should use realloc2 to use slack space */ @@ -3247,10 +3436,23 @@ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr, /* `description` may be pure ASCII or UTF-8 encoded */ JSValue JS_NewSymbol(JSContext *ctx, const char *description, bool is_global) { + if (description == NULL) { + if (!is_global) { + /* Local symbol without description: Symbol() */ + return JS_NewSymbolInternal(ctx, NULL, JS_ATOM_TYPE_SYMBOL); + } + /* Global symbol without description: Symbol.for() + Per ES spec, ToString(undefined) becomes "undefined" */ + description = "undefined"; + } JSAtom atom = JS_NewAtom(ctx, description); if (atom == JS_ATOM_NULL) return JS_EXCEPTION; - return JS_NewSymbolFromAtom(ctx, atom, is_global ? JS_ATOM_TYPE_GLOBAL_SYMBOL : JS_ATOM_TYPE_SYMBOL); + int atom_type = + is_global ? JS_ATOM_TYPE_GLOBAL_SYMBOL : JS_ATOM_TYPE_SYMBOL; + JSValue symbol = JS_NewSymbolFromAtom(ctx, atom, atom_type); + JS_FreeAtom(ctx, atom); + return symbol; } #define ATOM_GET_STR_BUF_SIZE 64 @@ -3893,7 +4095,7 @@ static no_inline int string_buffer_realloc(StringBuffer *s, int new_len, int c) return 0; } -static no_inline int string_buffer_putc_slow(StringBuffer *s, uint32_t c) +static no_inline int string_buffer_putc16_slow(StringBuffer *s, uint32_t c) { if (unlikely(s->len >= s->size)) { if (string_buffer_realloc(s, s->len + 1, c)) @@ -3938,13 +4140,13 @@ static int string_buffer_putc16(StringBuffer *s, uint32_t c) return 0; } } - return string_buffer_putc_slow(s, c); + return string_buffer_putc16_slow(s, c); } /* 0 <= c <= 0x10ffff */ -static int string_buffer_putc(StringBuffer *s, uint32_t c) +static no_inline int string_buffer_putc_slow(StringBuffer *s, uint32_t c) { - if (unlikely(c >= 0x10000)) { + if (c >= 0x10000) { /* surrogate pair */ if (string_buffer_putc16(s, get_hi_surrogate(c))) return -1; @@ -3953,6 +4155,28 @@ static int string_buffer_putc(StringBuffer *s, uint32_t c) return string_buffer_putc16(s, c); } +/* 0 <= c <= 0x10ffff */ +static inline int string_buffer_putc(StringBuffer *s, uint32_t c) +{ + if (likely(s->len < s->size)) { + if (s->is_wide_char) { + if (c < 0x10000) { + str16(s->str)[s->len++] = c; + return 0; + } else if (s->len + 1 < s->size) { + /* surrogate pair */ + str16(s->str)[s->len++] = get_hi_surrogate(c); + str16(s->str)[s->len++] = get_lo_surrogate(c); + return 0; + } + } else if (c < 0x100) { + str8(s->str)[s->len++] = c; + return 0; + } + } + return string_buffer_putc_slow(s, c); +} + static int string_getc(JSString *p, int *pidx) { int idx, c, c1; @@ -4041,12 +4265,21 @@ static int string_buffer_concat_value(StringBuffer *s, JSValueConst v) JSString *p; JSValue v1; int res; + int tag; if (s->error_status) { /* prevent exception overload */ return -1; } - if (unlikely(JS_VALUE_GET_TAG(v) != JS_TAG_STRING)) { + tag = JS_VALUE_GET_TAG(v); + if (tag == JS_TAG_STRING_ROPE) { + /* recursively concatenate rope children */ + JSStringRope *r = JS_VALUE_GET_STRING_ROPE(v); + if (string_buffer_concat_value(s, r->left)) + return -1; + return string_buffer_concat_value(s, r->right); + } + if (unlikely(tag != JS_TAG_STRING)) { v1 = JS_ToString(s->ctx, v); if (JS_IsException(v1)) return string_buffer_set_error(s); @@ -4063,13 +4296,21 @@ static int string_buffer_concat_value_free(StringBuffer *s, JSValue v) { JSString *p; int res; + int tag; if (s->error_status) { /* prevent exception overload */ JS_FreeValue(s->ctx, v); return -1; } - if (unlikely(JS_VALUE_GET_TAG(v) != JS_TAG_STRING)) { + tag = JS_VALUE_GET_TAG(v); + if (tag == JS_TAG_STRING_ROPE) { + /* concatenate rope (don't free since concat_value doesn't free) */ + res = string_buffer_concat_value(s, v); + JS_FreeValue(s->ctx, v); + return res; + } + if (unlikely(tag != JS_TAG_STRING)) { v = JS_ToStringFree(s->ctx, v); if (JS_IsException(v)) return string_buffer_set_error(s); @@ -4133,18 +4374,18 @@ JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len) size_t len; int kind; - if (buf_len <= 0) { + if (unlikely(buf_len <= 0)) return js_empty_string(ctx->rt); - } + /* Compute string kind and length: 7-bit, 8-bit, 16-bit, 16-bit UTF-16 */ kind = utf8_scan(buf, buf_len, &len); - if (len > JS_STRING_LEN_MAX) + if (unlikely(len > JS_STRING_LEN_MAX)) return JS_ThrowRangeError(ctx, "invalid string length"); switch (kind) { case UTF8_PLAIN_ASCII: str = js_alloc_string(ctx, len, 0); - if (!str) + if (unlikely(!str)) return JS_EXCEPTION; memcpy(str8(str), buf, len); str8(str)[len] = '\0'; @@ -4152,7 +4393,7 @@ JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len) case UTF8_NON_ASCII: /* buf contains non-ASCII code-points, but limited to 8-bit values */ str = js_alloc_string(ctx, len, 0); - if (!str) + if (unlikely(!str)) return JS_EXCEPTION; utf8_decode_buf8(str8(str), len + 1, buf, buf_len); break; @@ -4161,7 +4402,7 @@ JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len) //if (kind & UTF8_HAS_ERRORS) // return JS_ThrowRangeError(ctx, "invalid UTF-8 sequence"); str = js_alloc_string(ctx, len, 1); - if (!str) + if (unlikely(!str)) return JS_EXCEPTION; utf8_decode_buf16(str16(str), len, buf, buf_len); break; @@ -4169,14 +4410,17 @@ JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len) return JS_MKPTR(JS_TAG_STRING, str); } -JSValue JS_NewTwoByteString(JSContext *ctx, const uint16_t *buf, size_t len) +JSValue JS_NewStringUTF16(JSContext *ctx, const uint16_t *buf, size_t len) { JSString *str; - if (!len) + if (unlikely(!len)) return js_empty_string(ctx->rt); + if (unlikely(len > JS_STRING_LEN_MAX)) + return JS_ThrowRangeError(ctx, "invalid string length"); + str = js_alloc_string(ctx, len, 1); - if (!str) + if (unlikely(!str)) return JS_EXCEPTION; memcpy(str16(str), buf, len * sizeof(*buf)); return JS_MKPTR(JS_TAG_STRING, str); @@ -4224,45 +4468,47 @@ JSValue JS_NewAtomString(JSContext *ctx, const char *str) return val; } -/* return (NULL, 0) if exception. */ -/* return pointer into a JSString with a live ref_count */ -/* cesu8 determines if non-BMP1 codepoints are encoded as 1 or 2 utf-8 sequences */ -const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, - bool cesu8) +static JSValue js_force_tostring(JSContext *ctx, JSValueConst val1) { - JSValue val; - JSString *str, *str_new; - int pos, len, c, c1; JSObject *p; - uint8_t *q; - - if (JS_VALUE_GET_TAG(val1) == JS_TAG_STRING) { - val = js_dup(val1); - goto go; - } + JSValue val; + if (JS_VALUE_GET_TAG(val1) == JS_TAG_STRING) + return js_dup(val1); val = JS_ToString(ctx, val1); if (!JS_IsException(val)) - goto go; - + return val; // Stringification can fail when there is an exception pending, // e.g. a stack overflow InternalError. Special-case exception // objects to make debugging easier, look up the .message property // and stringify that. if (JS_VALUE_GET_TAG(val1) != JS_TAG_OBJECT) - goto fail; - + return JS_EXCEPTION; p = JS_VALUE_GET_OBJ(val1); if (p->class_id != JS_CLASS_ERROR) - goto fail; - + return JS_EXCEPTION; val = JS_GetProperty(ctx, val1, JS_ATOM_message); if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING) { JS_FreeValue(ctx, val); - goto fail; + return JS_EXCEPTION; } + return val; +} -go: +/* return (NULL, 0) if exception. */ +/* return pointer into a JSString with a live ref_count */ +/* cesu8 determines if non-BMP1 codepoints are encoded as 1 or 2 utf-8 sequences */ +const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, + bool cesu8) +{ + JSValue val; + JSString *str, *str_new; + int pos, len, c, c1; + uint8_t *q; + + val = js_force_tostring(ctx, val1); + if (JS_IsException(val)) + goto fail; str = JS_VALUE_GET_STRING(val); len = str->len; if (!str->is_wide_char) { @@ -4338,18 +4584,68 @@ const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, if (plen) *plen = str_new->len; return (const char *)str8(str_new); - fail: +fail: if (plen) *plen = 0; return NULL; } -void JS_FreeCString(JSContext *ctx, const char *ptr) +const uint16_t *JS_ToCStringLenUTF16(JSContext *ctx, size_t *plen, + JSValueConst val1) +{ + JSString *p, *q; + uint32_t i; + JSValue v; + + v = js_force_tostring(ctx, val1); + if (JS_IsException(v)) + goto fail; + p = JS_VALUE_GET_STRING(v); + if (!p->is_wide_char) { + q = js_alloc_string(ctx, p->len, /*is_wide_char*/true); + if (!q) + goto fail; + for (i = 0; i < p->len; i++) + str16(q)[i] = str8(p)[i]; + JS_FreeValue(ctx, v); + p = q; + } + if (plen) + *plen = p->len; + return str16(p); +fail: + JS_FreeValue(ctx, v); + if (plen) + *plen = 0; + return NULL; +} + +static void js_free_cstring(JSRuntime *rt, const void *ptr) { if (!ptr) return; /* purposely removing constness */ - JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, (JSString *)ptr - 1)); + JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_STRING, (JSString *)ptr - 1)); +} + +void JS_FreeCString(JSContext *ctx, const char *ptr) +{ + return js_free_cstring(ctx->rt, ptr); +} + +void JS_FreeCStringRT(JSRuntime *rt, const char *ptr) +{ + return js_free_cstring(rt, ptr); +} + +void JS_FreeCStringUTF16(JSContext *ctx, const uint16_t *ptr) +{ + return js_free_cstring(ctx->rt, ptr); +} + +void JS_FreeCStringRT_UTF16(JSRuntime *rt, const uint16_t *ptr) +{ + return js_free_cstring(rt, ptr); } static int memcmp16_8(const uint16_t *src1, const uint8_t *src2, int len) @@ -4409,6 +4705,352 @@ static int js_string_compare(JSString *p1, JSString *p2) return res; } +/* Rope string support functions */ + +static inline bool tag_is_string(int tag) +{ + return tag == JS_TAG_STRING || tag == JS_TAG_STRING_ROPE; +} + +static uint32_t string_rope_get_len(JSValueConst val) +{ + if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) + return JS_VALUE_GET_STRING(val)->len; + else + return JS_VALUE_GET_STRING_ROPE(val)->len; +} + +static int string_rope_get(JSValueConst val, uint32_t idx) +{ + if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) { + return string_get(JS_VALUE_GET_STRING(val), idx); + } else { + JSStringRope *r = JS_VALUE_GET_STRING_ROPE(val); + uint32_t len; + if (JS_VALUE_GET_TAG(r->left) == JS_TAG_STRING) + len = JS_VALUE_GET_STRING(r->left)->len; + else + len = JS_VALUE_GET_STRING_ROPE(r->left)->len; + if (idx < len) + return string_rope_get(r->left, idx); + else + return string_rope_get(r->right, idx - len); + } +} + +typedef struct { + JSValueConst stack[JS_STRING_ROPE_MAX_DEPTH]; + int stack_len; +} JSStringRopeIter; + +static void string_rope_iter_init(JSStringRopeIter *s, JSValueConst val) +{ + s->stack_len = 0; + s->stack[s->stack_len++] = val; +} + +/* iterate thru a rope and return the strings in order */ +static JSString *string_rope_iter_next(JSStringRopeIter *s) +{ + JSValueConst val; + JSStringRope *r; + + if (s->stack_len == 0) + return NULL; + val = s->stack[--s->stack_len]; + for(;;) { + if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) + return JS_VALUE_GET_STRING(val); + r = JS_VALUE_GET_STRING_ROPE(val); + assert(s->stack_len < JS_STRING_ROPE_MAX_DEPTH); + s->stack[s->stack_len++] = r->right; + val = r->left; + } +} + +/* compare two string values with position offsets */ +static int js_string_memcmp_pos(JSString *p1, uint32_t pos1, + JSString *p2, uint32_t pos2, uint32_t len) +{ + int res; + + if (likely(!p1->is_wide_char)) { + if (likely(!p2->is_wide_char)) + res = memcmp(str8(p1) + pos1, str8(p2) + pos2, len); + else + res = -memcmp16_8(str16(p2) + pos2, str8(p1) + pos1, len); + } else { + if (!p2->is_wide_char) + res = memcmp16_8(str16(p1) + pos1, str8(p2) + pos2, len); + else + res = memcmp16(str16(p1) + pos1, str16(p2) + pos2, len); + } + return res; +} + +static int js_string_rope_compare(JSValueConst op1, + JSValueConst op2, bool eq_only) +{ + uint32_t len1, len2, len, pos1, pos2, l; + int res; + JSStringRopeIter it1, it2; + JSString *p1, *p2; + + len1 = string_rope_get_len(op1); + len2 = string_rope_get_len(op2); + /* no need to go further for equality test if different length */ + if (eq_only && len1 != len2) + return 1; + len = min_uint32(len1, len2); + string_rope_iter_init(&it1, op1); + string_rope_iter_init(&it2, op2); + p1 = string_rope_iter_next(&it1); + p2 = string_rope_iter_next(&it2); + pos1 = 0; + pos2 = 0; + while (len != 0) { + l = min_uint32(p1->len - pos1, p2->len - pos2); + l = min_uint32(l, len); + res = js_string_memcmp_pos(p1, pos1, p2, pos2, l); + if (res != 0) + return res; + len -= l; + pos1 += l; + if (pos1 >= p1->len) { + p1 = string_rope_iter_next(&it1); + pos1 = 0; + } + pos2 += l; + if (pos2 >= p2->len) { + p2 = string_rope_iter_next(&it2); + pos2 = 0; + } + } + + if (len1 == len2) + res = 0; + else if (len1 < len2) + res = -1; + else + res = 1; + return res; +} + +/* forward declaration */ +static int string_buffer_concat_value(StringBuffer *s, JSValueConst v); +static JSValue js_rebalance_string_rope(JSContext *ctx, JSValueConst rope); + +/* op1 and op2 must be strings or string ropes */ +static JSValue js_new_string_rope(JSContext *ctx, JSValue op1, JSValue op2) +{ + uint32_t len; + int is_wide_char, depth; + JSStringRope *r; + JSValue res; + + if (JS_VALUE_GET_TAG(op1) == JS_TAG_STRING) { + JSString *p1 = JS_VALUE_GET_STRING(op1); + len = p1->len; + is_wide_char = p1->is_wide_char; + depth = 0; + } else { + JSStringRope *r1 = JS_VALUE_GET_STRING_ROPE(op1); + len = r1->len; + is_wide_char = r1->is_wide_char; + depth = r1->depth; + } + + if (JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) { + JSString *p2 = JS_VALUE_GET_STRING(op2); + len += p2->len; + is_wide_char |= p2->is_wide_char; + } else { + JSStringRope *r2 = JS_VALUE_GET_STRING_ROPE(op2); + len += r2->len; + is_wide_char |= r2->is_wide_char; + depth = max_int(depth, r2->depth); + } + if (len > JS_STRING_LEN_MAX) { + JS_ThrowInternalError(ctx, "string too long"); + goto fail; + } + r = js_malloc(ctx, sizeof(*r)); + if (!r) + goto fail; + r->header.ref_count = 1; + r->len = len; + r->is_wide_char = is_wide_char; + r->depth = depth + 1; + r->left = op1; + r->right = op2; + res = JS_MKPTR(JS_TAG_STRING_ROPE, r); + if (r->depth > JS_STRING_ROPE_MAX_DEPTH) { + JSValue res2; +#ifdef DUMP_ROPE_REBALANCE + printf("rebalance: initial depth=%d\n", r->depth); +#endif + res2 = js_rebalance_string_rope(ctx, res); +#ifdef DUMP_ROPE_REBALANCE + if (JS_VALUE_GET_TAG(res2) == JS_TAG_STRING_ROPE) + printf("rebalance: final depth=%d\n", JS_VALUE_GET_STRING_ROPE(res2)->depth); +#endif + JS_FreeValue(ctx, res); + return res2; + } else { + return res; + } + fail: + JS_FreeValue(ctx, op1); + JS_FreeValue(ctx, op2); + return JS_EXCEPTION; +} + +#define ROPE_N_BUCKETS 44 + +/* Fibonacci numbers starting from F_2 */ +static const uint32_t rope_bucket_len[ROPE_N_BUCKETS] = { + 1, 2, 3, 5, + 8, 13, 21, 34, + 55, 89, 144, 233, + 377, 610, 987, 1597, + 2584, 4181, 6765, 10946, + 17711, 28657, 46368, 75025, + 121393, 196418, 317811, 514229, + 832040, 1346269, 2178309, 3524578, + 5702887, 9227465, 14930352, 24157817, + 39088169, 63245986, 102334155, 165580141, + 267914296, 433494437, 701408733, 1134903170, /* > JS_STRING_LEN_MAX */ +}; + +static int js_rebalance_string_rope_rec(JSContext *ctx, JSValue *buckets, + JSValueConst val) +{ + if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) { + JSString *p = JS_VALUE_GET_STRING(val); + uint32_t len, i; + JSValue a, b; + + len = p->len; + if (len == 0) + return 0; /* nothing to do */ + /* find the bucket i so that rope_bucket_len[i] <= len < + rope_bucket_len[i + 1] and concatenate the ropes in the + buckets before */ + a = JS_NULL; + i = 0; + while (len >= rope_bucket_len[i + 1]) { + b = buckets[i]; + if (!JS_IsNull(b)) { + buckets[i] = JS_NULL; + if (JS_IsNull(a)) { + a = b; + } else { + a = js_new_string_rope(ctx, b, a); + if (JS_IsException(a)) + return -1; + } + } + i++; + } + if (!JS_IsNull(a)) { + a = js_new_string_rope(ctx, a, js_dup(val)); + if (JS_IsException(a)) + return -1; + } else { + a = js_dup(val); + } + while (!JS_IsNull(buckets[i])) { + a = js_new_string_rope(ctx, buckets[i], a); + buckets[i] = JS_NULL; + if (JS_IsException(a)) + return -1; + i++; + } + buckets[i] = a; + } else { + JSStringRope *r = JS_VALUE_GET_STRING_ROPE(val); + if (js_rebalance_string_rope_rec(ctx, buckets, r->left)) + return -1; + if (js_rebalance_string_rope_rec(ctx, buckets, r->right)) + return -1; + } + return 0; +} + +/* Return a new rope which is balanced. Algorithm from "Ropes: an + Alternative to Strings", Hans-J. Boehm, Russ Atkinson and Michael + Plass. */ +static JSValue js_rebalance_string_rope(JSContext *ctx, JSValueConst rope) +{ + JSValue buckets[ROPE_N_BUCKETS], a, b; + int i; + + for(i = 0; i < ROPE_N_BUCKETS; i++) + buckets[i] = JS_NULL; + if (js_rebalance_string_rope_rec(ctx, buckets, rope)) + goto fail; + a = JS_NULL; + for(i = 0; i < ROPE_N_BUCKETS; i++) { + b = buckets[i]; + if (!JS_IsNull(b)) { + buckets[i] = JS_NULL; + if (JS_IsNull(a)) { + a = b; + } else { + a = js_new_string_rope(ctx, b, a); + if (JS_IsException(a)) + goto fail; + } + } + } + /* fail safe */ + if (JS_IsNull(a)) + return JS_AtomToString(ctx, JS_ATOM_empty_string); + else + return a; + fail: + for(i = 0; i < ROPE_N_BUCKETS; i++) { + JS_FreeValue(ctx, buckets[i]); + } + return JS_EXCEPTION; +} + +/* 'rope' must be a rope. return a string and modify the rope so that + it won't need to be linearized again. */ +static JSValue js_linearize_string_rope(JSContext *ctx, JSValueConst rope) +{ + StringBuffer b_s, *b = &b_s; + JSStringRope *r; + JSValue ret; + + r = JS_VALUE_GET_STRING_ROPE(rope); + + /* check whether it is already linearized */ + if (JS_VALUE_GET_TAG(r->right) == JS_TAG_STRING && + JS_VALUE_GET_STRING(r->right)->len == 0) { + ret = js_dup(r->left); + return ret; + } + if (string_buffer_init2(ctx, b, r->len, r->is_wide_char)) + goto fail; + if (string_buffer_concat_value(b, rope)) + goto fail; + ret = string_buffer_end(b); + if (r->header.ref_count > 1) { + /* update the rope so that it won't need to be linearized again */ + JS_FreeValue(ctx, r->left); + JS_FreeValue(ctx, r->right); + r->left = js_dup(ret); + r->right = JS_AtomToString(ctx, JS_ATOM_empty_string); + } + return ret; + fail: + return JS_EXCEPTION; +} + +/* flat string concatenation - used by rope when concatenating short strings */ +static JSValue JS_ConcatString2(JSContext *ctx, JSValue op1, JSValue op2); + static void copy_str16(uint16_t *dst, JSString *p, int offset, int len) { if (p->is_wide_char) { @@ -4446,27 +5088,12 @@ static JSValue JS_ConcatString1(JSContext *ctx, JSString *p1, JSString *p2) return JS_MKPTR(JS_TAG_STRING, p); } -/* op1 and op2 are converted to strings. For convience, op1 or op2 = - JS_EXCEPTION are accepted and return JS_EXCEPTION. */ -static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2) +/* flat string concatenation - op1 and op2 must be JS_TAG_STRING */ +static JSValue JS_ConcatString2(JSContext *ctx, JSValue op1, JSValue op2) { JSValue ret; JSString *p1, *p2; - if (unlikely(JS_VALUE_GET_TAG(op1) != JS_TAG_STRING)) { - op1 = JS_ToStringFree(ctx, op1); - if (JS_IsException(op1)) { - JS_FreeValue(ctx, op2); - return JS_EXCEPTION; - } - } - if (unlikely(JS_VALUE_GET_TAG(op2) != JS_TAG_STRING)) { - op2 = JS_ToStringFree(ctx, op2); - if (JS_IsException(op2)) { - JS_FreeValue(ctx, op1); - return JS_EXCEPTION; - } - } p1 = JS_VALUE_GET_STRING(op1); p2 = JS_VALUE_GET_STRING(op2); @@ -4495,6 +5122,83 @@ static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2) return ret; } +/* op1 and op2 are converted to strings. For convenience, op1 or op2 = + JS_EXCEPTION are accepted and return JS_EXCEPTION. */ +static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2) +{ + JSString *p1, *p2; + + if (unlikely(!tag_is_string(JS_VALUE_GET_TAG(op1)))) { + op1 = JS_ToStringFree(ctx, op1); + if (JS_IsException(op1)) { + JS_FreeValue(ctx, op2); + return JS_EXCEPTION; + } + } + if (unlikely(!tag_is_string(JS_VALUE_GET_TAG(op2)))) { + op2 = JS_ToStringFree(ctx, op2); + if (JS_IsException(op2)) { + JS_FreeValue(ctx, op1); + return JS_EXCEPTION; + } + } + + /* normal concatenation for short strings */ + if (JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) { + p2 = JS_VALUE_GET_STRING(op2); + if (p2->len == 0) { + JS_FreeValue(ctx, op2); + return op1; + } + if (p2->len <= JS_STRING_ROPE_SHORT_LEN) { + if (JS_VALUE_GET_TAG(op1) == JS_TAG_STRING) { + p1 = JS_VALUE_GET_STRING(op1); + if (p1->len <= JS_STRING_ROPE_SHORT2_LEN) { + return JS_ConcatString2(ctx, op1, op2); + } else { + return js_new_string_rope(ctx, op1, op2); + } + } else { + JSStringRope *r1; + r1 = JS_VALUE_GET_STRING_ROPE(op1); + if (JS_VALUE_GET_TAG(r1->right) == JS_TAG_STRING && + JS_VALUE_GET_STRING(r1->right)->len <= JS_STRING_ROPE_SHORT_LEN) { + JSValue val, ret; + val = JS_ConcatString2(ctx, js_dup(r1->right), op2); + if (JS_IsException(val)) { + JS_FreeValue(ctx, op1); + return JS_EXCEPTION; + } + ret = js_new_string_rope(ctx, js_dup(r1->left), val); + JS_FreeValue(ctx, op1); + return ret; + } + } + } + } else if (JS_VALUE_GET_TAG(op1) == JS_TAG_STRING) { + JSStringRope *r2; + p1 = JS_VALUE_GET_STRING(op1); + if (p1->len == 0) { + JS_FreeValue(ctx, op1); + return op2; + } + r2 = JS_VALUE_GET_STRING_ROPE(op2); + if (JS_VALUE_GET_TAG(r2->left) == JS_TAG_STRING && + JS_VALUE_GET_STRING(r2->left)->len <= JS_STRING_ROPE_SHORT_LEN) { + JSValue val, ret; + val = JS_ConcatString2(ctx, op1, js_dup(r2->left)); + if (JS_IsException(val)) { + JS_FreeValue(ctx, op2); + return JS_EXCEPTION; + } + ret = js_new_string_rope(ctx, val, js_dup(r2->right)); + JS_FreeValue(ctx, op2); + return ret; + } + } + return js_new_string_rope(ctx, op1, op2); +} + /* Shape support */ static inline size_t get_shape_size(size_t hash_size, size_t prop_size) @@ -4518,11 +5222,6 @@ static inline void *get_alloc_from_shape(JSShape *sh) return prop_hash_end(sh) - ((intptr_t)sh->prop_hash_mask + 1); } -static inline JSShapeProperty *get_shape_prop(JSShape *sh) -{ - return sh->prop; -} - static int init_shape_hash(JSRuntime *rt) { rt->shape_hash_bits = 6; /* 64 shapes */ @@ -4538,7 +5237,7 @@ static int init_shape_hash(JSRuntime *rt) /* same magic hash multiplier as the Linux kernel */ static uint32_t shape_hash(uint32_t h, uint32_t val) { - return (h + val) * 0x9e370001; + return hash32(h + val); } /* truncate the shape hash to 'hash_bits' bits */ @@ -4604,19 +5303,14 @@ static void js_shape_hash_unlink(JSRuntime *rt, JSShape *sh) rt->shape_hash_count--; } -/* create a new empty shape with prototype 'proto' */ -static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, - int hash_size, int prop_size) +/* create a new empty shape with prototype 'proto'. It is not hashed */ +static inline JSShape *js_new_shape_nohash(JSContext *ctx, JSObject *proto, + int hash_size, int prop_size) { JSRuntime *rt = ctx->rt; void *sh_alloc; JSShape *sh; - /* resize the shape hash table if necessary */ - if (2 * (rt->shape_hash_count + 1) > rt->shape_hash_size) { - resize_shape_hash(rt, rt->shape_hash_bits + 1); - } - sh_alloc = js_malloc(ctx, get_shape_size(hash_size, prop_size)); if (!sh_alloc) return NULL; @@ -4632,11 +5326,29 @@ static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, sh->prop_size = prop_size; sh->prop_count = 0; sh->deleted_prop_count = 0; + sh->is_hashed = false; + return sh; +} + +/* create a new empty shape with prototype 'proto' */ +static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, + int hash_size, int prop_size) +{ + JSRuntime *rt = ctx->rt; + JSShape *sh; + + /* resize the shape hash table if necessary */ + if (2 * (rt->shape_hash_count + 1) > rt->shape_hash_size) { + resize_shape_hash(rt, rt->shape_hash_bits + 1); + } + + sh = js_new_shape_nohash(ctx, proto, hash_size, prop_size); + if (!sh) + return NULL; /* insert in the hash table */ sh->hash = shape_initial_hash(proto); sh->is_hashed = true; - sh->has_small_array_index = false; js_shape_hash_link(ctx->rt, sh); return sh; } @@ -4647,6 +5359,40 @@ static JSShape *js_new_shape(JSContext *ctx, JSObject *proto) JS_PROP_INITIAL_SIZE); } +static JSObject *object_or_null(JSValueConst val) +{ + if (JS_TAG_OBJECT == JS_VALUE_GET_TAG(val)) + return JS_VALUE_GET_OBJ(val); + return NULL; +} + +static int add_shape_property(JSContext *ctx, JSShape **psh, + JSObject *p, JSAtom atom, int prop_flags); + +static JSShape *js_new_shape_with2(JSContext *ctx, JSObject *proto, + int prop_count, const JSShapeProperty props[]) { + JSShape *sh; + int i; + + sh = js_new_shape2(ctx, proto, JS_PROP_INITIAL_HASH_SIZE, prop_count); + if (sh) + for (i = 0; i < prop_count; i++) + if (add_shape_property(ctx, &sh, NULL, props[i].atom, props[i].flags)) + goto fail; + return sh; +fail: + js_free_shape(ctx->rt, sh); + return NULL; +} + +static int js_new_shape_with(JSContext *ctx, JSShape **psh, JSValueConst proto, + int prop_count, const JSShapeProperty props[]) { + *psh = js_new_shape_with2(ctx, object_or_null(proto), prop_count, props); + if (*psh) + return 0; + return -1; +} + /* The shape is cloned. The new shape is not inserted in the shape hash table */ static JSShape *js_clone_shape(JSContext *ctx, JSShape *sh1) @@ -4671,7 +5417,7 @@ static JSShape *js_clone_shape(JSContext *ctx, JSShape *sh1) if (sh->proto) { js_dup(JS_MKPTR(JS_TAG_OBJECT, sh->proto)); } - for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { + for(i = 0, pr = sh->prop; i < sh->prop_count; i++, pr++) { JS_DupAtom(ctx, pr->atom); } return sh; @@ -4694,7 +5440,7 @@ static void js_free_shape0(JSRuntime *rt, JSShape *sh) if (sh->proto != NULL) { JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, sh->proto)); } - pr = get_shape_prop(sh); + pr = sh->prop; for(i = 0; i < sh->prop_count; i++) { JS_FreeAtomRT(rt, pr->atom); pr++; @@ -4882,11 +5628,10 @@ static int add_shape_property(JSContext *ctx, JSShape **psh, } /* Initialize the new shape property. The object property at p->prop[sh->prop_count] is uninitialized */ - prop = get_shape_prop(sh); + prop = sh->prop; pr = &prop[sh->prop_count++]; pr->atom = JS_DupAtom(ctx, atom); pr->flags = prop_flags; - sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom); /* add in hash table */ hash_mask = sh->prop_hash_mask; h = atom & hash_mask; @@ -4992,9 +5737,13 @@ static __maybe_unused void JS_DumpShapes(JSRuntime *rt) printf("}\n"); } -static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID class_id) +/* 'props[]' is used to initialized the object properties. The number + of elements depends on the shape. */ +static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID class_id, + JSProperty *props) { JSObject *p; + int i; js_trigger_gc(ctx->rt, sizeof(JSObject)); p = js_malloc(ctx, sizeof(JSObject)); @@ -5009,6 +5758,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas p->is_uncatchable_error = 0; p->tmp_mark = 0; p->is_HTMLDDA = 0; + p->is_prototype = 0; p->first_weak_ref = NULL; p->u.opaque = NULL; p->shape = sh; @@ -5016,6 +5766,13 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas if (unlikely(!p->prop)) { js_free(ctx, p); fail: + if (props) { + JSShapeProperty *prs = sh->prop; + for(i = 0; i < sh->prop_count; i++) { + free_property(ctx->rt, &props[i], prs->flags); + prs++; + } + } js_free_shape(ctx->rt, sh); return JS_EXCEPTION; } @@ -5031,22 +5788,26 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas p->u.array.u.values = NULL; p->u.array.count = 0; p->u.array.u1.size = 0; - /* the length property is always the first one */ - if (likely(sh == ctx->array_shape)) { - pr = &p->prop[0]; - } else { - /* only used for the first array */ - /* cannot fail */ - pr = add_property(ctx, p, JS_ATOM_length, - JS_PROP_WRITABLE | JS_PROP_LENGTH); + if (!props) { + /* XXX: remove */ + /* the length property is always the first one */ + if (likely(sh == ctx->array_shape)) { + pr = &p->prop[0]; + } else { + /* only used for the first array */ + /* cannot fail */ + pr = add_property(ctx, p, JS_ATOM_length, + JS_PROP_WRITABLE | JS_PROP_LENGTH); + } + pr->u.value = js_int32(0); } - pr->u.value = js_int32(0); } break; case JS_CLASS_C_FUNCTION: p->prop[0].u.value = JS_UNDEFINED; break; case JS_CLASS_ARGUMENTS: + case JS_CLASS_MAPPED_ARGUMENTS: case JS_CLASS_UINT8C_ARRAY: case JS_CLASS_INT8_ARRAY: case JS_CLASS_UINT8_ARRAY: @@ -5089,17 +5850,13 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas } p->header.ref_count = 1; add_gc_object(ctx->rt, &p->header, JS_GC_OBJ_TYPE_JS_OBJECT); + if (props) { + for(i = 0; i < sh->prop_count; i++) + p->prop[i] = props[i]; + } return JS_MKPTR(JS_TAG_OBJECT, p); } -static JSObject *get_proto_obj(JSValueConst proto_val) -{ - if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_OBJECT) - return NULL; - else - return JS_VALUE_GET_OBJ(proto_val); -} - /* WARNING: proto must be an object or JS_NULL */ JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto_val, JSClassID class_id) @@ -5107,7 +5864,7 @@ JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto_val, JSShape *sh; JSObject *proto; - proto = get_proto_obj(proto_val); + proto = object_or_null(proto_val); sh = find_hashed_shape_proto(ctx->rt, proto); if (likely(sh)) { sh = js_dup_shape(sh); @@ -5116,7 +5873,30 @@ JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto_val, if (!sh) return JS_EXCEPTION; } - return JS_NewObjectFromShape(ctx, sh, class_id); + return JS_NewObjectFromShape(ctx, sh, class_id, NULL); +} + +/* WARNING: the shape is not hashed. It is used for objects where + factorizing the shape is not relevant (prototypes, constructors) */ +static JSValue JS_NewObjectProtoClassAlloc(JSContext *ctx, JSValueConst proto_val, + JSClassID class_id, int n_alloc_props) +{ + JSShape *sh; + JSObject *proto; + int hash_size, hash_bits; + + if (n_alloc_props <= JS_PROP_INITIAL_SIZE) { + n_alloc_props = JS_PROP_INITIAL_SIZE; + hash_size = JS_PROP_INITIAL_HASH_SIZE; + } else { + hash_bits = 32 - clz32(n_alloc_props - 1); /* ceil(log2(radix)) */ + hash_size = 1 << hash_bits; + } + proto = object_or_null(proto_val); + sh = js_new_shape_nohash(ctx, proto, hash_size, n_alloc_props); + if (!sh) + return JS_EXCEPTION; + return JS_NewObjectFromShape(ctx, sh, class_id, NULL); } static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val) @@ -5133,7 +5913,8 @@ static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val) case JS_CLASS_DATE: case JS_CLASS_BIG_INT: JS_FreeValue(ctx, p->u.object_data); - p->u.object_data = val; + p->u.object_data = val; /* for JS_CLASS_STRING, 'val' must + be JS_TAG_STRING (and not a rope) */ return 0; } } @@ -5186,7 +5967,6 @@ JSValue JS_NewObjectFrom(JSContext *ctx, int count, const JSAtom *props, atom = props[i]; pr = &sh->prop[i]; sh->hash = shape_hash(shape_hash(sh->hash, atom), JS_PROP_C_W_E); - sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom); h = atom & sh->prop_hash_mask; hash = &prop_hash_end(sh)[-h - 1]; pr->hash_next = *hash; @@ -5234,7 +6014,7 @@ JSValue JS_NewObjectFromStr(JSContext *ctx, int count, const char **props, JSValue JS_NewArray(JSContext *ctx) { return JS_NewObjectFromShape(ctx, js_dup_shape(ctx->array_shape), - JS_CLASS_ARRAY); + JS_CLASS_ARRAY, NULL); } // note: takes ownership of |values|, unlike js_create_array @@ -5365,13 +6145,17 @@ static int js_method_set_properties(JSContext *ctx, JSValue func_obj, JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func, const char *name, int length, JSCFunctionEnum cproto, int magic, - JSValueConst proto_val) + JSValueConst proto_val, int n_fields) { JSValue func_obj; JSObject *p; JSAtom name_atom; - func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION); + if (n_fields > 0) { + func_obj = JS_NewObjectProtoClassAlloc(ctx, proto_val, JS_CLASS_C_FUNCTION, n_fields); + } else { + func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION); + } if (JS_IsException(func_obj)) return func_obj; p = JS_VALUE_GET_OBJ(func_obj); @@ -5403,7 +6187,7 @@ JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func, int length, JSCFunctionEnum cproto, int magic) { return JS_NewCFunction3(ctx, func, name, length, cproto, magic, - ctx->function_proto); + ctx->function_proto, 0); } typedef struct JSCFunctionDataRecord { @@ -5547,6 +6331,101 @@ static void js_autoinit_mark(JSRuntime *rt, JSProperty *pr, mark_func(rt, &js_autoinit_get_realm(pr)->header); } +typedef struct JSCClosureRecord { + JSCClosure *func; + uint16_t length; + uint16_t magic; + void *opaque; + void (*opaque_finalize)(void *opaque); +} JSCClosureRecord; + +static void js_c_closure_finalizer(JSRuntime *rt, JSValueConst val) +{ + JSCClosureRecord *s = JS_GetOpaque(val, JS_CLASS_C_CLOSURE); + + if (s) { + if (s->opaque_finalize) + s->opaque_finalize(s->opaque); + + js_free_rt(rt, s); + } +} + +static JSValue js_call_c_closure(JSContext *ctx, JSValueConst func_obj, + JSValueConst this_val, + int argc, JSValueConst *argv, int flags) +{ + JSRuntime *rt = ctx->rt; + JSStackFrame sf_s, *sf = &sf_s, *prev_sf; + JSCClosureRecord *s = JS_GetOpaque(func_obj, JS_CLASS_C_CLOSURE); + JSValueConst *arg_buf; + JSValue ret; + int arg_count; + int i; + size_t stack_size; + + arg_buf = argv; + arg_count = s->length; + if (unlikely(argc < arg_count)) { + stack_size = arg_count * sizeof(arg_buf[0]); + if (js_check_stack_overflow(rt, stack_size)) + return JS_ThrowStackOverflow(ctx); + arg_buf = alloca(stack_size); + for (i = 0; i < argc; i++) + arg_buf[i] = argv[i]; + for (i = argc; i < arg_count; i++) + arg_buf[i] = JS_UNDEFINED; + } + + prev_sf = rt->current_stack_frame; + sf->prev_frame = prev_sf; + rt->current_stack_frame = sf; + // TODO(bnoordhuis) switch realms like js_call_c_function does + sf->is_strict_mode = false; + sf->cur_func = unsafe_unconst(func_obj); + sf->arg_count = argc; + ret = s->func(ctx, this_val, argc, arg_buf, s->magic, s->opaque); + rt->current_stack_frame = sf->prev_frame; + + return ret; +} + +JSValue JS_NewCClosure(JSContext *ctx, JSCClosure *func, const char *name, + JSCClosureFinalizerFunc *opaque_finalize, + int length, int magic, void *opaque) +{ + JSCClosureRecord *s; + JSAtom name_atom; + JSValue func_obj; + + func_obj = JS_NewObjectProtoClass(ctx, ctx->function_proto, + JS_CLASS_C_CLOSURE); + if (JS_IsException(func_obj)) + return func_obj; + s = js_malloc(ctx, sizeof(*s)); + if (!s) { + JS_FreeValue(ctx, func_obj); + return JS_EXCEPTION; + } + s->func = func; + s->length = length; + s->magic = magic; + s->opaque = opaque; + s->opaque_finalize = opaque_finalize; + JS_SetOpaqueInternal(func_obj, s); + name_atom = JS_ATOM_empty_string; + if (name && *name) { + name_atom = JS_NewAtom(ctx, name); + if (name_atom == JS_ATOM_NULL) { + JS_FreeValue(ctx, func_obj); + return JS_EXCEPTION; + } + } + js_function_set_properties(ctx, func_obj, name_atom, length); + JS_FreeAtom(ctx, name_atom); + return func_obj; +} + static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags) { if (unlikely(prop_flags & JS_PROP_TMASK)) { @@ -5565,8 +6444,7 @@ static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags) } } -static force_inline JSShapeProperty *find_own_property1(JSObject *p, - JSAtom atom) +static inline JSShapeProperty *find_own_property1(JSObject *p, JSAtom atom) { JSShape *sh; JSShapeProperty *pr, *prop; @@ -5574,7 +6452,7 @@ static force_inline JSShapeProperty *find_own_property1(JSObject *p, sh = p->shape; h = (uintptr_t)atom & sh->prop_hash_mask; h = prop_hash_end(sh)[-h - 1]; - prop = get_shape_prop(sh); + prop = sh->prop; while (h) { pr = &prop[h - 1]; if (likely(pr->atom == atom)) { @@ -5585,9 +6463,9 @@ static force_inline JSShapeProperty *find_own_property1(JSObject *p, return NULL; } -static force_inline JSShapeProperty *find_own_property(JSProperty **ppr, - JSObject *p, - JSAtom atom) +static inline JSShapeProperty *find_own_property(JSProperty **ppr, + JSObject *p, + JSAtom atom) { JSShape *sh; JSShapeProperty *pr, *prop; @@ -5595,7 +6473,7 @@ static force_inline JSShapeProperty *find_own_property(JSProperty **ppr, sh = p->shape; h = (uintptr_t)atom & sh->prop_hash_mask; h = prop_hash_end(sh)[-h - 1]; - prop = get_shape_prop(sh); + prop = sh->prop; while (h) { pr = &prop[h - 1]; if (likely(pr->atom == atom)) { @@ -5618,7 +6496,9 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref) JS_FreeValueRT(rt, var_ref->value); remove_gc_object(&var_ref->header); } else { - list_del(&var_ref->header.link); /* still on the stack */ + JSStackFrame *sf = var_ref->stack_frame; + assert(sf->var_refs[var_ref->var_ref_idx] == var_ref); + sf->var_refs[var_ref->var_ref_idx] = NULL; } js_free_rt(rt, var_ref); } @@ -5628,7 +6508,7 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref) static void js_array_finalizer(JSRuntime *rt, JSValueConst val) { JSObject *p = JS_VALUE_GET_OBJ(val); - int i; + uint32_t i; for(i = 0; i < p->u.array.count; i++) { JS_FreeValueRT(rt, p->u.array.u.values[i]); @@ -5640,7 +6520,7 @@ static void js_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) { JSObject *p = JS_VALUE_GET_OBJ(val); - int i; + uint32_t i; for(i = 0; i < p->u.array.count; i++) { JS_MarkValue(rt, p->u.array.u.values[i], mark_func); @@ -5782,7 +6662,7 @@ static void free_object(JSRuntime *rt, JSObject *p) freeing cycles */ /* free all the fields */ sh = p->shape; - pr = get_shape_prop(sh); + pr = sh->prop; for(i = 0; i < sh->prop_count; i++) { free_property(rt, &p->prop[i], pr->flags); pr++; @@ -5874,6 +6754,14 @@ static void js_free_value_rt(JSRuntime *rt, JSValue v) case JS_TAG_STRING: js_free_string0(rt, JS_VALUE_GET_STRING(v)); break; + case JS_TAG_STRING_ROPE: + { + JSStringRope *p = JS_VALUE_GET_STRING_ROPE(v); + JS_FreeValueRT(rt, p->left); + JS_FreeValueRT(rt, p->right); + js_free_rt(rt, p); + } + break; case JS_TAG_OBJECT: case JS_TAG_FUNCTION_BYTECODE: { @@ -5981,7 +6869,7 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, sh = p->shape; mark_func(rt, &sh->header); /* mark all the fields */ - prs = get_shape_prop(sh); + prs = sh->prop; for(i = 0; i < sh->prop_count; i++) { JSProperty *pr = &p->prop[i]; if (prs->atom != JS_ATOM_NULL) { @@ -6365,7 +7253,7 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) s->memory_used_count++; s->prop_size += sh->prop_size * sizeof(*p->prop); s->prop_count += sh->prop_count; - prs = get_shape_prop(sh); + prs = sh->prop; for(i = 0; i < sh->prop_count; i++) { JSProperty *pr = &p->prop[i]; if (prs->atom != JS_ATOM_NULL && !(prs->flags & JS_PROP_TMASK)) { @@ -6455,6 +7343,15 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) } } break; + case JS_CLASS_C_CLOSURE: /* u.c_closure_record */ + { + JSCClosureRecord *c = p->u.c_closure_record; + if (c) { + s->memory_used_count += 1; + s->memory_used_size += sizeof(*c); + } + } + break; case JS_CLASS_REGEXP: /* u.regexp */ compute_jsstring_size(p->u.regexp.pattern, hp); compute_jsstring_size(p->u.regexp.bytecode, hp); @@ -6567,8 +7464,8 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt) { - fprintf(fp, "QuickJS-ng memory usage -- %s version, %d-bit, %s Endian, malloc limit: %"PRId64"\n\n", - JS_GetVersion(), (int)sizeof(void *) * 8, is_be() ? "Big" : "Little", s->malloc_limit); + fprintf(fp, "QuickJS-ng memory usage -- %s version, %d-bit, malloc limit: %"PRId64"\n\n", + JS_GetVersion(), (int)sizeof(void *) * 8, s->malloc_limit); if (rt) { static const struct { const char *name; @@ -6871,7 +7768,7 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_val, int line_num, int col_num, int backtrace_flags) { JSStackFrame *sf, *sf_start; - JSValue stack, prepare, saved_exception; + JSValue stack, prepare, saved_exception, error_obj; DynBuf dbuf; const char *func_name_str; const char *str1; @@ -6888,6 +7785,7 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_val, if (rt->in_build_stack_trace) return; rt->in_build_stack_trace = true; + error_obj = js_dup(error_val); // Save exception because conversion to double may fail. saved_exception = JS_GetException(ctx); @@ -7033,7 +7931,7 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_val, JS_FreeValue(ctx, csd[k].func_name); } JSValueConst args[] = { - error_val, + error_obj, stack, }; JSValue stack2 = JS_Call(ctx, prepare, ctx->error_ctor, countof(args), args); @@ -7054,13 +7952,14 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_val, if (JS_IsUndefined(ctx->error_back_trace)) ctx->error_back_trace = js_dup(stack); - if (has_filter_func || can_add_backtrace(error_val)) { - JS_DefinePropertyValue(ctx, error_val, JS_ATOM_stack, stack, + if (has_filter_func || can_add_backtrace(error_obj)) { + JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_stack, stack, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } else { JS_FreeValue(ctx, stack); } + JS_FreeValue(ctx, error_obj); rt->in_build_stack_trace = false; } @@ -7193,7 +8092,7 @@ static int JS_PRINTF_FORMAT_ATTR(3, 4) JS_ThrowTypeErrorOrFalse(JSContext *ctx, } } -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif // __GNUC__ @@ -7210,7 +8109,7 @@ static JSValue JS_ThrowSyntaxErrorAtom(JSContext *ctx, const char *fmt, JSAtom a JS_AtomGetStr(ctx, buf, sizeof(buf), atom); return JS_ThrowSyntaxError(ctx, fmt, buf); } -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic pop // ignored "-Wformat-nonliteral" #endif // __GNUC__ @@ -7415,6 +8314,14 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj, if (sh->proto) JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, sh->proto)); sh->proto = proto; + if (proto) + proto->is_prototype = true; + if (p->is_prototype) { + /* track modification of Array.prototype */ + if (unlikely(p == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_ARRAY]))) { + ctx->std_array_prototype = false; + } + } return true; } @@ -7441,6 +8348,7 @@ static JSValueConst JS_GetPrototypePrimitive(JSContext *ctx, JSValueConst val) ret = ctx->class_proto[JS_CLASS_BOOLEAN]; break; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: ret = ctx->class_proto[JS_CLASS_STRING]; break; case JS_TAG_SYMBOL: @@ -7594,6 +8502,71 @@ int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj) } #include "builtin-array-fromasync.h" +#include "builtin-iterator-zip-keyed.h" +#include "builtin-iterator-zip.h" + +// like Function.prototype.call but monkey patch-proof +static JSValue js_call_function(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + return JS_Call(ctx, argv[1], argv[0], argc-2, argv+2); +} + +// returns enumerable and non-enumerable strings *and* symbols +static JSValue js_getOwnPropertyKeys(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + int flags = JS_GPN_STRING_MASK|JS_GPN_SYMBOL_MASK; + return JS_GetOwnPropertyNames2(ctx, argv[0], flags, JS_ITERATOR_KIND_KEY); +} + +static JSValue js_hasOwnEnumProperty(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSObject *p; + JSAtom key; + int flags, res; + + if (JS_TAG_OBJECT != JS_VALUE_GET_TAG(argv[0])) + return JS_ThrowTypeErrorNotAnObject(ctx); + p = JS_VALUE_GET_OBJ(argv[0]); + key = JS_ValueToAtomInternal(ctx, argv[1], JS_TO_STRING_NO_SIDE_EFFECTS); + if (key == JS_ATOM_NULL) + return JS_EXCEPTION; + res = JS_GetOwnPropertyFlagsInternal(ctx, &flags, p, key); + JS_FreeAtom(ctx, key); + if (res < 0) + return JS_EXCEPTION; + if (res > 0 && (flags & JS_PROP_ENUMERABLE)) + return JS_TRUE; + return JS_FALSE; +} + +// note: takes ownership of |argv| +static JSValue js_bytecode_eval(JSContext *ctx, const uint8_t *bytecode, + size_t len, int argc, JSValue *argv) +{ + JSValue obj, fun, result; + int i; + + obj = JS_ReadObject(ctx, bytecode, len, JS_READ_OBJ_BYTECODE); + if (JS_IsException(obj)) + return JS_EXCEPTION; + fun = JS_EvalFunction(ctx, obj); + if (JS_IsException(fun)) + return JS_EXCEPTION; + assert(JS_IsFunction(ctx, fun)); + result = JS_Call(ctx, fun, JS_UNDEFINED, argc, vc(argv)); + for (i = 0; i < argc; i++) + JS_FreeValue(ctx, argv[i]); + JS_FreeValue(ctx, fun); + if (JS_SetPrototypeInternal(ctx, result, ctx->function_proto, + /*throw_flag*/true) < 0) { + JS_FreeValue(ctx, result); + return JS_EXCEPTION; + } + return result; +} static JSValue js_bytecode_autoinit(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque) @@ -7603,19 +8576,10 @@ static JSValue js_bytecode_autoinit(JSContext *ctx, JSObject *p, JSAtom atom, abort(); case JS_BUILTIN_ARRAY_FROMASYNC: { - JSValue obj = JS_ReadObject(ctx, qjsc_builtin_array_fromasync, - sizeof(qjsc_builtin_array_fromasync), - JS_READ_OBJ_BYTECODE); - if (JS_IsException(obj)) - return JS_EXCEPTION; - JSValue fun = JS_EvalFunction(ctx, obj); - if (JS_IsException(fun)) - return JS_EXCEPTION; - assert(JS_IsFunction(ctx, fun)); - JSValue args[] = { + JSValue argv[] = { JS_NewCFunction(ctx, js_array_constructor, "Array", 0), - JS_NewCFunctionMagic(ctx, js_error_constructor, "TypeError", 1, - JS_CFUNC_constructor_or_func_magic, + JS_NewCFunctionMagic(ctx, js_error_constructor, "TypeError", + 1, JS_CFUNC_constructor_or_func_magic, JS_TYPE_ERROR), JS_AtomToValue(ctx, JS_ATOM_Symbol_asyncIterator), JS_NewCFunctionMagic(ctx, js_object_defineProperty, @@ -7623,16 +8587,50 @@ static JSValue js_bytecode_autoinit(JSContext *ctx, JSObject *p, JSAtom atom, JS_CFUNC_generic_magic, 0), JS_AtomToValue(ctx, JS_ATOM_Symbol_iterator), }; - JSValue result = JS_Call(ctx, fun, JS_UNDEFINED, - countof(args), vc(args)); - for (size_t i = 0; i < countof(args); i++) - JS_FreeValue(ctx, args[i]); - JS_FreeValue(ctx, fun); - if (JS_SetPrototypeInternal(ctx, result, ctx->function_proto, - /*throw_flag*/true) < 0) { - JS_FreeValue(ctx, result); - return JS_EXCEPTION; - } + return js_bytecode_eval(ctx, qjsc_builtin_array_fromasync, + sizeof(qjsc_builtin_array_fromasync), + countof(argv), argv); + } + case JS_BUILTIN_ITERATOR_ZIP: + { + JSValue argv[] = { + js_dup(ctx->class_proto[JS_CLASS_ITERATOR_HELPER]), + JS_NewCFunctionMagic(ctx, js_error_constructor, "InternalError", + 1, JS_CFUNC_constructor_or_func_magic, + JS_INTERNAL_ERROR), + JS_NewCFunctionMagic(ctx, js_error_constructor, "TypeError", + 1, JS_CFUNC_constructor_or_func_magic, + JS_TYPE_ERROR), + JS_NewCFunction(ctx, js_call_function, "call", 2), + JS_AtomToValue(ctx, JS_ATOM_Symbol_iterator), + }; + JSValue result = js_bytecode_eval(ctx, qjsc_builtin_iterator_zip, + sizeof(qjsc_builtin_iterator_zip), + countof(argv), argv); + JS_SetConstructorBit(ctx, result, false); + return result; + } + case JS_BUILTIN_ITERATOR_ZIP_KEYED: + { + JSValue argv[] = { + js_dup(ctx->class_proto[JS_CLASS_ITERATOR_HELPER]), + JS_NewCFunctionMagic(ctx, js_error_constructor, "InternalError", + 1, JS_CFUNC_constructor_or_func_magic, + JS_INTERNAL_ERROR), + JS_NewCFunctionMagic(ctx, js_error_constructor, "TypeError", + 1, JS_CFUNC_constructor_or_func_magic, + JS_TYPE_ERROR), + JS_NewCFunction(ctx, js_call_function, "call", 2), + JS_NewCFunction(ctx, js_hasOwnEnumProperty, + "hasOwnEnumProperty", 2), + JS_NewCFunction(ctx, js_getOwnPropertyKeys, + "getOwnPropertyKeys", 1), + JS_AtomToValue(ctx, JS_ATOM_Symbol_iterator), + }; + JSValue result = js_bytecode_eval(ctx, qjsc_builtin_iterator_zip_keyed, + sizeof(qjsc_builtin_iterator_zip_keyed), + countof(argv), argv); + JS_SetConstructorBit(ctx, result, false); return result; } } @@ -7673,6 +8671,13 @@ static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop, return 0; } +#ifdef USE_HOST_OBJECT +/* NativeScript host-object exotic methods (defined in quickjs-api.c). Compared + by address below so the get_property handler can be treated as a non-masking + fallback for host objects only, leaving Proxy (js_proxy_get) authoritative. */ +extern JSClassExoticMethods NapiHostObjectExoticMethods; +#endif + static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, JSAtom prop, JSValueConst this_obj, bool throw_ref_error) @@ -7681,6 +8686,11 @@ static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, JSProperty *pr; JSShapeProperty *prs; uint32_t tag; +#ifdef USE_HOST_OBJECT + /* A host object whose get_property we deferred: the prototype chain is + consulted first, and this is called only if nothing was found. */ + JSObject *deferred_host = NULL; +#endif tag = JS_VALUE_GET_TAG(obj); if (unlikely(tag != JS_TAG_OBJECT)) { @@ -7706,6 +8716,21 @@ static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, } } break; + case JS_TAG_STRING_ROPE: + { + JSStringRope *r = JS_VALUE_GET_STRING_ROPE(obj); + if (__JS_AtomIsTaggedInt(prop)) { + uint32_t idx, ch; + idx = __JS_AtomToUInt32(prop); + if (idx < r->len) { + ch = string_rope_get(obj, idx); + return js_new_string_char(ctx, ch); + } + } else if (prop == JS_ATOM_length) { + return js_int32(r->len); + } + } + break; default: break; } @@ -7770,14 +8795,27 @@ static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; if (em) { if (em->get_property) { - JSValue obj1, retval; - /* XXX: should pass throw_ref_error */ - /* Note: if 'p' is a prototype, it can be - freed in the called function */ - obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); - retval = em->get_property(ctx, obj1, prop, this_obj); - JS_FreeValue(ctx, obj1); - return retval; +#ifdef USE_HOST_OBJECT + /* NativeScript host objects use get_property as a + NON-masking fallback: defer it so the prototype chain + (native methods / field accessors) is consulted first, + and call it only if nothing is found (see after loop). + Proxy and other exotics stay authoritative. */ + if (em == &NapiHostObjectExoticMethods) { + if (!deferred_host) + deferred_host = p; + } else +#endif + { + JSValue obj1, retval; + /* XXX: should pass throw_ref_error */ + /* Note: if 'p' is a prototype, it can be + freed in the called function */ + obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, p)); + retval = em->get_property(ctx, obj1, prop, this_obj); + JS_FreeValue(ctx, obj1); + return retval; + } } if (em->get_own_property) { JSPropertyDescriptor desc; @@ -7807,6 +8845,17 @@ static JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, if (!p) break; } +#ifdef USE_HOST_OBJECT + /* Nothing found on the prototype chain: now consult the deferred host + object's get_property (expandos, numeric indices, dynamic members). */ + if (deferred_host) { + JSValue obj1, retval; + obj1 = js_dup(JS_MKPTR(JS_TAG_OBJECT, deferred_host)); + retval = NapiHostObjectExoticMethods.get_property(ctx, obj1, prop, this_obj); + JS_FreeValue(ctx, obj1); + return retval; + } +#endif if (unlikely(throw_ref_error)) { return JS_ThrowReferenceErrorNotDefined(ctx, prop); } else { @@ -8080,7 +9129,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, exotic_count = 0; tab_exotic = NULL; sh = p->shape; - for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { + for(i = 0, prs = sh->prop; i < sh->prop_count; i++, prs++) { atom = prs->atom; if (atom != JS_ATOM_NULL) { is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0); @@ -8129,18 +9178,16 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, if (((flags >> kind) & 1) != 0) { is_enumerable = false; if (flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY)) { - JSPropertyDescriptor desc; - int res; + int desc_flags, res; /* set the "is_enumerable" field if necessary */ - res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom); + res = JS_GetOwnPropertyFlagsInternal(ctx, &desc_flags, p, atom); if (res < 0) { js_free_prop_enum(ctx, tab_exotic, exotic_count); return -1; } if (res) { is_enumerable = - ((desc.flags & JS_PROP_ENUMERABLE) != 0); - js_free_desc(ctx, &desc); + ((desc_flags & JS_PROP_ENUMERABLE) != 0); } tab_exotic[i].is_enumerable = is_enumerable; } @@ -8169,7 +9216,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, num_sorted = true; sh = p->shape; - for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { + for(i = 0, prs = sh->prop; i < sh->prop_count; i++, prs++) { atom = prs->atom; if (atom != JS_ATOM_NULL) { is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0); @@ -8257,11 +9304,12 @@ int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, /* Return -1 if exception, false if the property does not exist, true if it exists. If true is returned, the property descriptor 'desc' is filled present. */ -static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, - JSObject *p, JSAtom prop) +static int JS_GetOwnPropertyInternal2(JSContext *ctx, JSPropertyDescriptor *desc, + JSObject *p, JSAtom prop, int *pflags) { JSShapeProperty *prs; JSProperty *pr; + int flags_only = (desc == NULL && pflags != NULL); retry: prs = find_own_property(&pr, p, prop); @@ -8295,6 +9343,11 @@ static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, desc->value = js_dup(pr->u.value); } } else { + if (pflags) { + *pflags = prs->flags & JS_PROP_C_W_E; + if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) + *pflags |= JS_PROP_GETSET; + } /* for consistency, send the exception even if desc is NULL */ if (unlikely((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF)) { if (unlikely(JS_IsUninitialized(*pr->u.var_ref->pvalue))) { @@ -8317,9 +9370,20 @@ static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, if (desc) { desc->flags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE | JS_PROP_CONFIGURABLE; + if (is_typed_array(p->class_id) && typed_array_is_immutable(p)) { + desc->flags &= ~JS_PROP_WRITABLE; + desc->flags &= ~JS_PROP_CONFIGURABLE; + } desc->getter = JS_UNDEFINED; desc->setter = JS_UNDEFINED; desc->value = JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx); + } else if (flags_only) { + *pflags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE | + JS_PROP_CONFIGURABLE; + if (is_typed_array(p->class_id) && typed_array_is_immutable(p)) { + *pflags &= ~JS_PROP_WRITABLE; + *pflags &= ~JS_PROP_CONFIGURABLE; + } } return true; } @@ -8327,6 +9391,20 @@ static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, } else { const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; if (em && em->get_own_property) { + if (flags_only) { + /* Call the exotic handler with a temporary desc, + extract flags, and free the values. For Proxy + objects, the JS trap runs regardless, so the + dup+free overhead is negligible. */ + JSPropertyDescriptor d; + int ret = em->get_own_property(ctx, &d, + JS_MKPTR(JS_TAG_OBJECT, p), prop); + if (ret > 0) { + *pflags = d.flags; + js_free_desc(ctx, &d); + } + return ret; + } return em->get_own_property(ctx, desc, JS_MKPTR(JS_TAG_OBJECT, p), prop); } @@ -8335,6 +9413,21 @@ static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, return false; } +static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, + JSObject *p, JSAtom prop) +{ + return JS_GetOwnPropertyInternal2(ctx, desc, p, prop, NULL); +} + +/* Same as JS_GetOwnPropertyInternal but only returns flags, not + value/getter/setter. Avoids unnecessary js_dup() for callers that + only need the property flags. */ +static int JS_GetOwnPropertyFlagsInternal(JSContext *ctx, int *pflags, + JSObject *p, JSAtom prop) +{ + return JS_GetOwnPropertyInternal2(ctx, NULL, p, prop, pflags); +} + int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, JSValueConst obj, JSAtom prop) { @@ -8470,6 +9563,10 @@ static bool js_get_fast_array_element(JSContext *ctx, JSObject *p, if (unlikely(idx >= p->u.array.count)) return false; *pval = js_dup(p->u.array.u.values[idx]); return true; + case JS_CLASS_MAPPED_ARGUMENTS: + if (unlikely(idx >= p->u.array.count)) return false; + *pval = js_dup(*p->u.array.u.var_refs[idx]->pvalue); + return true; case JS_CLASS_INT8_ARRAY: if (unlikely(idx >= p->u.array.count)) return false; *pval = js_int32(p->u.array.u.int8_ptr[idx]); @@ -8646,6 +9743,15 @@ static JSProperty *add_property(JSContext *ctx, { JSShape *sh, *new_sh; + if (unlikely(p->is_prototype)) { + /* track addition of small integer properties to + Array.prototype and Object.prototype */ + if (unlikely((p == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_ARRAY]) || + p == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_OBJECT])) && + __JS_AtomIsTaggedInt(prop))) { + ctx->std_array_prototype = false; + } + } sh = p->shape; if (sh->is_hashed) { /* try to find an existing shape */ @@ -8682,16 +9788,20 @@ static JSProperty *add_property(JSContext *ctx, return &p->prop[p->shape->prop_count - 1]; } -/* can be called on Array or Arguments objects. return < 0 if - memory alloc error. */ +/* can be called on JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS or + JS_CLASS_MAPPED_ARGUMENTS objects. return < 0 if memory alloc + error. */ static no_inline __exception int convert_fast_array_to_array(JSContext *ctx, JSObject *p) { JSProperty *pr; JSShape *sh; - JSValue *tab; uint32_t i, len, new_count; + /* track modification of Array.prototype */ + if (unlikely(p == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_ARRAY]))) { + ctx->std_array_prototype = false; + } if (js_shape_prepare_update(ctx, p, NULL)) return -1; len = p->u.array.count; @@ -8703,12 +9813,22 @@ static no_inline __exception int convert_fast_array_to_array(JSContext *ctx, return -1; } - tab = p->u.array.u.values; - for(i = 0; i < len; i++) { - /* add_property cannot fail here but - __JS_AtomFromUInt32(i) fails for i > INT32_MAX */ - pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E); - pr->u.value = *tab++; + if (p->class_id == JS_CLASS_MAPPED_ARGUMENTS) { + JSVarRef **tab = p->u.array.u.var_refs; + for(i = 0; i < len; i++) { + /* add_property cannot fail here but + __JS_AtomFromUInt32(i) fails for i > INT32_MAX */ + pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF); + pr->u.var_ref = *tab++; + } + } else { + JSValue *tab = p->u.array.u.values; + for(i = 0; i < len; i++) { + /* add_property cannot fail here but + __JS_AtomFromUInt32(i) fails for i > INT32_MAX */ + pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E); + pr->u.value = *tab++; + } } js_free(ctx, p->u.array.u.values); p->u.array.count = 0; @@ -8730,7 +9850,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) sh = p->shape; h1 = atom & sh->prop_hash_mask; h = prop_hash_end(sh)[-h1 - 1]; - prop = get_shape_prop(sh); + prop = sh->prop; lpr = NULL; lpr_idx = 0; /* prevent warning */ while (h != 0) { @@ -8741,13 +9861,13 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) return false; /* realloc the shape if needed */ if (lpr) - lpr_idx = lpr - get_shape_prop(sh); + lpr_idx = lpr - sh->prop; if (js_shape_prepare_update(ctx, p, &pr)) return -1; sh = p->shape; /* remove property */ if (lpr) { - lpr = get_shape_prop(sh) + lpr_idx; + lpr = &sh->prop[lpr_idx]; lpr->hash_next = pr->hash_next; } else { prop_hash_end(sh)[-h1 - 1] = pr->hash_next; @@ -8779,13 +9899,8 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) if (JS_AtomIsArrayIndex(ctx, &idx, atom) && idx < p->u.array.count) { if (p->class_id == JS_CLASS_ARRAY || - p->class_id == JS_CLASS_ARGUMENTS) { - /* Special case deleting the last element of a fast Array */ - if (idx == p->u.array.count - 1) { - JS_FreeValue(ctx, p->u.array.u.values[idx]); - p->u.array.count = idx; - return true; - } + p->class_id == JS_CLASS_ARGUMENTS || + p->class_id == JS_CLASS_MAPPED_ARGUMENTS) { if (convert_fast_array_to_array(ctx, p)) return -1; goto redo; @@ -8849,6 +9964,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, if (len < old_len) { for(i = len; i < old_len; i++) { JS_FreeValue(ctx, p->u.array.u.values[i]); + p->u.array.u.values[i] = JS_UNDEFINED; } p->u.array.count = len; } @@ -8884,7 +10000,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, passes in case one of the property is not configurable */ cur_len = len; - for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; + for(i = 0, pr = sh->prop; i < sh->prop_count; i++, pr++) { if (pr->atom != JS_ATOM_NULL && JS_AtomIsArrayIndex(ctx, &idx, pr->atom)) { @@ -8895,7 +10011,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, } } - for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; + for(i = 0, pr = sh->prop; i < sh->prop_count; i++, pr++) { if (pr->atom != JS_ATOM_NULL && JS_AtomIsArrayIndex(ctx, &idx, pr->atom)) { @@ -8904,7 +10020,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, delete_property(ctx, p, pr->atom); /* WARNING: the shape may have been modified */ sh = p->shape; - pr = get_shape_prop(sh) + i; + pr = &sh->prop[i]; } } } @@ -8923,11 +10039,22 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, /* return -1 if exception */ static int expand_fast_array(JSContext *ctx, JSObject *p, uint32_t new_len) { - uint32_t new_size; + uint32_t old_size, new_size; size_t slack; JSValue *new_array_prop; - /* XXX: potential arithmetic overflow */ - new_size = max_int(new_len, p->u.array.u1.size * 3 / 2); + + if (unlikely(new_len > (uint32_t)INT32_MAX)) { + JS_ThrowOutOfMemory(ctx); + return -1; + } + + old_size = p->u.array.u1.size; + new_size = old_size + old_size/2; + if (new_size < old_size) { + JS_ThrowOutOfMemory(ctx); + return -1; + } + new_size = max_uint32(new_len, new_size); new_array_prop = js_realloc2(ctx, p->u.array.u.values, sizeof(JSValue) * new_size, &slack); if (!new_array_prop) return -1; @@ -8951,7 +10078,7 @@ static int add_fast_array_element(JSContext *ctx, JSObject *p, if (likely(JS_VALUE_GET_TAG(p->prop[0].u.value) == JS_TAG_INT)) { array_len = JS_VALUE_GET_INT(p->prop[0].u.value); if (new_len > array_len) { - if (unlikely(!(get_shape_prop(p->shape)->flags & JS_PROP_WRITABLE))) { + if (unlikely(!(p->shape->prop->flags & JS_PROP_WRITABLE))) { JS_FreeValue(ctx, val); return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length); } @@ -8969,6 +10096,35 @@ static int add_fast_array_element(JSContext *ctx, JSObject *p, return true; } +/* Allocate a new fast array initialized to JS_UNDEFINED. Its maximum + size is 2^31-1 elements. For convenience, 'len' is a 64 bit + integer. */ +static JSValue js_allocate_fast_array(JSContext *ctx, int64_t len) +{ + JSValue arr; + JSObject *p; + int i; + + if (len > INT32_MAX) + return JS_ThrowRangeError(ctx, "invalid array length"); + arr = JS_NewArray(ctx); + if (JS_IsException(arr)) + return arr; + if (len > 0) { + p = JS_VALUE_GET_OBJ(arr); + if (expand_fast_array(ctx, p, len) < 0) { + JS_FreeValue(ctx, arr); + return JS_EXCEPTION; + } + p->u.array.count = len; + for(i = 0; i < len; i++) + p->u.array.u.values[i] = JS_UNDEFINED; + /* update the 'length' field */ + set_value(ctx, &p->prop[0].u.value, js_int32(len)); + } + return arr; +} + static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc) { JS_FreeValue(ctx, desc->getter); @@ -8989,6 +10145,7 @@ static int JS_SetPropertyInternal2(JSContext *ctx, JSValueConst obj, JSAtom prop JSShapeProperty *prs; JSProperty *pr; JSPropertyDescriptor desc; + int desc_flags; int ret; switch(JS_VALUE_GET_TAG(this_obj)) { @@ -9162,12 +10319,11 @@ static int JS_SetPropertyInternal2(JSContext *ctx, JSValueConst obj, JSAtom prop goto done; } - if (unlikely(!p->extensible)) { - ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible"); - goto done; - } - if (p == JS_VALUE_GET_OBJ(obj)) { + if (unlikely(!p->extensible)) { + ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible"); + goto done; + } if (p->is_exotic) { if (p->class_id == JS_CLASS_ARRAY && p->fast_array && __JS_AtomIsTaggedInt(prop)) { @@ -9190,18 +10346,15 @@ static int JS_SetPropertyInternal2(JSContext *ctx, JSValueConst obj, JSAtom prop // TODO(bnoordhuis) return JSProperty slot and update in place // when plain property (not is_exotic/setter/etc.) to avoid // calling find_own_property() thrice? - ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); + ret = JS_GetOwnPropertyFlagsInternal(ctx, &desc_flags, p, prop); if (ret < 0) goto fail; if (ret) { - JS_FreeValue(ctx, desc.value); - if (desc.flags & JS_PROP_GETSET) { - JS_FreeValue(ctx, desc.getter); - JS_FreeValue(ctx, desc.setter); + if (desc_flags & JS_PROP_GETSET) { ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "setter is forbidden"); goto done; - } else if (!(desc.flags & JS_PROP_WRITABLE) || + } else if (!(desc_flags & JS_PROP_WRITABLE) || p->class_id == JS_CLASS_MODULE_NS) { read_only_prop: ret = JS_ThrowTypeErrorReadOnly(ctx, flags, prop); @@ -9211,6 +10364,10 @@ static int JS_SetPropertyInternal2(JSContext *ctx, JSValueConst obj, JSAtom prop JS_UNDEFINED, JS_UNDEFINED, JS_PROP_HAS_VALUE); } else { + if (unlikely(!p->extensible)) { + ret = JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible"); + goto done; + } generic_create_prop: ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED, flags | @@ -9257,27 +10414,13 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, switch(p->class_id) { case JS_CLASS_ARRAY: if (unlikely(idx >= (uint32_t)p->u.array.count)) { - JSObject *p1; - JSShape *sh1; - /* fast path to add an element to the array */ - if (idx != (uint32_t)p->u.array.count || - !p->fast_array || !p->extensible) + if (unlikely(idx != (uint32_t)p->u.array.count || + !p->fast_array || + !p->extensible || + p->shape->proto != JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_ARRAY]) || + !ctx->std_array_prototype)) { goto slow_path; - /* check if prototype chain has a numeric property */ - p1 = p->shape->proto; - while (p1 != NULL) { - sh1 = p1->shape; - if (p1->class_id == JS_CLASS_ARRAY) { - if (unlikely(!p1->fast_array)) - goto slow_path; - } else if (p1->class_id == JS_CLASS_OBJECT) { - if (unlikely(sh1->has_small_array_index)) - goto slow_path; - } else { - goto slow_path; - } - p1 = sh1->proto; } /* add element */ return add_fast_array_element(ctx, p, val, flags); @@ -9289,9 +10432,16 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, goto slow_path; set_value(ctx, &p->u.array.u.values[idx], val); break; + case JS_CLASS_MAPPED_ARGUMENTS: + if (unlikely(idx >= (uint32_t)p->u.array.count)) + goto slow_path; + set_value(ctx, p->u.array.u.var_refs[idx]->pvalue, val); + break; case JS_CLASS_UINT8C_ARRAY: if (JS_ToUint8ClampFree(ctx, &v, val)) goto ta_cvt_fail; + if (typed_array_is_immutable(p)) + goto ta_immutable; /* Note: the conversion can detach the typed array, so the array bound check must be done after */ if (unlikely(idx >= (uint32_t)p->u.array.count)) @@ -9302,6 +10452,8 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, case JS_CLASS_UINT8_ARRAY: if (JS_ToInt32Free(ctx, &v, val)) goto ta_cvt_fail; + if (typed_array_is_immutable(p)) + goto ta_immutable; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint8_ptr[idx] = v; @@ -9310,6 +10462,8 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, case JS_CLASS_UINT16_ARRAY: if (JS_ToInt32Free(ctx, &v, val)) goto ta_cvt_fail; + if (typed_array_is_immutable(p)) + goto ta_immutable; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint16_ptr[idx] = v; @@ -9318,6 +10472,8 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, case JS_CLASS_UINT32_ARRAY: if (JS_ToInt32Free(ctx, &v, val)) goto ta_cvt_fail; + if (typed_array_is_immutable(p)) + goto ta_immutable; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint32_ptr[idx] = v; @@ -9329,6 +10485,8 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, int64_t v; if (JS_ToBigInt64Free(ctx, &v, val)) goto ta_cvt_fail; + if (typed_array_is_immutable(p)) + goto ta_immutable; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.uint64_ptr[idx] = v; @@ -9337,6 +10495,8 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, case JS_CLASS_FLOAT16_ARRAY: if (JS_ToFloat64Free(ctx, &d, val)) goto ta_cvt_fail; + if (typed_array_is_immutable(p)) + goto ta_immutable; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.fp16_ptr[idx] = tofp16(d); @@ -9344,6 +10504,8 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, case JS_CLASS_FLOAT32_ARRAY: if (JS_ToFloat64Free(ctx, &d, val)) goto ta_cvt_fail; + if (typed_array_is_immutable(p)) + goto ta_immutable; if (unlikely(idx >= (uint32_t)p->u.array.count)) goto ta_out_of_bound; p->u.array.u.float_ptr[idx] = d; @@ -9357,6 +10519,10 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, } return -1; } + if (typed_array_is_immutable(p)) { + ta_immutable: + return false; + } if (unlikely(idx >= (uint32_t)p->u.array.count)) { ta_out_of_bound: if (typed_array_is_oob(p)) @@ -9485,7 +10651,7 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p, plen = &p->prop[0]; JS_ToUint32(ctx, &len, plen->u.value); if ((idx + 1) > len) { - pslen = get_shape_prop(p->shape); + pslen = p->shape->prop; if (unlikely(!(pslen->flags & JS_PROP_WRITABLE))) return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length); /* XXX: should update the length after defining @@ -9595,7 +10761,7 @@ static int js_shape_prepare_update(JSContext *ctx, JSObject *p, if (sh->is_hashed) { if (sh->header.ref_count != 1) { if (pprs) - idx = *pprs - get_shape_prop(sh); + idx = *pprs - sh->prop; /* clone the shape (the resulting one is no longer hashed) */ sh = js_clone_shape(ctx, sh); if (!sh) @@ -9603,7 +10769,7 @@ static int js_shape_prepare_update(JSContext *ctx, JSObject *p, js_free_shape(ctx->rt, p->shape); p->shape = sh; if (pprs) - *pprs = get_shape_prop(sh) + idx; + *pprs = &sh->prop[idx]; } else { js_shape_hash_unlink(ctx->rt, sh); sh->is_hashed = false; @@ -9793,7 +10959,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, property is read-only. */ if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == JS_PROP_HAS_WRITABLE) { - prs = get_shape_prop(p->shape); + prs = p->shape->prop; if (js_update_property_flags(ctx, p, &prs, prs->flags & ~JS_PROP_WRITABLE)) return -1; @@ -9928,13 +11094,21 @@ static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj, return true; } +/* Like JS_DefinePropertyValue but borrows val (does not free it) */ +static int JS_DefinePropertyValueConst(JSContext *ctx, JSValueConst this_obj, + JSAtom prop, JSValueConst val, int flags) +{ + return JS_DefineProperty(ctx, this_obj, prop, val, JS_UNDEFINED, JS_UNDEFINED, + flags | JS_PROP_HAS_VALUE | JS_PROP_HAS_CONFIGURABLE | + JS_PROP_HAS_WRITABLE | JS_PROP_HAS_ENUMERABLE); +} + /* shortcut to add or redefine a new property value */ int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val, int flags) { int ret; - ret = JS_DefineProperty(ctx, this_obj, prop, val, JS_UNDEFINED, JS_UNDEFINED, - flags | JS_PROP_HAS_VALUE | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_WRITABLE | JS_PROP_HAS_ENUMERABLE); + ret = JS_DefinePropertyValueConst(ctx, this_obj, prop, val, flags); JS_FreeValue(ctx, val); return ret; } @@ -10007,6 +11181,29 @@ static int JS_CreateDataPropertyUint32(JSContext *ctx, JSValueConst this_obj, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE); } +/* Like JS_DefinePropertyValueInt64 but borrows val (does not free it) */ +static int JS_DefinePropertyValueInt64Const(JSContext *ctx, JSValueConst this_obj, + int64_t idx, JSValueConst val, int flags) +{ + JSAtom atom; + int ret; + atom = JS_ValueToAtom(ctx, js_int64(idx)); + if (unlikely(atom == JS_ATOM_NULL)) + return -1; + ret = JS_DefinePropertyValueConst(ctx, this_obj, atom, val, flags); + JS_FreeAtom(ctx, atom); + return ret; +} + +/* Like JS_CreateDataPropertyUint32 but borrows val (does not free it) */ +static int JS_CreateDataPropertyUint32Const(JSContext *ctx, JSValueConst this_obj, + int64_t idx, JSValueConst val, int flags) +{ + return JS_DefinePropertyValueInt64Const(ctx, this_obj, idx, val, + flags | JS_PROP_CONFIGURABLE | + JS_PROP_ENUMERABLE | JS_PROP_WRITABLE); +} + /* return true if 'obj' has a non empty 'name' string */ static bool js_object_has_name(JSContext *ctx, JSValue obj) @@ -10182,6 +11379,14 @@ static JSValue JS_GetGlobalVar(JSContext *ctx, JSAtom prop, return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); return js_dup(pr->u.value); } + + /* fast path */ + p = JS_VALUE_GET_OBJ(ctx->global_obj); + prs = find_own_property(&pr, p, prop); + if (prs) { + if (likely((prs->flags & JS_PROP_TMASK) == 0)) + return js_dup(pr->u.value); + } return JS_GetPropertyInternal(ctx, ctx->global_obj, prop, ctx->global_obj, throw_ref_error); } @@ -10223,37 +11428,16 @@ static int JS_GetGlobalVarRef(JSContext *ctx, JSAtom prop, JSValue *sp) return 0; } -/* use for strict variable access: test if the variable exists */ -static int JS_CheckGlobalVar(JSContext *ctx, JSAtom prop) -{ - JSObject *p; - JSShapeProperty *prs; - int ret; - - /* no exotic behavior is possible in global_var_obj */ - p = JS_VALUE_GET_OBJ(ctx->global_var_obj); - prs = find_own_property1(p, prop); - if (prs) { - ret = true; - } else { - ret = JS_HasProperty(ctx, ctx->global_obj, prop); - if (ret < 0) - return -1; - } - return ret; -} - /* flag = 0: normal variable write flag = 1: initialize lexical variable - flag = 2: normal variable write, strict check was done before */ -static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val, - int flag) +static inline int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val, + int flag) { JSObject *p; JSShapeProperty *prs; JSProperty *pr; - int flags; + int ret; /* no exotic behavior is possible in global_var_obj */ p = JS_VALUE_GET_OBJ(ctx->global_var_obj); @@ -10274,10 +11458,30 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val, set_value(ctx, &pr->u.value, val); return 0; } - flags = JS_PROP_THROW_STRICT; - if (is_strict_mode(ctx)) - flags |= JS_PROP_NO_ADD; - return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, flags); + + p = JS_VALUE_GET_OBJ(ctx->global_obj); + prs = find_own_property(&pr, p, prop); + if (prs) { + if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE | + JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) { + /* fast path */ + set_value(ctx, &pr->u.value, val); + return 0; + } + } + /* slow path */ + ret = JS_HasProperty(ctx, ctx->global_obj, prop); + if (ret < 0) { + JS_FreeValue(ctx, val); + return -1; + } + if (ret == 0 && is_strict_mode(ctx)) { + JS_FreeValue(ctx, val); + JS_ThrowReferenceErrorNotDefined(ctx, prop); + return -1; + } + return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, + JS_PROP_THROW_STRICT); } /* return -1, false or true */ @@ -10361,6 +11565,11 @@ bool JS_IsFunction(JSContext *ctx, JSValueConst val) } } +bool JS_IsAsyncFunction(JSValueConst val) +{ + return JS_CLASS_ASYNC_FUNCTION == JS_GetClassID(val); +} + static bool JS_IsCFunction(JSContext *ctx, JSValueConst val, JSCFunction *func, int magic) { @@ -10641,6 +11850,12 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val) JS_FreeValue(ctx, val); return ret; } + case JS_TAG_STRING_ROPE: + { + bool ret = JS_VALUE_GET_STRING_ROPE(val)->len != 0; + JS_FreeValue(ctx, val); + return ret; + } case JS_TAG_SHORT_BIG_INT: return JS_VALUE_GET_SHORT_BIG_INT(val) != 0; case JS_TAG_BIG_INT: @@ -12202,7 +13417,7 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, if (!(flags & ATOD_INT_ONLY) && (atod_type == ATOD_TYPE_FLOAT64) && js__strstart(p, "Infinity", &p)) { - double d = INF; + double d = INFINITY; if (is_neg) d = -d; val = js_float64(d); @@ -12354,6 +13569,7 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val, return JS_EXCEPTION; goto redo; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: { const char *str; const char *p; @@ -12975,6 +14191,8 @@ static JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, switch(tag) { case JS_TAG_STRING: return js_dup(val); + case JS_TAG_STRING_ROPE: + return js_linearize_string_rope(ctx, val); case JS_TAG_INT: len = i32toa(buf, JS_VALUE_GET_INT(val)); return js_new_string8_len(ctx, buf, len); @@ -13028,8 +14246,9 @@ JSValue JS_ToString(JSContext *ctx, JSValueConst val) static JSValue JS_ToStringFree(JSContext *ctx, JSValue val) { - JSValue ret; - ret = JS_ToString(ctx, val); + if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) + return val; + JSValue ret = JS_ToString(ctx, val); JS_FreeValue(ctx, val); return ret; } @@ -13194,7 +14413,7 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) if (sh) { printf("{ "); - for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { + for(i = 0, prs = sh->prop; i < sh->prop_count; i++, prs++) { if (prs->atom != JS_ATOM_NULL) { pr = &p->prop[i]; if (!is_first) @@ -13332,6 +14551,12 @@ static __maybe_unused void JS_DumpValue(JSRuntime *rt, JSValueConst val) JS_DumpString(rt, p); } break; + case JS_TAG_STRING_ROPE: + { + JSStringRope *r = JS_VALUE_GET_STRING_ROPE(val); + printf("[rope len=%d depth=%d]", r->len, r->depth); + } + break; case JS_TAG_FUNCTION_BYTECODE: { JSFunctionBytecode *b = JS_VALUE_GET_PTR(val); @@ -13492,6 +14717,7 @@ static JSValue JS_ToBigIntFree(JSContext *ctx, JSValue val) val = __JS_NewShortBigInt(ctx, JS_VALUE_GET_INT(val)); break; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: val = JS_StringToBigIntErr(ctx, val); if (JS_IsException(val)) return val; @@ -13825,9 +15051,11 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s } break; case OP_div: - JS_X87_FPCW_SAVE_AND_ADJUST(fpcw); - sp[-2] = js_number((double)v1 / (double)v2); - JS_X87_FPCW_RESTORE(fpcw); + { + JS_X87_FPCW_SAVE_AND_ADJUST(fpcw); + sp[-2] = js_number((double)v1 / (double)v2); + JS_X87_FPCW_RESTORE(fpcw); + } return 0; case OP_mod: if (v1 < 0 || v2 <= 0) { @@ -13979,7 +15207,7 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp) tag2 = JS_VALUE_GET_NORM_TAG(op2); } - if (tag1 == JS_TAG_STRING || tag2 == JS_TAG_STRING) { + if (tag_is_string(tag1) || tag_is_string(tag2)) { sp[-2] = JS_ConcatString(ctx, op1, op2); if (JS_IsException(sp[-2])) goto exception; @@ -14324,11 +15552,13 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, tag1 = JS_VALUE_GET_NORM_TAG(op1); tag2 = JS_VALUE_GET_NORM_TAG(op2); - if (tag1 == JS_TAG_STRING && tag2 == JS_TAG_STRING) { - JSString *p1, *p2; - p1 = JS_VALUE_GET_STRING(op1); - p2 = JS_VALUE_GET_STRING(op2); - res = js_string_compare(p1, p2); + if (tag_is_string(tag1) && tag_is_string(tag2)) { + if (tag1 == JS_TAG_STRING && tag2 == JS_TAG_STRING) { + res = js_string_compare(JS_VALUE_GET_STRING(op1), + JS_VALUE_GET_STRING(op2)); + } else { + res = js_string_rope_compare(op1, op2, false); + } switch(op) { case OP_lt: res = (res < 0); @@ -14477,21 +15707,23 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, } } else if (tag1 == tag2) { res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT); + JS_FreeValue(ctx, op1); + JS_FreeValue(ctx, op2); } else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) || (tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) { res = true; - } else if ((tag1 == JS_TAG_STRING && tag_is_number(tag2)) || - (tag2 == JS_TAG_STRING && tag_is_number(tag1))) { + } else if ((tag_is_string(tag1) && tag_is_number(tag2)) || + (tag_is_string(tag2) && tag_is_number(tag1))) { if (tag1 == JS_TAG_BIG_INT || tag1 == JS_TAG_SHORT_BIG_INT || tag2 == JS_TAG_BIG_INT || tag2 == JS_TAG_SHORT_BIG_INT) { - if (tag1 == JS_TAG_STRING) { + if (tag_is_string(tag1)) { op1 = JS_StringToBigInt(ctx, op1); if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT && JS_VALUE_GET_TAG(op1) != JS_TAG_SHORT_BIG_INT) goto invalid_bigint_string; } - if (tag2 == JS_TAG_STRING) { + if (tag_is_string(tag2)) { op2 = JS_StringToBigInt(ctx, op2); if (JS_VALUE_GET_TAG(op2) != JS_TAG_BIG_INT && JS_VALUE_GET_TAG(op2) != JS_TAG_SHORT_BIG_INT ) { @@ -14515,6 +15747,8 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, } } res = js_strict_eq(ctx, op1, op2); + JS_FreeValue(ctx, op1); + JS_FreeValue(ctx, op2); } else if (tag1 == JS_TAG_BOOL) { op1 = js_int32(JS_VALUE_GET_INT(op1)); goto redo; @@ -14522,9 +15756,9 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, op2 = js_int32(JS_VALUE_GET_INT(op2)); goto redo; } else if ((tag1 == JS_TAG_OBJECT && - (tag_is_number(tag2) || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) || + (tag_is_number(tag2) || tag_is_string(tag2) || tag2 == JS_TAG_SYMBOL)) || (tag2 == JS_TAG_OBJECT && - (tag_is_number(tag1) || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL))) { + (tag_is_number(tag1) || tag_is_string(tag1) || tag1 == JS_TAG_SYMBOL))) { op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE); if (JS_IsException(op1)) { JS_FreeValue(ctx, op2); @@ -14597,7 +15831,7 @@ static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp) return -1; } -static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, +static bool js_strict_eq2(JSContext *ctx, JSValueConst op1, JSValueConst op2, JSStrictEqModeEnum eq_mode) { bool res; @@ -14612,7 +15846,6 @@ static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, res = false; } else { res = JS_VALUE_GET_INT(op1) == JS_VALUE_GET_INT(op2); - goto done_no_free; } break; case JS_TAG_NULL: @@ -14620,14 +15853,15 @@ static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, res = (tag1 == tag2); break; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: { - JSString *p1, *p2; - if (tag1 != tag2) { + if (!tag_is_string(tag2)) { res = false; + } else if (tag1 == JS_TAG_STRING && tag2 == JS_TAG_STRING) { + res = js_string_eq(JS_VALUE_GET_STRING(op1), + JS_VALUE_GET_STRING(op2)); } else { - p1 = JS_VALUE_GET_STRING(op1); - p2 = JS_VALUE_GET_STRING(op2); - res = js_string_eq(p1, p2); + res = (js_string_rope_compare(op1, op2, true) == 0); } } break; @@ -14687,7 +15921,7 @@ static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, } else { res = (d1 == d2); /* if NaN return false and +0 == -0 */ } - goto done_no_free; + break; case JS_TAG_SHORT_BIG_INT: case JS_TAG_BIG_INT: { @@ -14715,25 +15949,22 @@ static bool js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2, res = false; break; } - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - done_no_free: return res; } -static bool js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2) +static bool js_strict_eq(JSContext *ctx, JSValueConst op1, JSValueConst op2) { return js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT); } static bool js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2) { - return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_SAME_VALUE); + return js_strict_eq2(ctx, op1, op2, JS_EQ_SAME_VALUE); } static bool js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2) { - return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_SAME_VALUE_ZERO); + return js_strict_eq2(ctx, op1, op2, JS_EQ_SAME_VALUE_ZERO); } static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp, @@ -14741,6 +15972,8 @@ static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp, { bool res; res = js_strict_eq(ctx, sp[-2], sp[-1]); + JS_FreeValue(ctx, sp[-2]); + JS_FreeValue(ctx, sp[-1]); sp[-2] = js_bool(res ^ is_neq); return 0; } @@ -14862,6 +16095,7 @@ static __exception int js_operator_typeof(JSContext *ctx, JSValue op1) atom = JS_ATOM_boolean; break; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: atom = JS_ATOM_string; break; case JS_TAG_OBJECT: @@ -14970,33 +16204,27 @@ static const JSClassExoticMethods js_arguments_exotic_methods = { static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv) { JSValue val, *tab; - JSProperty *pr; + JSProperty props[3]; JSObject *p; int i; - val = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], - JS_CLASS_ARGUMENTS); + props[0].u.value = js_int32(argc); /* length */ + props[1].u.value = js_dup(ctx->array_proto_values); /* Symbol.iterator */ + props[2].u.getset.getter = JS_VALUE_GET_OBJ(js_dup(ctx->throw_type_error)); /* callee */ + props[2].u.getset.setter = JS_VALUE_GET_OBJ(js_dup(ctx->throw_type_error)); /* callee */ + + val = JS_NewObjectFromShape(ctx, js_dup_shape(ctx->arguments_shape), + JS_CLASS_ARGUMENTS, props); if (JS_IsException(val)) return val; p = JS_VALUE_GET_OBJ(val); - /* add the length field (cannot fail) */ - pr = add_property(ctx, p, JS_ATOM_length, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - if (!pr) { - JS_FreeValue(ctx, val); - return JS_EXCEPTION; - } - pr->u.value = js_int32(argc); - /* initialize the fast array part */ tab = NULL; if (argc > 0) { tab = js_malloc(ctx, sizeof(tab[0]) * argc); - if (!tab) { - JS_FreeValue(ctx, val); - return JS_EXCEPTION; - } + if (!tab) + goto fail; for(i = 0; i < argc; i++) { tab[i] = js_dup(argv[i]); } @@ -15004,71 +16232,95 @@ static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv) p->u.array.u.values = tab; p->u.array.count = argc; - JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator, - js_dup(ctx->array_proto_values), - JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); - /* add callee property to throw a TypeError in strict mode */ - JS_DefineProperty(ctx, val, JS_ATOM_callee, JS_UNDEFINED, - ctx->throw_type_error, ctx->throw_type_error, - JS_PROP_HAS_GET | JS_PROP_HAS_SET); return val; + fail: + JS_FreeValue(ctx, val); + return JS_EXCEPTION; } #define GLOBAL_VAR_OFFSET 0x40000000 #define ARGUMENT_VAR_OFFSET 0x20000000 +static void js_mapped_arguments_finalizer(JSRuntime *rt, JSValueConst val) +{ + JSObject *p = JS_VALUE_GET_OBJ(val); + if (p->fast_array) { + JSVarRef **var_refs = p->u.array.u.var_refs; + int i; + if (var_refs) { + for(i = 0; i < p->u.array.count; i++) { + if (var_refs[i]) + free_var_ref(rt, var_refs[i]); + } + js_free_rt(rt, var_refs); + } + } +} + +static void js_mapped_arguments_mark(JSRuntime *rt, JSValueConst val, + JS_MarkFunc *mark_func) +{ + JSObject *p = JS_VALUE_GET_OBJ(val); + if (p->fast_array) { + JSVarRef **var_refs = p->u.array.u.var_refs; + int i; + if (var_refs) { + for(i = 0; i < p->u.array.count; i++) { + if (var_refs[i] && var_refs[i]->is_detached) + mark_func(rt, &var_refs[i]->header); + } + } + } +} + /* legacy arguments object: add references to the function arguments */ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc, JSValueConst *argv, JSStackFrame *sf, int arg_count) { JSValue val; - JSProperty *pr; + JSProperty props[3]; + JSVarRef **tab, *var_ref; JSObject *p; - int i; + int i, j; + + props[0].u.value = js_int32(argc); /* length */ + props[1].u.value = js_dup(ctx->array_proto_values); /* Symbol.iterator */ + props[2].u.value = js_dup(ctx->rt->current_stack_frame->cur_func); /* callee */ - val = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], - JS_CLASS_MAPPED_ARGUMENTS); + val = JS_NewObjectFromShape(ctx, js_dup_shape(ctx->mapped_arguments_shape), + JS_CLASS_MAPPED_ARGUMENTS, props); if (JS_IsException(val)) return val; p = JS_VALUE_GET_OBJ(val); - /* add the length field (cannot fail) */ - pr = add_property(ctx, p, JS_ATOM_length, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - if (!pr) - goto fail; - pr->u.value = js_int32(argc); - - for(i = 0; i < arg_count; i++) { - JSVarRef *var_ref; - var_ref = get_var_ref(ctx, sf, i, true); - if (!var_ref) - goto fail; - pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF); - if (!pr) { - free_var_ref(ctx->rt, var_ref); + /* initialize the fast array part */ + tab = NULL; + if (argc > 0) { + tab = js_malloc(ctx, sizeof(tab[0]) * argc); + if (!tab) goto fail; + for(i = 0; i < arg_count; i++) { + var_ref = get_var_ref(ctx, sf, i, true); + if (!var_ref) + goto fail1; + tab[i] = var_ref; + } + for(i = arg_count; i < argc; i++) { + var_ref = js_create_var_ref(ctx, true); + if (!var_ref) { + fail1: + for(j = 0; j < i; j++) + free_var_ref(ctx->rt, tab[j]); + js_free(ctx, tab); + goto fail; + } + var_ref->value = js_dup(argv[i]); + tab[i] = var_ref; } - pr->u.var_ref = var_ref; - } - - /* the arguments not mapped to the arguments of the function can - be normal properties */ - for(i = arg_count; i < argc; i++) { - if (JS_DefinePropertyValueUint32(ctx, val, i, - js_dup(argv[i]), - JS_PROP_C_W_E) < 0) - goto fail; } - - JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator, - js_dup(ctx->array_proto_values), - JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); - /* callee returns this function in non strict mode */ - JS_DefinePropertyValue(ctx, val, JS_ATOM_callee, - js_dup(ctx->rt->current_stack_frame->cur_func), - JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); + p->u.array.u.var_refs = tab; + p->u.array.count = argc; return val; fail: JS_FreeValue(ctx, val); @@ -15142,7 +16394,7 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj) JSShapeProperty *prs; /* check that there are no enumerable normal fields */ sh = p->shape; - for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { + for(i = 0, prs = sh->prop; i < sh->prop_count; i++, prs++) { if (prs->flags & JS_PROP_ENUMERABLE) goto normal_case; } @@ -15234,7 +16486,7 @@ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp) JSShapeProperty *prs; if (it->idx >= sh->prop_count) goto done; - prs = get_shape_prop(sh) + it->idx; + prs = &sh->prop[it->idx]; prop = prs->atom; it->idx++; if (prop == JS_ATOM_NULL || !(prs->flags & JS_PROP_ENUMERABLE)) @@ -15497,6 +16749,63 @@ static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValue obj, return JS_EXCEPTION; } +static JSValue js_sync_dispose_wrapper(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, + int magic, JSValueConst *func_data); + +static __exception int js_op_using_check(JSContext *ctx, JSValueConst val, + int hint, JSValue *pmethod) +{ + JSValue method; + bool is_sync_fallback = false; + + *pmethod = JS_UNDEFINED; + if (JS_IsNull(val) || JS_IsUndefined(val)) + return 0; + if (!JS_IsObject(val)) { + JS_ThrowTypeErrorNotAnObject(ctx); + return -1; + } + if (hint == 1) { + method = JS_GetProperty(ctx, val, JS_ATOM_Symbol_asyncDispose); + if (JS_IsException(method)) + return -1; + if (JS_IsUndefined(method) || JS_IsNull(method)) { + JS_FreeValue(ctx, method); + method = JS_GetProperty(ctx, val, JS_ATOM_Symbol_dispose); + if (JS_IsException(method)) + return -1; + is_sync_fallback = true; + } + } else { + method = JS_GetProperty(ctx, val, JS_ATOM_Symbol_dispose); + if (JS_IsException(method)) + return -1; + } + if (JS_IsUndefined(method) || JS_IsNull(method)) { + JS_ThrowTypeError(ctx, "value is not disposable"); + return -1; + } + if (!JS_IsFunction(ctx, method)) { + JS_FreeValue(ctx, method); + JS_ThrowTypeError(ctx, "dispose method is not a function"); + return -1; + } + if (is_sync_fallback) { + JSValueConst data[1]; + JSValue wrapped; + data[0] = method; + wrapped = JS_NewCFunctionData(ctx, js_sync_dispose_wrapper, 0, 0, + 1, data); + JS_FreeValue(ctx, method); + if (JS_IsException(wrapped)) + return -1; + method = wrapped; + } + *pmethod = method; + return 0; +} + static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp) { JSValue obj, value; @@ -15669,7 +16978,7 @@ static __exception int JS_CopyDataProperties(JSContext *ctx, JSObject *p; JSObject *pexcl = NULL; int ret, gpn_flags; - JSPropertyDescriptor desc; + int desc_flags; bool is_enumerable; if (JS_VALUE_GET_TAG(source) != JS_TAG_OBJECT) @@ -15704,13 +17013,12 @@ static __exception int JS_CopyDataProperties(JSContext *ctx, } if (!(gpn_flags & JS_GPN_ENUM_ONLY)) { /* test if the property is enumerable */ - ret = JS_GetOwnPropertyInternal(ctx, &desc, p, tab_atom[i].atom); + ret = JS_GetOwnPropertyFlagsInternal(ctx, &desc_flags, p, tab_atom[i].atom); if (ret < 0) goto exception; if (!ret) continue; - is_enumerable = (desc.flags & JS_PROP_ENUMERABLE) != 0; - js_free_desc(ctx, &desc); + is_enumerable = (desc_flags & JS_PROP_ENUMERABLE) != 0; if (!is_enumerable) continue; } @@ -15738,35 +17046,79 @@ static JSValueConst JS_GetActiveFunction(JSContext *ctx) return ctx->rt->current_stack_frame->cur_func; } -static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, - int var_idx, bool is_arg) +/* create a detached var ref */ +static JSVarRef *js_create_var_ref(JSContext *ctx, bool is_gc_object) { JSVarRef *var_ref; - struct list_head *el; + var_ref = js_malloc(ctx, sizeof(JSVarRef)); + if (!var_ref) + return NULL; + var_ref->header.ref_count = 1; + var_ref->is_detached = true; + var_ref->value = JS_UNDEFINED; + var_ref->pvalue = &var_ref->value; + if (is_gc_object) + add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); + return var_ref; +} + +static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx, + bool is_arg) +{ + JSObject *p; + JSFunctionBytecode *b; + JSVarRef *var_ref; JSValue *pvalue; + int var_ref_idx; + JSVarDef *vd; - if (is_arg) + p = JS_VALUE_GET_OBJ(sf->cur_func); + b = p->u.func.function_bytecode; + + if (is_arg) { + vd = &b->vardefs[var_idx]; pvalue = &sf->arg_buf[var_idx]; - else + } else { + vd = &b->vardefs[b->arg_count + var_idx]; pvalue = &sf->var_buf[var_idx]; + } - list_for_each(el, &sf->var_ref_list) { - var_ref = list_entry(el, JSVarRef, header.link); - if (var_ref->pvalue == pvalue) { + /* If the variable is captured, use the pre-computed index for O(1) lookup */ + if (vd->is_captured) { + var_ref_idx = vd->var_ref_idx; + var_ref = sf->var_refs[var_ref_idx]; + if (var_ref) { + /* reference to the already created local variable */ var_ref->header.ref_count++; return var_ref; } + + /* create a new one */ + var_ref = js_malloc(ctx, sizeof(JSVarRef)); + if (!var_ref) + return NULL; + var_ref->header.ref_count = 1; + var_ref->is_detached = false; + var_ref->is_lexical = false; + var_ref->is_const = false; + var_ref->var_ref_idx = var_ref_idx; + var_ref->stack_frame = sf; + sf->var_refs[var_ref_idx] = var_ref; + var_ref->pvalue = pvalue; + return var_ref; + } else { + /* Variable is not captured (e.g., from eval closures on uncaptured vars). + Create a detached var_ref that holds a copy of the value. */ + var_ref = js_malloc(ctx, sizeof(JSVarRef)); + if (!var_ref) + return NULL; + var_ref->header.ref_count = 1; + var_ref->is_detached = true; + var_ref->value = js_dup(*pvalue); + var_ref->pvalue = &var_ref->value; + add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); + return var_ref; } - /* create a new one */ - var_ref = js_malloc(ctx, sizeof(JSVarRef)); - if (!var_ref) - return NULL; - var_ref->header.ref_count = 1; - var_ref->is_detached = false; - list_add_tail(&var_ref->header.link, &sf->var_ref_list); - var_ref->pvalue = pvalue; - var_ref->value = JS_UNDEFINED; - return var_ref; } static JSValue js_closure2(JSContext *ctx, JSValue func_obj, @@ -15790,15 +17142,25 @@ static JSValue js_closure2(JSContext *ctx, JSValue func_obj, for(i = 0; i < b->closure_var_count; i++) { JSClosureVar *cv = &b->closure_var[i]; JSVarRef *var_ref; - if (cv->is_local) { + switch(cv->closure_type) { + case JS_CLOSURE_LOCAL: /* reuse the existing variable reference if it already exists */ - var_ref = get_var_ref(ctx, sf, cv->var_idx, cv->is_arg); - if (!var_ref) - goto fail; - } else { + var_ref = get_var_ref(ctx, sf, cv->var_idx, false); + break; + case JS_CLOSURE_ARG: + /* reuse the existing variable reference if it already exists */ + var_ref = get_var_ref(ctx, sf, cv->var_idx, true); + break; + case JS_CLOSURE_REF: + case JS_CLOSURE_GLOBAL_REF: var_ref = cur_var_refs[cv->var_idx]; var_ref->header.ref_count++; + break; + default: + abort(); } + if (!var_ref) + goto fail; var_refs[i] = var_ref; } } @@ -15985,38 +17347,38 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp, return -1; } +static void close_var_ref(JSRuntime *rt, JSVarRef *var_ref) +{ + var_ref->value = js_dup(*var_ref->pvalue); + var_ref->pvalue = &var_ref->value; + /* the reference is no longer to a local variable */ + var_ref->is_detached = true; + add_gc_object(rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); +} + static void close_var_refs(JSRuntime *rt, JSStackFrame *sf) { - struct list_head *el, *el1; JSVarRef *var_ref; + int i; - list_for_each_safe(el, el1, &sf->var_ref_list) { - var_ref = list_entry(el, JSVarRef, header.link); - var_ref->value = js_dup(*var_ref->pvalue); - var_ref->pvalue = &var_ref->value; - /* the reference is no longer to a local variable */ - var_ref->is_detached = true; - add_gc_object(rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); + for (i = 0; i < sf->var_ref_count; i++) { + var_ref = sf->var_refs[i]; + if (var_ref) + close_var_ref(rt, var_ref); } } -static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int var_idx) +static void close_lexical_var(JSContext *ctx, JSFunctionBytecode *b, + JSStackFrame *sf, int var_idx) { - JSValue *pvalue; - struct list_head *el, *el1; JSVarRef *var_ref; + int var_ref_idx; - pvalue = &sf->var_buf[var_idx]; - list_for_each_safe(el, el1, &sf->var_ref_list) { - var_ref = list_entry(el, JSVarRef, header.link); - if (var_ref->pvalue == pvalue) { - var_ref->value = js_dup(*var_ref->pvalue); - var_ref->pvalue = &var_ref->value; - list_del(&var_ref->header.link); - /* the reference is no longer to a local variable */ - var_ref->is_detached = true; - add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); - } + var_ref_idx = b->vardefs[b->arg_count + var_idx].var_ref_idx; + var_ref = sf->var_refs[var_ref_idx]; + if (var_ref) { + close_var_ref(ctx->rt, var_ref); + sf->var_refs[var_ref_idx] = NULL; } } @@ -16309,7 +17671,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } alloca_size = sizeof(JSValue) * (arg_allocated_size + b->var_count + - b->stack_size); + b->stack_size) + + sizeof(JSVarRef *) * b->var_ref_count; if (js_check_stack_overflow(rt, alloca_size)) return JS_ThrowStackOverflow(caller_ctx); @@ -16317,7 +17680,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, arg_buf = (JSValue *)argv; sf->arg_count = argc; sf->cur_func = unsafe_unconst(func_obj); - init_list_head(&sf->var_ref_list); var_refs = p->u.func.var_refs; local_buf = alloca(alloca_size); @@ -16338,6 +17700,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, var_buf[i] = JS_UNDEFINED; stack_buf = var_buf + b->var_count; + sf->var_refs = (JSVarRef **)(stack_buf + b->stack_size); + sf->var_ref_count = b->var_ref_count; + for(i = 0; i < b->var_ref_count; i++) + sf->var_refs[i] = NULL; sp = stack_buf; pc = b->byte_code_buf; /* sf->cur_pc must we set to pc before any recursive calls to JS_CallInternal. */ @@ -16401,12 +17767,43 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_get_length): { - JSValue val; + JSValue val, obj; + JSAtom atom; + JSObject *p; + JSProperty *pr; + JSShapeProperty *prs; - sf->cur_pc = pc; - val = JS_GetProperty(ctx, sp[-1], JS_ATOM_length); - if (unlikely(JS_IsException(val))) - goto exception; + atom = JS_ATOM_length; + + obj = sp[-1]; + if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT)) { + p = JS_VALUE_GET_OBJ(obj); + for(;;) { + prs = find_own_property(&pr, p, atom); + if (prs) { + /* found */ + if (unlikely(prs->flags & JS_PROP_TMASK)) + goto get_length_slow_path; + val = js_dup(pr->u.value); + break; + } + if (unlikely(p->is_exotic)) { + obj = JS_MKPTR(JS_TAG_OBJECT, p); + goto get_length_slow_path; + } + p = p->shape->proto; + if (!p) { + val = JS_UNDEFINED; + break; + } + } + } else { + get_length_slow_path: + sf->cur_pc = pc; + val = JS_GetPropertyInternal(ctx, obj, atom, sp[-1], false); + if (unlikely(JS_IsException(val))) + goto exception; + } JS_FreeValue(ctx, sp[-1]); sp[-1] = val; } @@ -16511,7 +17908,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, pc += 2; i = min_int(first, argc); n = argc - i; - *sp++ = js_create_array(ctx, n, &argv[i]); + *sp++ = js_create_array(ctx, n, n ? &argv[i] : NULL); if (unlikely(JS_IsException(sp[-1]))) goto exception; } @@ -16928,6 +18325,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp[-2] = js_regexp_constructor_internal(ctx, JS_UNDEFINED, sp[-2], sp[-1]); sp--; + if (JS_IsException(sp[-1])) + goto exception; } BREAK; @@ -16946,28 +18345,16 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; sf->cur_pc = pc; - val = js_dynamic_import(ctx, sp[-1]); + val = js_dynamic_import(ctx, sp[-2], sp[-1]); if (JS_IsException(val)) goto exception; + JS_FreeValue(ctx, sp[-2]); JS_FreeValue(ctx, sp[-1]); + sp--; sp[-1] = val; } BREAK; - CASE(OP_check_var): - { - int ret; - JSAtom atom; - atom = get_u32(pc); - pc += 4; - - ret = JS_CheckGlobalVar(ctx, atom); - if (ret < 0) - goto exception; - *sp++ = js_bool(ret); - } - BREAK; - CASE(OP_get_var_undef): CASE(OP_get_var): { @@ -17000,26 +18387,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } BREAK; - CASE(OP_put_var_strict): - { - int ret; - JSAtom atom; - atom = get_u32(pc); - pc += 4; - sf->cur_pc = pc; - - /* sp[-2] is JS_TRUE or JS_FALSE */ - if (unlikely(!JS_VALUE_GET_INT(sp[-2]))) { - JS_ThrowReferenceErrorNotDefined(ctx, atom); - goto exception; - } - ret = JS_SetGlobalVar(ctx, atom, sp[-1], 2); - sp -= 2; - if (unlikely(ret < 0)) - goto exception; - } - BREAK; - CASE(OP_check_define_var): { JSAtom atom; @@ -17282,7 +18649,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int idx; idx = get_u16(pc); pc += 2; - close_lexical_var(ctx, sf, idx); + close_lexical_var(ctx, b, sf, idx); } BREAK; @@ -17503,9 +18870,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, goto exception; sp += 1; BREAK; - CASE(OP_iterator_check_object): + CASE(OP_check_object): if (unlikely(!JS_IsObject(sp[-1]))) { - JS_ThrowTypeError(ctx, "iterator must return an object"); + JS_ThrowTypeErrorNotAnObject(ctx); goto exception; } BREAK; @@ -17541,6 +18908,124 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } BREAK; + CASE(OP_using_dispose_init): + sp[0] = JS_UNINITIALIZED; + sp++; + BREAK; + + CASE(OP_using_dispose): + { + int idx; + JSValueConst val, method; + JSValue ret, error_state; + + idx = get_u16(pc); + pc += 2; + val = var_buf[idx]; + method = var_buf[idx + 1]; + error_state = sp[-1]; + + if (JS_IsNull(val) || JS_IsUndefined(val) || + JS_IsUninitialized(val)) { + /* null/undefined (spec-permitted) or uninitialized + (declaration threw before assignment). */ + BREAK; + } + sf->cur_pc = pc; + ret = JS_Call(ctx, method, val, 0, NULL); + if (JS_IsException(ret)) { + JSValue new_error = JS_GetException(ctx); + if (!JS_IsUninitialized(error_state)) { + JSValue se; + se = js_new_suppressed_error(ctx, new_error, + error_state); + JS_FreeValue(ctx, new_error); + JS_FreeValue(ctx, error_state); + if (JS_IsException(se)) { + sp[-1] = JS_GetException(ctx); + } else { + sp[-1] = se; + } + } else { + sp[-1] = new_error; + } + } else { + JS_FreeValue(ctx, ret); + } + } + BREAK; + + CASE(OP_using_dispose_async): + { + int idx; + JSValueConst val, method; + JSValue ret; + + idx = get_u16(pc); + pc += 2; + val = var_buf[idx]; + method = var_buf[idx + 1]; + + if (JS_IsNull(val) || JS_IsUndefined(val) || + JS_IsUninitialized(val)) { + sp[0] = JS_UNDEFINED; + sp++; + BREAK; + } + sf->cur_pc = pc; + ret = JS_Call(ctx, method, val, 0, NULL); + if (JS_IsException(ret)) + goto exception; + sp[0] = ret; + sp++; + } + BREAK; + + CASE(OP_using_dispose_merge): + { + JSValue new_error = sp[-1]; + JSValue error_state = sp[-2]; + sp--; + if (!JS_IsUninitialized(error_state)) { + JSValue se = js_new_suppressed_error(ctx, new_error, + error_state); + JS_FreeValue(ctx, new_error); + JS_FreeValue(ctx, error_state); + if (JS_IsException(se)) { + sp[-1] = JS_GetException(ctx); + } else { + sp[-1] = se; + } + } else { + sp[-1] = new_error; + } + } + BREAK; + + CASE(OP_using_dispose_end): + { + JSValue error_state = sp[-1]; + sp--; + if (!JS_IsUninitialized(error_state)) { + JS_Throw(ctx, error_state); + goto exception; + } + } + BREAK; + + CASE(OP_using_check): + { + int hint = pc[0]; + JSValue method; + pc += 1; + sf->cur_pc = pc; + if (js_op_using_check(ctx, sp[-1], hint, &method)) + goto exception; + sp[0] = method; + sp++; + } + BREAK; + CASE(OP_iterator_next): /* stack: iter_obj next catch_offset val */ { @@ -17605,14 +19090,47 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_get_field): { - JSValue val; + JSValue val, obj; JSAtom atom; + JSObject *p; + JSProperty *pr; + JSShapeProperty *prs; + atom = get_u32(pc); pc += 4; - sf->cur_pc = pc; - val = JS_GetPropertyInternal(ctx, sp[-1], atom, sp[-1], false); - if (unlikely(JS_IsException(val))) - goto exception; + + obj = sp[-1]; + if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT)) { + p = JS_VALUE_GET_OBJ(obj); + for(;;) { + prs = find_own_property(&pr, p, atom); + if (prs) { + /* found */ + if (unlikely(prs->flags & JS_PROP_TMASK)) + goto get_field_slow_path; + val = js_dup(pr->u.value); + break; + } + if (unlikely(p->is_exotic)) { + /* XXX: should avoid the slow path for arrays + and typed arrays by ensuring that 'prop' is + not numeric */ + obj = JS_MKPTR(JS_TAG_OBJECT, p); + goto get_field_slow_path; + } + p = p->shape->proto; + if (!p) { + val = JS_UNDEFINED; + break; + } + } + } else { + get_field_slow_path: + sf->cur_pc = pc; + val = JS_GetPropertyInternal(ctx, obj, atom, sp[-1], false); + if (unlikely(JS_IsException(val))) + goto exception; + } JS_FreeValue(ctx, sp[-1]); sp[-1] = val; } @@ -17620,33 +19138,88 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_get_field2): { - JSValue val; + JSValue val, obj; JSAtom atom; + JSObject *p; + JSProperty *pr; + JSShapeProperty *prs; + atom = get_u32(pc); pc += 4; - sf->cur_pc = pc; - val = JS_GetPropertyInternal(ctx, sp[-1], atom, sp[-1], false); - if (unlikely(JS_IsException(val))) - goto exception; + + obj = sp[-1]; + if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT)) { + p = JS_VALUE_GET_OBJ(obj); + for(;;) { + prs = find_own_property(&pr, p, atom); + if (prs) { + /* found */ + if (unlikely(prs->flags & JS_PROP_TMASK)) + goto get_field2_slow_path; + val = js_dup(pr->u.value); + break; + } + if (unlikely(p->is_exotic)) { + /* XXX: should avoid the slow path for arrays + and typed arrays by ensuring that 'prop' is + not numeric */ + obj = JS_MKPTR(JS_TAG_OBJECT, p); + goto get_field2_slow_path; + } + p = p->shape->proto; + if (!p) { + val = JS_UNDEFINED; + break; + } + } + } else { + get_field2_slow_path: + sf->cur_pc = pc; + val = JS_GetPropertyInternal(ctx, obj, atom, sp[-1], false); + if (unlikely(JS_IsException(val))) + goto exception; + } *sp++ = val; - } - BREAK; + } + BREAK; CASE(OP_put_field): { int ret; + JSValue obj; JSAtom atom; + JSObject *p; + JSProperty *pr; + JSShapeProperty *prs; + atom = get_u32(pc); pc += 4; - sf->cur_pc = pc; - ret = JS_SetPropertyInternal2(ctx, - sp[-2], atom, - sp[-1], sp[-2], - JS_PROP_THROW_STRICT); - JS_FreeValue(ctx, sp[-2]); - sp -= 2; - if (unlikely(ret < 0)) - goto exception; + + obj = sp[-2]; + if (likely(JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT)) { + p = JS_VALUE_GET_OBJ(obj); + prs = find_own_property(&pr, p, atom); + if (!prs) + goto put_field_slow_path; + if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE | + JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) { + /* fast path */ + set_value(ctx, &pr->u.value, sp[-1]); + } else { + goto put_field_slow_path; + } + JS_FreeValue(ctx, obj); + sp -= 2; + } else { + put_field_slow_path: + sf->cur_pc = pc; + ret = JS_SetPropertyInternal2(ctx, obj, atom, sp[-1], obj, + JS_PROP_THROW_STRICT); + JS_FreeValue(ctx, obj); + sp -= 2; + if (unlikely(ret < 0)) + goto exception; + } } BREAK; @@ -17898,6 +19471,46 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_put_array_el): { int ret; + JSValue val; + uint32_t idx; + JSObject *p; + + val = sp[-1]; + if (likely(JS_VALUE_GET_TAG(sp[-2]) == JS_TAG_INT)) { + idx = JS_VALUE_GET_INT(sp[-2]); + if (likely(JS_VALUE_GET_TAG(sp[-3]) == JS_TAG_OBJECT)) { + p = JS_VALUE_GET_OBJ(sp[-3]); + if (likely(p->class_id == JS_CLASS_ARRAY && + idx < (uint32_t)p->u.array.count)) { + set_value(ctx, &p->u.array.u.values[idx], val); + JS_FreeValue(ctx, sp[-3]); + sp -= 3; + BREAK; + } + if (likely(p->class_id == JS_CLASS_ARRAY && + idx == (uint32_t)p->u.array.count && + p->fast_array && + p->extensible && + p->shape->proto == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_ARRAY]) && + ctx->std_array_prototype)) { + /* fast path to add an element */ + uint32_t array_len; + if (likely(JS_VALUE_GET_TAG(p->prop[0].u.value) == JS_TAG_INT)) { + uint32_t new_len = idx + 1; + array_len = JS_VALUE_GET_INT(p->prop[0].u.value); + if (likely(new_len <= p->u.array.u1.size)) { + p->u.array.u.values[idx] = val; + p->u.array.count = new_len; + if (new_len > array_len) + p->prop[0].u.value = js_int32(new_len); + JS_FreeValue(ctx, sp[-3]); + sp -= 3; + BREAK; + } + } + } + } + } sf->cur_pc = pc; ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], JS_PROP_THROW_STRICT); JS_FreeValue(ctx, sp[-3]); @@ -18006,9 +19619,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { int64_t r; r = (int64_t)JS_VALUE_GET_INT(op1) + JS_VALUE_GET_INT(op2); - if (unlikely((int)r != r)) - goto add_slow; - sp[-2] = js_int32(r); + if (unlikely(r < INT32_MIN || r > INT32_MAX)) + sp[-2] = js_float64(r); + else + sp[-2] = js_int32(r); sp--; } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { JS_X87_FPCW_SAVE_AND_ADJUST(fpcw); @@ -18017,7 +19631,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_X87_FPCW_RESTORE(fpcw); sp--; } else { - add_slow: sf->cur_pc = pc; if (js_add_slow(ctx, sp)) goto exception; @@ -18038,8 +19651,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, r = (int64_t)JS_VALUE_GET_INT(*pv) + JS_VALUE_GET_INT(sp[-1]); if (unlikely((int)r != r)) - goto add_loc_slow; - *pv = js_int32(r); + *pv = __JS_NewFloat64((double)r); + else + *pv = js_int32(r); sp--; } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) { JSValue op1; @@ -18055,7 +19669,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, set_value(ctx, pv, op1); } else { JSValue ops[2]; - add_loc_slow: /* In case of exception, js_add_slow frees ops[0] and ops[1], so we must duplicate *pv */ sf->cur_pc = pc; @@ -18077,8 +19690,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int64_t r; r = (int64_t)JS_VALUE_GET_INT(op1) - JS_VALUE_GET_INT(op2); if (unlikely((int)r != r)) - goto binary_arith_slow; - sp[-2] = js_int32(r); + sp[-2] = __JS_NewFloat64((double)r); + else + sp[-2] = js_int32(r); sp--; } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { JS_X87_FPCW_SAVE_AND_ADJUST(fpcw); @@ -18253,11 +19867,42 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } BREAK; CASE(OP_post_inc): + { + JSValue op1; + int val; + op1 = sp[-1]; + if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { + val = JS_VALUE_GET_INT(op1); + if (unlikely(val == INT32_MAX)) + goto post_inc_slow; + sp[0] = js_int32(val + 1); + } else { + post_inc_slow: + sf->cur_pc = pc; + if (js_post_inc_slow(ctx, sp, opcode)) + goto exception; + } + sp++; + } + BREAK; CASE(OP_post_dec): - sf->cur_pc = pc; - if (js_post_inc_slow(ctx, sp, opcode)) - goto exception; - sp++; + { + JSValue op1; + int val; + op1 = sp[-1]; + if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { + val = JS_VALUE_GET_INT(op1); + if (unlikely(val == INT32_MIN)) + goto post_dec_slow; + sp[0] = js_int32(val - 1); + } else { + post_dec_slow: + sf->cur_pc = pc; + if (js_post_inc_slow(ctx, sp, opcode)) + goto exception; + } + sp++; + } BREAK; CASE(OP_inc_loc): { @@ -18748,7 +20393,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sf->cur_sp = sp; } else { done: - if (unlikely(!list_empty(&sf->var_ref_list))) { + if (unlikely(sf->var_ref_count != 0)) { /* variable references reference the stack: must close them */ close_var_refs(rt, sf); } @@ -18947,16 +20592,18 @@ static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s, JSFunctionBytecode *b; JSStackFrame *sf; int local_count, i, arg_buf_len, n; + size_t alloc_size; sf = &s->frame; - init_list_head(&sf->var_ref_list); p = JS_VALUE_GET_OBJ(func_obj); b = p->u.func.function_bytecode; sf->is_strict_mode = b->is_strict_mode; sf->cur_pc = b->byte_code_buf; arg_buf_len = max_int(b->arg_count, argc); local_count = arg_buf_len + b->var_count + b->stack_size; - sf->arg_buf = js_malloc(ctx, sizeof(JSValue) * max_int(local_count, 1)); + alloc_size = sizeof(JSValue) * max_int(local_count, 1) + + sizeof(JSVarRef *) * b->var_ref_count; + sf->arg_buf = js_malloc(ctx, alloc_size); if (!sf->arg_buf) return -1; sf->cur_func = js_dup(func_obj); @@ -18965,6 +20612,10 @@ static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s, sf->arg_count = arg_buf_len; sf->var_buf = sf->arg_buf + arg_buf_len; sf->cur_sp = sf->var_buf + b->var_count; + sf->var_refs = (JSVarRef **)(sf->cur_sp + b->stack_size); + sf->var_ref_count = b->var_ref_count; + for(i = 0; i < b->var_ref_count; i++) + sf->var_refs[i] = NULL; for(i = 0; i < argc; i++) sf->arg_buf[i] = js_dup(argv[i]); n = arg_buf_len + b->var_count; @@ -18999,10 +20650,11 @@ static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s) sf = &s->frame; - /* close the closure variables. */ - close_var_refs(rt, sf); - if (sf->arg_buf) { + /* close the closure variables. */ + if (sf->var_ref_count != 0) + close_var_refs(rt, sf); + /* cannot free the function if it is running */ assert(sf->cur_sp != NULL); for(sp = sf->arg_buf; sp < sf->cur_sp; sp++) { @@ -19754,9 +21406,8 @@ static JSValue js_async_generator_resolve_function(JSContext *ctx, } else { js_async_generator_resolve(ctx, s, arg, true); } - } else { + } else if (s->state == JS_ASYNC_GENERATOR_STATE_EXECUTING) { /* restart function execution after await() */ - assert(s->state == JS_ASYNC_GENERATOR_STATE_EXECUTING); s->func_state.throw_flag = is_reject; if (is_reject) { JS_Throw(ctx, js_dup(arg)); @@ -19935,6 +21586,7 @@ enum { TOK_EXTENDS, TOK_IMPORT, TOK_SUPER, + TOK_USING, /* FutureReservedWords when parsing strict mode code */ TOK_IMPLEMENTS, TOK_INTERFACE, @@ -19969,6 +21621,8 @@ typedef struct BlockEnv { int scope_level; uint8_t has_iterator : 1; uint8_t is_regular_stmt : 1; // i.e. not a loop statement + uint8_t has_using : 1; /* scope has using declarations needing disposal */ + int using_scope_level; /* scope level for OP_dispose_scope (-1 if none) */ } BlockEnv; typedef struct JSGlobalVar { @@ -20065,7 +21719,7 @@ typedef struct JSFunctionDef { bool need_home_object : 1; bool use_short_opcodes : 1; /* true if short opcodes are used in byte_code */ bool has_await : 1; /* true if await is used (used in module eval) */ - + JSFunctionKindEnum func_kind : 8; JSParseFunctionEnum func_type : 7; uint8_t is_strict_mode : 1; @@ -20079,6 +21733,7 @@ typedef struct JSFunctionDef { int arg_size; /* allocated size for args[] */ int arg_count; /* number of arguments */ int defined_arg_count; + int var_ref_count; /* number of local/arg variable references */ int var_object_idx; /* -1 if none */ int arg_var_object_idx; /* -1 if none (var object for the argument scope) */ int arguments_var_idx; /* -1 if none */ @@ -20224,6 +21879,21 @@ static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = { opcode_info[(op) >= OP_TEMP_START ? \ (op) + (OP_TEMP_END - OP_TEMP_START) : (op)] +static void json_free_token(JSParseState *s, JSToken *token) { + // Only free actual allocated values + switch(token->val) { + case TOK_NUMBER: + JS_FreeValue(s->ctx, token->u.num.val); + break; + case TOK_STRING: + JS_FreeValue(s->ctx, token->u.str.str); + break; + case TOK_IDENT: + JS_FreeAtom(s->ctx, token->u.ident.atom); + break; + } +} + static void free_token(JSParseState *s, JSToken *token) { switch(token->val) { @@ -20729,6 +22399,12 @@ static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize, /* convert a TOK_IDENT to a keyword when needed */ static void update_token_ident(JSParseState *s) { + /* `using` is contextually reserved, not a true keyword. Leave it as + TOK_IDENT so it can be used as a regular identifier in expressions. + Using declarations are detected explicitly at statement and + for-loop head parsing via token_is_pseudo_keyword. */ + if (s->token.u.ident.atom == JS_ATOM_using) + return; if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD || (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD && s->cur_func->is_strict_mode) || @@ -21047,6 +22723,7 @@ static __exception int next_token(JSParseState *s) if (JS_VALUE_IS_NAN(ret) || lre_js_is_ident_next(utf8_decode(p, &p1))) { JS_FreeValue(s->ctx, ret); + s->col_num = max_int(1, s->mark - s->eol); js_parse_error(s, "invalid number literal"); goto fail; } @@ -21305,7 +22982,7 @@ static int json_parse_string(JSParseState *s, const uint8_t **pp) uint32_t c; StringBuffer b_s, *b = &b_s; - if (string_buffer_init(s->ctx, b, 32)) + if (string_buffer_init(s->ctx, b, 48)) goto fail; p = *pp; @@ -21313,6 +22990,22 @@ static int json_parse_string(JSParseState *s, const uint8_t **pp) if (p >= s->buf_end) { goto end_of_input; } + + // Fast path: batch consecutive ASCII characters + const uint8_t *p_start = p; + while (p < s->buf_end && *p != '"' && *p != '\\' && *p >= 0x20 && *p < 0x80) { + p++; + } + + // Write batched ASCII in one call + if (p > p_start) { + if (string_buffer_write8(b, p_start, p - p_start)) + goto fail; + } + + if (p >= s->buf_end) + goto end_of_input; + c = *p++; if (c == '"') break; @@ -21458,7 +23151,7 @@ static __exception int json_next_token(JSParseState *s) return -1; } - free_token(s, &s->token); + json_free_token(s, &s->token); p = s->last_ptr = s->buf_ptr; s->last_line_num = s->token.line_num; @@ -21656,6 +23349,9 @@ static int simple_next_token(const uint8_t **pp, bool no_line_terminator) } else if (c == 'a' && p[0] == 'w' && p[1] == 'a' && p[2] == 'i' && p[3] == 't' && !lre_js_is_ident_next(p[4])) { return TOK_AWAIT; + } else if (c == 'u' && p[0] == 's' && p[1] == 'i' && + p[2] == 'n' && p[3] == 'g' && !lre_js_is_ident_next(p[4])) { + return TOK_USING; } return TOK_IDENT; } @@ -21735,14 +23431,19 @@ static void emit_u32(JSParseState *s, uint32_t val) dbuf_put_u32(&s->cur_func->byte_code, val); } -static void emit_source_loc(JSParseState *s) +static void emit_source_loc_at(JSParseState *s, int line_num, int col_num) { JSFunctionDef *fd = s->cur_func; DynBuf *bc = &fd->byte_code; dbuf_putc(bc, OP_source_loc); - dbuf_put_u32(bc, s->token.line_num); - dbuf_put_u32(bc, s->token.col_num); + dbuf_put_u32(bc, line_num); + dbuf_put_u32(bc, col_num); +} + +static void emit_source_loc(JSParseState *s) +{ + emit_source_loc_at(s, s->token.line_num, s->token.col_num); } static void emit_op(JSParseState *s, uint8_t val) @@ -21757,7 +23458,7 @@ static void emit_op(JSParseState *s, uint8_t val) static void emit_atom(JSParseState *s, JSAtom name) { DynBuf *bc = &s->cur_func->byte_code; - if (dbuf_realloc(bc, bc->size + 4)) + if (dbuf_claim(bc, 4)) return; /* not enough memory : don't duplicate the atom */ put_u32(bc->buf + bc->size, JS_DupAtom(s->ctx, name)); bc->size += 4; @@ -21878,23 +23579,6 @@ static __exception int emit_push_const(JSParseState *s, JSValue val, return 0; } -// perl hash; variation of k&r hash with a different magic multiplier -// and a final shuffle to improve distribution of the low-order bits -static uint32_t hash_bytes(uint32_t h, const void *b, size_t n) -{ - const char *p; - - for (p = b; p < (char *)b + n; p++) - h = 33*h + *p; - h += h >> 5; - return h; -} - -static uint32_t hash_atom(JSAtom atom) -{ - return hash_bytes(0, &atom, sizeof(atom)); -} - // caveat emptor: the table size must be a power of two in order for // masking to work, and the load factor constant must be an odd number (5) // @@ -21924,7 +23608,7 @@ static int update_var_htab(JSContext *ctx, JSFunctionDef *fd) insert: m = UINT32_MAX >> clz32(m); do { - i = hash_atom(fd->vars[k].var_name); + i = hash32(fd->vars[k].var_name); j = 1; for (;;) { p = &fd->vars_htab[i & m]; @@ -21942,7 +23626,7 @@ static int find_var_htab(JSFunctionDef *fd, JSAtom var_name) { uint32_t i, j, m, *p; - i = hash_atom(var_name); + i = hash32(var_name); j = 1; m = fd->var_count + fd->var_count/5; m = UINT32_MAX >> clz32(m); @@ -21980,7 +23664,7 @@ static int find_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name) if (i == -1) goto not_found; vd = &fd->vars[i]; - if (fd->vars[i].scope_level == 0) + if (vd->scope_level == 0) return i; } for(i = fd->var_count; i-- > 0;) { @@ -22106,6 +23790,10 @@ static int push_scope(JSParseState *s) { fd->scope_count++; fd->scopes[scope].parent = fd->scope_level; fd->scopes[scope].first = fd->scope_first; + fd->scopes[scope].has_using = 0; + fd->scopes[scope].is_await_using = 0; + fd->scopes[scope].using_label_catch = -1; + fd->scopes[scope].using_label_end = -1; emit_op(s, OP_enter_scope); emit_u16(s, scope); return fd->scope_level = scope; @@ -22279,6 +23967,7 @@ typedef enum { JS_VAR_DEF_NEW_FUNCTION_DECL, /* async/generator function declaration */ JS_VAR_DEF_CATCH, JS_VAR_DEF_VAR, + JS_VAR_DEF_USING, } JSVarDefEnum; static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, @@ -22295,6 +23984,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, case JS_VAR_DEF_LET: case JS_VAR_DEF_CONST: + case JS_VAR_DEF_USING: case JS_VAR_DEF_FUNCTION_DECL: case JS_VAR_DEF_NEW_FUNCTION_DECL: idx = find_lexical_decl(ctx, fd, name, fd->scope_first, true); @@ -22341,9 +24031,10 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, } if (fd->is_eval && - (fd->eval_type == JS_EVAL_TYPE_GLOBAL || - fd->eval_type == JS_EVAL_TYPE_MODULE) && - fd->scope_level == fd->body_scope) { + (fd->eval_type == JS_EVAL_TYPE_GLOBAL || + fd->eval_type == JS_EVAL_TYPE_MODULE) && + fd->scope_level == fd->body_scope && + var_def_type != JS_VAR_DEF_USING) { JSGlobalVar *hf; hf = add_global_var(s->ctx, fd, name); if (!hf) @@ -22357,13 +24048,16 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, var_kind = JS_VAR_FUNCTION_DECL; else if (var_def_type == JS_VAR_DEF_NEW_FUNCTION_DECL) var_kind = JS_VAR_NEW_FUNCTION_DECL; + else if (var_def_type == JS_VAR_DEF_USING) + var_kind = JS_VAR_USING; else var_kind = JS_VAR_NORMAL; idx = add_scope_var(ctx, fd, name, var_kind); if (idx >= 0) { vd = &fd->vars[idx]; vd->is_lexical = 1; - vd->is_const = (var_def_type == JS_VAR_DEF_CONST); + vd->is_const = (var_def_type == JS_VAR_DEF_CONST || + var_def_type == JS_VAR_DEF_USING); } } break; @@ -22768,6 +24462,7 @@ static bool is_regexp_allowed(int tok) case TOK_FALSE: case TOK_TRUE: case TOK_THIS: + case TOK_PRIVATE_NAME: case ')': case ']': case '}': /* XXX: regexp may occur after */ @@ -23075,6 +24770,7 @@ static __exception int js_parse_object_literal(JSParseState *s) #define PF_POW_ALLOWED (1 << 2) /* forbid the exponentiation operator in js_parse_unary() */ #define PF_POW_FORBIDDEN (1 << 3) +#define PF_AWAIT_USING (1 << 4) static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags); @@ -23885,18 +25581,19 @@ static __exception int js_parse_array_literal(JSParseState *s) return js_parse_expect(s, ']'); } -/* XXX: remove */ +/* check if scope chain contains a with statement */ static bool has_with_scope(JSFunctionDef *s, int scope_level) { - /* check if scope chain contains a with statement */ while (s) { - int scope_idx = s->scopes[scope_level].first; - while (scope_idx >= 0) { - JSVarDef *vd = &s->vars[scope_idx]; - - if (vd->var_name == JS_ATOM__with_) - return true; - scope_idx = vd->scope_next; + /* no with in strict mode */ + if (!s->is_strict_mode) { + int scope_idx = s->scopes[scope_level].first; + while (scope_idx >= 0) { + JSVarDef *vd = &s->vars[scope_idx]; + if (vd->var_name == JS_ATOM__with_) + return true; + scope_idx = vd->scope_next; + } } /* check parent scopes */ scope_level = s->parent_scope_level; @@ -23929,7 +25626,11 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, } if (name == JS_ATOM_this || name == JS_ATOM_new_target) goto invalid_lvalue; - depth = 2; /* will generate OP_get_ref_value */ + if (has_with_scope(fd, scope)) { + depth = 2; /* will generate OP_get_ref_value */ + } else { + depth = 0; + } break; case OP_get_field: name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1); @@ -23966,16 +25667,22 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, /* get the value but keep the object/fields on the stack */ switch(opcode) { case OP_scope_get_var: - label = new_label(s); - if (label < 0) - return -1; - emit_op(s, OP_scope_make_ref); - emit_atom(s, name); - emit_u32(s, label); - emit_u16(s, scope); - update_label(fd, label, 1); - emit_op(s, OP_get_ref_value); - opcode = OP_get_ref_value; + if (depth != 0) { + label = new_label(s); + if (label < 0) + return -1; + emit_op(s, OP_scope_make_ref); + emit_atom(s, name); + emit_u32(s, label); + emit_u16(s, scope); + update_label(fd, label, 1); + emit_op(s, OP_get_ref_value); + opcode = OP_get_ref_value; + } else { + emit_op(s, OP_scope_get_var); + emit_atom(s, name); + emit_u16(s, scope); + } break; case OP_get_field: emit_op(s, OP_get_field2); @@ -24003,15 +25710,17 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, } else { switch(opcode) { case OP_scope_get_var: - label = new_label(s); - if (label < 0) - return -1; - emit_op(s, OP_scope_make_ref); - emit_atom(s, name); - emit_u32(s, label); - emit_u16(s, scope); - update_label(fd, label, 1); - opcode = OP_get_ref_value; + if (depth != 0) { + label = new_label(s); + if (label < 0) + return -1; + emit_op(s, OP_scope_make_ref); + emit_atom(s, name); + emit_u32(s, label); + emit_u16(s, scope); + update_label(fd, label, 1); + opcode = OP_get_ref_value; + } break; case OP_get_array_el: emit_op(s, OP_to_propkey2); @@ -24049,6 +25758,21 @@ static void put_lvalue(JSParseState *s, int opcode, int scope, bool is_let) { switch(opcode) { + case OP_scope_get_var: + /* depth = 0 */ + switch(special) { + case PUT_LVALUE_NOKEEP: + case PUT_LVALUE_NOKEEP_DEPTH: + case PUT_LVALUE_KEEP_SECOND: + case PUT_LVALUE_NOKEEP_BOTTOM: + break; + case PUT_LVALUE_KEEP_TOP: + emit_op(s, OP_dup); + break; + default: + abort(); + } + break; case OP_get_field: case OP_scope_get_private_field: /* depth = 1 */ @@ -24120,8 +25844,6 @@ static void put_lvalue(JSParseState *s, int opcode, int scope, switch(opcode) { case OP_scope_get_var: /* val -- */ - assert(special == PUT_LVALUE_NOKEEP || - special == PUT_LVALUE_NOKEEP_DEPTH); emit_op(s, is_let ? OP_scope_put_var_init : OP_scope_put_var); emit_u32(s, name); /* has refcount */ emit_u16(s, scope); @@ -24201,6 +25923,9 @@ static __exception int js_define_var(JSParseState *s, JSAtom name, int tok) case TOK_VAR: var_def_type = JS_VAR_DEF_VAR; break; + case TOK_USING: + var_def_type = JS_VAR_DEF_USING; + break; case TOK_CATCH: var_def_type = JS_VAR_DEF_CATCH; break; @@ -24449,6 +26174,8 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, /* swap ref and lvalue object if any */ if (prop_name == JS_ATOM_NULL) { switch(depth_lvalue) { + case 0: + break; case 1: /* source prop x -> x source prop */ emit_op(s, OP_rot3r); @@ -24462,9 +26189,13 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, emit_op(s, OP_rot5l); emit_op(s, OP_rot5l); break; + default: + abort(); } } else { switch(depth_lvalue) { + case 0: + break; case 1: /* source x -> x source */ emit_op(s, OP_swap); @@ -24477,6 +26208,8 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, /* source x y z -> x y z source */ emit_op(s, OP_rot4l); break; + default: + abort(); } } } @@ -24569,8 +26302,11 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, } else if (s->token.val == '[') { bool has_spread; int enum_depth; + int source_line_num, source_col_num; BlockEnv block_env; + source_line_num = s->token.line_num; + source_col_num = s->token.col_num; if (next_token(s)) return -1; /* the block environment is only needed in generators in case @@ -24666,6 +26402,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, } /* close iterator object: if completed, enum_obj has been replaced by undefined */ + emit_source_loc_at(s, source_line_num, source_col_num); emit_op(s, OP_iterator_close); pop_break_entry(s->cur_func); if (next_token(s)) @@ -24993,6 +26730,23 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) return js_parse_error(s, "invalid use of 'import()'"); if (js_parse_assign_expr(s)) return -1; + if (s->token.val == ',') { + if (next_token(s)) + return -1; + if (s->token.val != ')') { + if (js_parse_assign_expr(s)) + return -1; + /* accept a trailing comma */ + if (s->token.val == ',') { + if (next_token(s)) + return -1; + } + } else { + emit_op(s, OP_undefined); + } + } else { + emit_op(s, OP_undefined); + } if (js_parse_expect(s, ')')) return -1; emit_op(s, OP_import); @@ -25461,6 +27215,9 @@ static __exception int js_parse_delete(JSParseState *s) return 0; } +static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok, + bool export_flag); + /* allowed parse_flags: PF_POW_ALLOWED, PF_POW_FORBIDDEN */ static __exception int js_parse_unary(JSParseState *s, int parse_flags) { @@ -25547,8 +27304,8 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) return -1; if (js_parse_unary(s, PF_POW_FORBIDDEN)) return -1; - s->cur_func->has_await = true; emit_op(s, OP_await); + s->cur_func->has_await = true; parse_flags = 0; break; default: @@ -25904,7 +27661,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) emit_op(s, OP_iterator_next); if (is_async) emit_op(s, OP_await); - emit_op(s, OP_iterator_check_object); + emit_op(s, OP_check_object); emit_op(s, OP_get_field2); emit_atom(s, JS_ATOM_done); label_next = emit_goto(s, OP_if_true, -1); /* end of loop */ @@ -25937,7 +27694,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) label_return1 = emit_goto(s, OP_if_true, -1); if (is_async) emit_op(s, OP_await); - emit_op(s, OP_iterator_check_object); + emit_op(s, OP_check_object); emit_op(s, OP_get_field2); emit_atom(s, JS_ATOM_done); emit_goto(s, OP_if_false, label_yield); @@ -25958,7 +27715,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) label_throw1 = emit_goto(s, OP_if_true, -1); if (is_async) emit_op(s, OP_await); - emit_op(s, OP_iterator_check_object); + emit_op(s, OP_check_object); emit_op(s, OP_get_field2); emit_atom(s, JS_ATOM_done); emit_goto(s, OP_if_false, label_yield); @@ -26087,7 +27844,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) } if (op == '=') { - if (opcode == OP_get_ref_value && name == name0) { + if ((opcode == OP_get_ref_value || opcode == OP_scope_get_var) && name == name0) { set_object_name(s, name); } } else { @@ -26115,11 +27872,14 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) return -1; } - if (opcode == OP_get_ref_value && name == name0) { + if ((opcode == OP_get_ref_value || opcode == OP_scope_get_var) && name == name0) { set_object_name(s, name); } switch(depth_lvalue) { + case 0: + emit_op(s, OP_dup); + break; case 1: emit_op(s, OP_insert2); break; @@ -26202,6 +27962,8 @@ static void push_break_entry(JSFunctionDef *fd, BlockEnv *be, be->scope_level = fd->scope_level; be->has_iterator = false; be->is_regular_stmt = false; + be->has_using = false; + be->using_scope_level = -1; } static void pop_break_entry(JSFunctionDef *fd) @@ -26242,6 +28004,12 @@ static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont) } for(; i < top->drop_count; i++) emit_op(s, OP_drop); + if (top->has_using) { + emit_op(s, OP_using_dispose_init); + emit_op(s, OP_dispose_scope); + emit_u16(s, top->using_scope_level); + emit_op(s, OP_using_dispose_end); + } if (top->label_finally != -1) { /* must push dummy value to keep same stack depth */ emit_op(s, OP_undefined); @@ -26279,7 +28047,8 @@ static void emit_return(JSParseState *s, bool hasval) top = s->cur_func->top_break; while (top != NULL) { - if (top->has_iterator || top->label_finally != -1) { + if (top->has_iterator || top->label_finally != -1 || + top->has_using) { if (!hasval) { emit_op(s, OP_undefined); hasval = true; @@ -26303,7 +28072,7 @@ static void emit_return(JSParseState *s, bool hasval) label_next = emit_goto(s, OP_if_true, -1); emit_op(s, OP_call_method); emit_u16(s, 0); - emit_op(s, OP_iterator_check_object); + emit_op(s, OP_check_object); emit_op(s, OP_await); label_next2 = emit_goto(s, OP_goto, -1); emit_label(s, label_next); @@ -26315,6 +28084,14 @@ static void emit_return(JSParseState *s, bool hasval) emit_op(s, OP_undefined); /* dummy catch offset */ emit_op(s, OP_iterator_close); } + } else if (top->has_using) { + /* Dispose using variables. The return value is on TOS. + stack: ret_val */ + emit_op(s, OP_using_dispose_init); /* initial error_state */ + emit_op(s, OP_dispose_scope); + emit_u16(s, top->using_scope_level); + emit_op(s, OP_using_dispose_end); + /* stack: ret_val */ } else { /* execute the "finally" block */ emit_goto(s, OP_gosub, top->label_finally); @@ -26366,16 +28143,53 @@ static __exception int js_parse_statement(JSParseState *s) static __exception int js_parse_block(JSParseState *s) { + JSFunctionDef *fd = s->cur_func; + if (js_parse_expect(s, '{')) return -1; if (s->token.val != '}') { + BlockEnv using_be; + int has_using_be = 0; + int scope_level; + push_scope(s); + scope_level = fd->scope_level; for(;;) { if (js_parse_statement_or_decl(s, DECL_MASK_ALL)) return -1; + if (!has_using_be && fd->scopes[scope_level].has_using) { + has_using_be = 1; + push_break_entry(fd, &using_be, JS_ATOM_NULL, -1, -1, 1); + using_be.has_using = true; + using_be.using_scope_level = scope_level; + } if (s->token.val == '}') break; } + if (has_using_be) { + int label_catch = fd->scopes[scope_level].using_label_catch; + int label_end = fd->scopes[scope_level].using_label_end; + + pop_break_entry(fd); + + if (js_is_live_code(s)) { + emit_op(s, OP_drop); /* drop catch_offset */ + emit_op(s, OP_using_dispose_init); /* initial error_state: no error */ + emit_op(s, OP_dispose_scope); + emit_u16(s, scope_level); + emit_op(s, OP_using_dispose_end); + emit_goto(s, OP_goto, label_end); + } + + emit_label(s, label_catch); + /* Stack: exception_value (= initial error_state) */ + emit_op(s, OP_dispose_scope); + emit_u16(s, scope_level); + /* Stack: final_error_state (original or SuppressedError) */ + emit_op(s, OP_throw); + + emit_label(s, label_end); + } pop_scope(s); } if (next_token(s)) @@ -26397,14 +28211,29 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok, return js_parse_error_reserved_identifier(s); } name = JS_DupAtom(ctx, s->token.u.ident.atom); - if (name == JS_ATOM_let && (tok == TOK_LET || tok == TOK_CONST)) { + if (name == JS_ATOM_let && + (tok == TOK_LET || tok == TOK_CONST || tok == TOK_USING)) { js_parse_error(s, "'let' is not a valid lexical identifier"); goto var_error; } + int using_method_idx = -1; if (next_token(s)) goto var_error; if (js_define_var(s, name, tok)) goto var_error; + if (tok == TOK_USING) { + /* Allocate a paired hidden local for the cached dispose + method. Must be allocated immediately after the value + var so OP_using_dispose can locate it at value_idx + 1. + */ + using_method_idx = add_scope_var(ctx, fd, + JS_ATOM__using_dispose_, + JS_VAR_USING_METHOD); + if (using_method_idx < 0) + goto var_error; + fd->vars[using_method_idx].is_lexical = 1; + fd->vars[using_method_idx].is_const = 1; + } if (export_flag) { if (!add_export_entry(s, s->cur_func->module, name, name, JS_EXPORT_TYPE_LOCAL)) @@ -26432,17 +28261,54 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok, put_lvalue(s, opcode, scope, name1, label, PUT_LVALUE_NOKEEP, false); } else { + bool init; + + if (tok == TOK_USING) { + bool is_await = (parse_flags & PF_AWAIT_USING) != 0; + + if (!fd->scopes[fd->scope_level].has_using) { + /* First 'using' in this scope: set up labels + for the catch handler and end of disposal */ + fd->scopes[fd->scope_level].has_using = 1; + fd->scopes[fd->scope_level].using_label_catch = + new_label(s); + fd->scopes[fd->scope_level].using_label_end = + new_label(s); + + /* Emit OP_catch: push catch_offset on the value + stack. If an exception occurs, control jumps + to catch_label with the exception value on the + stack instead of catch_offset. */ + emit_goto(s, OP_catch, + fd->scopes[fd->scope_level].using_label_catch); + } + if (is_await) + fd->scopes[fd->scope_level].is_await_using = 1; + } + if (js_parse_assign_expr2(s, parse_flags)) goto var_error; set_object_name(s, name); - emit_op(s, (tok == TOK_CONST || tok == TOK_LET) ? - OP_scope_put_var_init : OP_scope_put_var); + + if (tok == TOK_USING) { + emit_op(s, OP_using_check); + emit_u8(s, (parse_flags & PF_AWAIT_USING) != 0); + /* Stack: value, method. Store the method first. + Emit OP_put_loc directly (bypasses atom lookup) + so multiple using decls with the shared hidden + atom name don't collide. */ + emit_op(s, OP_put_loc); + emit_u16(s, using_method_idx); + } + + init = (tok == TOK_CONST || tok == TOK_LET || tok == TOK_USING); + emit_op(s, init ? OP_scope_put_var_init : OP_scope_put_var); emit_atom(s, name); emit_u16(s, fd->scope_level); } } else { - if (tok == TOK_CONST) { - js_parse_error(s, "missing initializer for const variable"); + if (tok == TOK_CONST || tok == TOK_USING) { + js_parse_error(s, "missing initializer for variable"); goto var_error; } if (tok == TOK_LET) { @@ -26458,6 +28324,10 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok, int skip_bits; if ((s->token.val == '[' || s->token.val == '{') && js_parse_skip_parens_token(s, &skip_bits, false) == '=') { + /* using declarations do not allow binding patterns */ + if (tok == TOK_USING) { + return js_parse_error(s, "binding patterns are not allowed in using declarations"); + } emit_op(s, OP_undefined); if (js_parse_destructuring_element(s, tok, false, true, skip_bits & SKIP_HAS_ELLIPSIS, true, export_flag) < 0) return -1; @@ -26526,10 +28396,38 @@ static int is_let(JSParseState *s, int decl_mask) return res; } +/* Return 1 if the current token is `using` introducing a UsingDeclaration, + 0 if it is a plain identifier usage, or -1 on error. + If `is_for_of` is true, `using of` is specifically treated as identifier + per the for-of lookahead restriction. */ +static int is_using(JSParseState *s, bool is_for_of) +{ + int res = false; + if (token_is_pseudo_keyword(s, JS_ATOM_using)) { + JSParsePos pos; + js_parse_get_pos(s, &pos); + if (next_token(s)) + return -1; + /* No line terminator allowed between `using` and the binding */ + if (s->last_line_num == s->token.line_num) { + if (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved) { + if (!(is_for_of && s->token.u.ident.atom == JS_ATOM_of)) { + res = true; + } + } + } + if (js_parse_seek_token(s, &pos)) + res = -1; + } + return res; +} + /* XXX: handle IteratorClose when exiting the loop before the enumeration is done */ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, - bool is_async) + bool is_async, + int source_line_num, + int source_col_num) { JSContext *ctx = s->ctx; JSFunctionDef *fd = s->cur_func; @@ -26575,7 +28473,27 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, default: return -1; } - if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_CONST) { + bool is_await_using = false; + if (tok == TOK_AWAIT) { + int u; + if (next_token(s)) + return -1; + u = is_using(s, false); + if (u < 0) + return -1; + if (!u) + return js_parse_error(s, "'using' expected"); + tok = TOK_USING; + is_await_using = true; + s->cur_func->has_await = true; + } else if (token_is_pseudo_keyword(s, JS_ATOM_using)) { + int u = is_using(s, true); + if (u < 0) + return -1; + if (u) + tok = TOK_USING; + } + if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_CONST || tok == TOK_USING) { if (next_token(s)) return -1; @@ -26589,7 +28507,13 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, } var_name = JS_ATOM_NULL; } else { + bool init; var_name = JS_DupAtom(ctx, s->token.u.ident.atom); + if (var_name == JS_ATOM_let && + (tok == TOK_LET || tok == TOK_CONST || tok == TOK_USING)) { + JS_FreeAtom(s->ctx, var_name); + return js_parse_error(s, "'let' is not a valid lexical identifier"); + } if (next_token(s)) { JS_FreeAtom(s->ctx, var_name); return -1; @@ -26598,10 +28522,33 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, JS_FreeAtom(s->ctx, var_name); return -1; } - emit_op(s, (tok == TOK_CONST || tok == TOK_LET) ? - OP_scope_put_var_init : OP_scope_put_var); + if (tok == TOK_USING) { + int mi = add_scope_var(ctx, fd, JS_ATOM__using_dispose_, + JS_VAR_USING_METHOD); + if (mi < 0) { + JS_FreeAtom(s->ctx, var_name); + return -1; + } + fd->vars[mi].is_lexical = 1; + fd->vars[mi].is_const = 1; + emit_op(s, OP_using_check); + emit_u8(s, is_await_using); + emit_op(s, OP_put_loc); + emit_u16(s, mi); + } + init = (tok == TOK_CONST || tok == TOK_LET || tok == TOK_USING); + emit_op(s, init ? OP_scope_put_var_init : OP_scope_put_var); emit_atom(s, var_name); emit_u16(s, fd->scope_level); + if (tok == TOK_USING) { + if (!fd->scopes[fd->scope_level].has_using) { + fd->scopes[fd->scope_level].has_using = 1; + fd->scopes[fd->scope_level].using_label_catch = new_label(s); + fd->scopes[fd->scope_level].using_label_end = new_label(s); + } + if (is_await_using) + fd->scopes[fd->scope_level].is_await_using = 1; + } } } else if (!is_async && token_is_pseudo_keyword(s, JS_ATOM_async) && peek_token(s, false) == TOK_OF) { return js_parse_error(s, "'for of' expression cannot start with 'async'"); @@ -26647,13 +28594,13 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, if (token_is_pseudo_keyword(s, JS_ATOM_of)) { is_for_of = true; - break_entry.has_iterator = true; - break_entry.drop_count += 2; if (has_initializer) goto initializer_error; } else if (s->token.val == TOK_IN) { if (is_async) return js_parse_error(s, "'for await' loop should be used with 'of'"); + if (tok == TOK_USING) + return js_parse_error(s, "using declaration not allowed in for-in"); if (has_initializer && (tok != TOK_VAR || fd->is_strict_mode || has_destructuring)) { initializer_error: @@ -26676,6 +28623,11 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, the TDZ values are in the closures */ close_scopes(s, s->cur_func->scope_level, block_scope_level); if (is_for_of) { + /* set has_iterator after the iterable expression is parsed so + that a yield in the expression does not try to close a + not-yet-created iterator */ + break_entry.has_iterator = true; + break_entry.drop_count += 2; if (is_async) emit_op(s, OP_for_await_of_start); else @@ -26696,7 +28648,8 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, int chunk_size = pos_expr - pos_next; int offset = bc->size - pos_next; int i; - dbuf_realloc(bc, bc->size + chunk_size); + if (dbuf_claim(bc, chunk_size)) + return -1; dbuf_put(bc, bc->buf + pos_next, chunk_size); memset(bc->buf + pos_next, OP_nop, chunk_size); /* `next` part ends with a goto */ @@ -26710,8 +28663,46 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, } emit_label(s, label_body); - if (js_parse_statement(s)) - return -1; + { + bool scope_has_using = fd->scopes[fd->scope_level].has_using; + int using_scope_level = fd->scope_level; + BlockEnv using_be; + int had_using_be = 0; + + if (scope_has_using) { + emit_goto(s, OP_catch, fd->scopes[using_scope_level].using_label_catch); + push_break_entry(fd, &using_be, JS_ATOM_NULL, -1, -1, 1); + using_be.has_using = true; + using_be.using_scope_level = using_scope_level; + had_using_be = 1; + } + + if (js_parse_statement(s)) + return -1; + + if (had_using_be) { + pop_break_entry(fd); + } + + if (scope_has_using && js_is_live_code(s)) { + emit_op(s, OP_drop); + emit_op(s, OP_using_dispose_init); + emit_op(s, OP_dispose_scope); + emit_u16(s, using_scope_level); + emit_op(s, OP_using_dispose_end); + emit_goto(s, OP_goto, + fd->scopes[using_scope_level].using_label_end); + } + + if (scope_has_using) { + emit_label(s, fd->scopes[using_scope_level].using_label_catch); + emit_op(s, OP_dispose_scope); + emit_u16(s, using_scope_level); + emit_op(s, OP_throw); + + emit_label(s, fd->scopes[using_scope_level].using_label_end); + } + } close_scopes(s, s->cur_func->scope_level, block_scope_level); @@ -26743,6 +28734,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, emit_label(s, label_break); if (is_for_of) { /* close and drop enum_rec */ + emit_source_loc_at(s, source_line_num, source_col_num); emit_op(s, OP_iterator_close); } else { emit_op(s, OP_drop); @@ -26852,6 +28844,36 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, if (js_parse_expect_semi(s)) goto fail; break; + case TOK_AWAIT: + /* Check for 'await using' declaration */ + if (s->cur_func->func_kind & JS_FUNC_ASYNC) { + JSParsePos pos; + int u; + js_parse_get_pos(s, &pos); + if (next_token(s)) /* skip 'await' */ + goto fail; + u = is_using(s, false); + if (u < 0) + goto fail; + if (u) { + if (!(decl_mask & DECL_MASK_OTHER)) { + js_parse_error(s, "lexical declarations can't appear in single-statement context"); + goto fail; + } + s->cur_func->has_await = true; + if (next_token(s)) /* skip 'using' */ + goto fail; + if (js_parse_var(s, PF_IN_ACCEPTED | PF_AWAIT_USING, TOK_USING, /*export_flag*/false)) + goto fail; + if (js_parse_expect_semi(s)) + goto fail; + break; + } + /* Not 'await using': restore to parse as expression */ + if (js_parse_seek_token(s, &pos)) + goto fail; + } + goto hasexpr; case TOK_LET: case TOK_CONST: haslet: @@ -26975,10 +28997,14 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, { int label_cont, label_break, label_body, label_test; int pos_cont, pos_body, block_scope_level; + int for_scope_level; BlockEnv break_entry; int tok, bits; + int source_line_num, source_col_num; bool is_async; + source_line_num = s->token.line_num; + source_col_num = s->token.col_num; if (next_token(s)) goto fail; @@ -27002,7 +29028,8 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, if (!(bits & SKIP_HAS_SEMI)) { /* parse for/in or for/of */ - if (js_parse_for_in_of(s, label_name, is_async)) + if (js_parse_for_in_of(s, label_name, is_async, + source_line_num, source_col_num)) goto fail; break; } @@ -27011,6 +29038,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, /* create scope for the lexical variables declared in the initial, test and increment expressions */ push_scope(s); + for_scope_level = s->cur_func->scope_level; /* initial expression */ tok = s->token.val; if (tok != ';') { @@ -27023,10 +29051,48 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, default: goto fail; } - if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_CONST) { + if (tok != TOK_VAR && tok != TOK_LET && tok != TOK_CONST && + token_is_pseudo_keyword(s, JS_ATOM_using)) { + int u = is_using(s, false); + if (u < 0) + goto fail; + if (u) + tok = TOK_USING; + } + if (tok == TOK_AWAIT && + (s->cur_func->func_kind & JS_FUNC_ASYNC)) { + /* Check for `await using` declaration head */ + JSParsePos pos; + int u; + js_parse_get_pos(s, &pos); + if (next_token(s)) /* skip 'await' */ + goto fail; + u = is_using(s, false); + if (u < 0) + goto fail; + if (u) { + s->cur_func->has_await = true; + tok = TOK_USING; + if (next_token(s)) /* skip 'using' */ + goto fail; + if (js_parse_var(s, PF_IN_ACCEPTED | PF_AWAIT_USING, + TOK_USING, false)) + goto fail; + goto for_init_done; + } + if (js_parse_seek_token(s, &pos)) + goto fail; + } + if (tok == TOK_VAR + || tok == TOK_LET + || tok == TOK_CONST + || tok == TOK_USING) { + int pf = 0; + if (tok == TOK_USING && is_async) + pf |= PF_AWAIT_USING; if (next_token(s)) goto fail; - if (js_parse_var(s, 0, tok, /*export_flag*/false)) + if (js_parse_var(s, pf, tok, /*export_flag*/false)) goto fail; } else { if (js_parse_expr2(s, false)) @@ -27034,6 +29100,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, emit_op(s, OP_drop); } + for_init_done: /* close the closures before the first iteration */ close_scopes(s, s->cur_func->scope_level, block_scope_level); } @@ -27047,6 +29114,11 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, push_break_entry(s->cur_func, &break_entry, label_name, label_break, label_cont, 0); + if (s->cur_func->scopes[for_scope_level].has_using) { + break_entry.has_using = true; + break_entry.using_scope_level = for_scope_level; + break_entry.drop_count = 1; /* catch_offset from OP_catch */ + } /* test expression */ if (s->token.val == ';') { @@ -27095,7 +29167,8 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, int chunk_size = pos_body - pos_cont; int offset = bc->size - pos_cont; int i; - dbuf_realloc(bc, bc->size + chunk_size); + if (dbuf_claim(bc, chunk_size)) + return -1; dbuf_put(bc, bc->buf + pos_cont, chunk_size); memset(bc->buf + pos_cont, OP_nop, chunk_size); /* increment part ends with a goto */ @@ -27113,6 +29186,27 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, emit_label(s, label_break); pop_break_entry(s->cur_func); + + if (s->cur_func->scopes[for_scope_level].has_using) { + int label_catch = s->cur_func->scopes[for_scope_level].using_label_catch; + int label_end = s->cur_func->scopes[for_scope_level].using_label_end; + + /* Normal exit: drop catch_offset, dispose */ + emit_op(s, OP_drop); + emit_op(s, OP_using_dispose_init); + emit_op(s, OP_dispose_scope); + emit_u16(s, for_scope_level); + emit_op(s, OP_using_dispose_end); + emit_goto(s, OP_goto, label_end); + + /* Catch handler: exception on stack */ + emit_label(s, label_catch); + emit_op(s, OP_dispose_scope); + emit_u16(s, for_scope_level); + emit_op(s, OP_throw); + + emit_label(s, label_end); + } pop_scope(s); } break; @@ -27215,6 +29309,35 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, js_parse_error(s, "invalid switch statement"); goto fail; } + /* `using` / `await using` declarations are not allowed + directly within a CaseClause or DefaultClause + (early error per spec). */ + if (token_is_pseudo_keyword(s, JS_ATOM_using)) { + int u = is_using(s, false); + if (u < 0) + goto fail; + if (u) { + js_parse_error(s, "using declaration is not allowed in this context"); + goto fail; + } + } + if (s->token.val == TOK_AWAIT && + (s->cur_func->func_kind & JS_FUNC_ASYNC)) { + JSParsePos pos; + int u; + js_parse_get_pos(s, &pos); + if (next_token(s)) + goto fail; + u = is_using(s, false); + if (u < 0) + goto fail; + if (js_parse_seek_token(s, &pos)) + goto fail; + if (u) { + js_parse_error(s, "await using declaration is not allowed in this context"); + goto fail; + } + } if (js_parse_statement_or_decl(s, DECL_MASK_ALL)) goto fail; } @@ -27222,7 +29345,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, if (js_parse_expect(s, '}')) goto fail; if (default_label_pos >= 0) { - /* Ugly patch for the the `default` label, shameful and risky */ + /* Ugly patch for the `default` label, shameful and risky */ put_u32(s->cur_func->byte_code.buf + default_label_pos, label_case); s->cur_func->label_slots[label_case].pos = default_label_pos + 4; @@ -27448,6 +29571,33 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, default: goto fail; } + if (token_is_pseudo_keyword(s, JS_ATOM_using)) { + int u = is_using(s, false); + if (u < 0) + goto fail; + if (u) { + JSFunctionDef *fd = s->cur_func; + if (!(decl_mask & DECL_MASK_OTHER)) { + js_parse_error(s, "lexical declarations can't appear in single-statement context"); + goto fail; + } + if (fd->is_eval && + (fd->eval_type == JS_EVAL_TYPE_GLOBAL || + fd->eval_type == JS_EVAL_TYPE_DIRECT || + fd->eval_type == JS_EVAL_TYPE_INDIRECT) && + fd->scope_level == fd->body_scope) { + js_parse_error(s, "using declaration is not allowed at the top level of a script"); + goto fail; + } + if (next_token(s)) + goto fail; + if (js_parse_var(s, PF_IN_ACCEPTED, TOK_USING, /*export_flag*/false)) + goto fail; + if (js_parse_expect_semi(s)) + goto fail; + break; + } + } if (token_is_pseudo_keyword(s, JS_ATOM_async) && peek_token(s, true) == TOK_FUNCTION) { if (!(decl_mask & DECL_MASK_OTHER)) { @@ -27534,6 +29684,7 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name) m->promise = JS_UNDEFINED; m->resolving_funcs[0] = JS_UNDEFINED; m->resolving_funcs[1] = JS_UNDEFINED; + m->private_value = JS_UNDEFINED; list_add_tail(&m->link, &ctx->loaded_modules); return m; } @@ -27543,6 +29694,11 @@ static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m, { int i; + for(i = 0; i < m->req_module_entries_count; i++) { + JSReqModuleEntry *rme = &m->req_module_entries[i]; + JS_MarkValue(rt, rme->attributes, mark_func); + } + for(i = 0; i < m->export_entries_count; i++) { JSExportEntry *me = &m->export_entries[i]; if (me->export_type == JS_EXPORT_TYPE_LOCAL && @@ -27558,6 +29714,7 @@ static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m, JS_MarkValue(rt, m->promise, mark_func); JS_MarkValue(rt, m->resolving_funcs[0], mark_func); JS_MarkValue(rt, m->resolving_funcs[1], mark_func); + JS_MarkValue(rt, m->private_value, mark_func); } static void js_free_module_def(JSContext *ctx, JSModuleDef *m) @@ -27569,6 +29726,7 @@ static void js_free_module_def(JSContext *ctx, JSModuleDef *m) for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; JS_FreeAtom(ctx, rme->module_name); + JS_FreeValue(ctx, rme->attributes); } js_free(ctx, m->req_module_entries); @@ -27597,6 +29755,7 @@ static void js_free_module_def(JSContext *ctx, JSModuleDef *m) JS_FreeValue(ctx, m->promise); JS_FreeValue(ctx, m->resolving_funcs[0]); JS_FreeValue(ctx, m->resolving_funcs[1]); + JS_FreeValue(ctx, m->private_value); list_del(&m->link); js_free(ctx, m); } @@ -27624,6 +29783,7 @@ static int add_req_module_entry(JSContext *ctx, JSModuleDef *m, rme = &m->req_module_entries[m->req_module_entries_count++]; rme->module_name = JS_DupAtom(ctx, module_name); rme->module = NULL; + rme->attributes = JS_UNDEFINED; return i; } @@ -27758,11 +29918,46 @@ void JS_SetModuleLoaderFunc(JSRuntime *rt, JSModuleNormalizeFunc *module_normalize, JSModuleLoaderFunc *module_loader, void *opaque) { - rt->module_normalize_func = module_normalize; - rt->module_loader_func = module_loader; + rt->module_normalize_has_attr = false; + rt->normalize_u.module_normalize_func = module_normalize; + rt->module_loader_has_attr = false; + rt->u.module_loader_func = module_loader; + rt->module_check_attrs = NULL; + rt->module_loader_opaque = opaque; +} + +void JS_SetModuleLoaderFunc2(JSRuntime *rt, + JSModuleNormalizeFunc *module_normalize, + JSModuleLoaderFunc2 *module_loader, + JSModuleCheckSupportedImportAttributes *module_check_attrs, + void *opaque) +{ + rt->module_normalize_has_attr = false; + rt->normalize_u.module_normalize_func = module_normalize; + rt->module_loader_has_attr = true; + rt->u.module_loader_func2 = module_loader; + rt->module_check_attrs = module_check_attrs; rt->module_loader_opaque = opaque; } +void JS_SetModuleNormalizeFunc2(JSRuntime *rt, + JSModuleNormalizeFunc2 *module_normalize) +{ + rt->module_normalize_has_attr = true; + rt->normalize_u.module_normalize_func2 = module_normalize; +} + +int JS_SetModulePrivateValue(JSContext *ctx, JSModuleDef *m, JSValue val) +{ + set_value(ctx, &m->private_value, val); + return 0; +} + +JSValue JS_GetModulePrivateValue(JSContext *ctx, JSModuleDef *m) +{ + return js_dup(m->private_value); +} + /* default module filename normalizer */ static char *js_default_module_normalize_name(JSContext *ctx, const char *base_name, @@ -27778,9 +29973,9 @@ static char *js_default_module_normalize_name(JSContext *ctx, return js_strdup(ctx, name); } - p = strrchr(base_name, '/'); - if (p) - len = p - base_name; + r = strrchr(base_name, '/'); + if (r) + len = r - base_name; else len = 0; @@ -27841,18 +30036,23 @@ static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name) /* `base_cname` and `cname1` may be pure ASCII or UTF-8 encoded */ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, const char *base_cname, - const char *cname1) + const char *cname1, + JSValueConst attributes) { JSRuntime *rt = ctx->rt; JSModuleDef *m; char *cname; JSAtom module_name; - if (!rt->module_normalize_func) { + if (!rt->normalize_u.module_normalize_func && !rt->normalize_u.module_normalize_func2) { cname = js_default_module_normalize_name(ctx, base_cname, cname1); + } else if (rt->module_normalize_has_attr) { + cname = rt->normalize_u.module_normalize_func2(ctx, base_cname, cname1, + attributes, + rt->module_loader_opaque); } else { - cname = rt->module_normalize_func(ctx, base_cname, cname1, - rt->module_loader_opaque); + cname = rt->normalize_u.module_normalize_func(ctx, base_cname, cname1, + rt->module_loader_opaque); } if (!cname) return NULL; @@ -27874,7 +30074,7 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, JS_FreeAtom(ctx, module_name); /* load the module */ - if (!rt->module_loader_func) { + if (!rt->u.module_loader_func) { /* XXX: use a syntax error ? */ // XXX: update JS_DetectModule when you change this JS_ThrowReferenceError(ctx, "could not load module '%s'", @@ -27883,14 +30083,19 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, return NULL; } - m = rt->module_loader_func(ctx, cname, rt->module_loader_opaque); + if (rt->module_loader_has_attr) { + m = rt->u.module_loader_func2(ctx, cname, rt->module_loader_opaque, attributes); + } else { + m = rt->u.module_loader_func(ctx, cname, rt->module_loader_opaque); + } js_free(ctx, cname); return m; } static JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx, - JSAtom base_module_name, - JSAtom module_name1) + JSAtom base_module_name, + JSAtom module_name1, + JSValueConst attributes) { const char *base_cname, *cname; JSModuleDef *m; @@ -27903,7 +30108,7 @@ static JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx, JS_FreeCString(ctx, base_cname); return NULL; } - m = js_host_resolve_imported_module(ctx, base_cname, cname); + m = js_host_resolve_imported_module(ctx, base_cname, cname, attributes); JS_FreeCString(ctx, base_cname); JS_FreeCString(ctx, cname); return m; @@ -28358,7 +30563,8 @@ static int js_resolve_module(JSContext *ctx, JSModuleDef *m) for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; m1 = js_host_resolve_imported_module_atom(ctx, m->module_name, - rme->module_name); + rme->module_name, + rme->attributes); if (!m1) return -1; rme->module = m1; @@ -28420,7 +30626,7 @@ static int js_create_module_bytecode_function(JSContext *ctx, JSModuleDef *m) for(i = 0; i < b->closure_var_count; i++) { JSClosureVar *cv = &b->closure_var[i]; JSVarRef *var_ref; - if (cv->is_local) { + if (cv->closure_type == JS_CLOSURE_MODULE_DECL) { var_ref = js_create_module_var(ctx, cv->is_lexical); if (!var_ref) goto fail; @@ -28828,14 +31034,15 @@ static JSValue js_load_module_fulfilled(JSContext *ctx, JSValueConst this_val, static void JS_LoadModuleInternal(JSContext *ctx, const char *basename, const char *filename, - JSValueConst *resolving_funcs) + JSValueConst *resolving_funcs, + JSValueConst attributes) { JSValue evaluate_promise; JSModuleDef *m; JSValue ret, err, func_obj, evaluate_resolving_funcs[2]; JSValueConst func_data[3]; - m = js_host_resolve_imported_module(ctx, basename, filename); + m = js_host_resolve_imported_module(ctx, basename, filename, attributes); if (!m) goto fail; @@ -28880,7 +31087,7 @@ JSValue JS_LoadModule(JSContext *ctx, const char *basename, promise = JS_NewPromiseCapability(ctx, resolving_funcs); if (JS_IsException(promise)) return JS_EXCEPTION; - JS_LoadModuleInternal(ctx, basename, filename, vc(resolving_funcs)); + JS_LoadModuleInternal(ctx, basename, filename, vc(resolving_funcs), JS_UNDEFINED); JS_FreeValue(ctx, resolving_funcs[0]); JS_FreeValue(ctx, resolving_funcs[1]); return promise; @@ -28892,6 +31099,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx, JSValueConst *resolving_funcs = argv; JSValueConst basename_val = argv[2]; JSValueConst specifier = argv[3]; + JSValueConst attributes = argv[4]; const char *basename = NULL, *filename; JSValue ret, err; @@ -28907,8 +31115,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx, if (!filename) goto exception; - JS_LoadModuleInternal(ctx, basename, filename, - resolving_funcs); + JS_LoadModuleInternal(ctx, basename, filename, resolving_funcs, attributes); JS_FreeCString(ctx, filename); JS_FreeCString(ctx, basename); return JS_UNDEFINED; @@ -28921,11 +31128,14 @@ static JSValue js_dynamic_import_job(JSContext *ctx, return JS_UNDEFINED; } -static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) +static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier, + JSValueConst options) { JSAtom basename; - JSValue promise, resolving_funcs[2], basename_val; - JSValue args[4]; + JSValue promise, resolving_funcs[2], basename_val, err, ret; + JSValue specifier_str = JS_UNDEFINED, attributes = JS_UNDEFINED; + JSValue attributes_obj = JS_UNDEFINED; + JSValue args[5]; basename = JS_GetScriptOrModuleName(ctx, 0); if (basename == JS_ATOM_NULL) @@ -28942,19 +31152,84 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) return promise; } + /* the string conversion must occur here */ + specifier_str = JS_ToString(ctx, specifier); + if (JS_IsException(specifier_str)) + goto exception; + + if (!JS_IsUndefined(options)) { + if (!JS_IsObject(options)) { + JS_ThrowTypeError(ctx, "options must be an object"); + goto exception; + } + attributes_obj = JS_GetProperty(ctx, options, JS_ATOM_with); + if (JS_IsException(attributes_obj)) + goto exception; + if (!JS_IsUndefined(attributes_obj)) { + JSPropertyEnum *atoms; + uint32_t atoms_len, i; + JSValue val; + + if (!JS_IsObject(attributes_obj)) { + JS_ThrowTypeError(ctx, "options.with must be an object"); + goto exception; + } + attributes = JS_NewObjectProto(ctx, JS_NULL); + if (JS_IsException(attributes)) + goto exception; + if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &atoms_len, JS_VALUE_GET_OBJ(attributes_obj), + JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) { + goto exception; + } + for(i = 0; i < atoms_len; i++) { + val = JS_GetProperty(ctx, attributes_obj, atoms[i].atom); + if (JS_IsException(val)) + goto exception1; + if (!JS_IsString(val)) { + JS_FreeValue(ctx, val); + JS_ThrowTypeError(ctx, "module attribute values must be strings"); + goto exception1; + } + if (JS_DefinePropertyValue(ctx, attributes, atoms[i].atom, val, + JS_PROP_C_W_E) < 0) { + exception1: + JS_FreePropertyEnum(ctx, atoms, atoms_len); + goto exception; + } + } + JS_FreePropertyEnum(ctx, atoms, atoms_len); + if (ctx->rt->module_check_attrs && + ctx->rt->module_check_attrs(ctx, ctx->rt->module_loader_opaque, attributes) < 0) { + goto exception; + } + JS_FreeValue(ctx, attributes_obj); + attributes_obj = JS_UNDEFINED; + } + } + args[0] = resolving_funcs[0]; args[1] = resolving_funcs[1]; args[2] = basename_val; - args[3] = unsafe_unconst(specifier); + args[3] = specifier_str; + args[4] = attributes; /* cannot run JS_LoadModuleInternal synchronously because it would cause an unexpected recursion in js_evaluate_module() */ - JS_EnqueueJob(ctx, js_dynamic_import_job, 4, vc(args)); - + JS_EnqueueJob(ctx, js_dynamic_import_job, 5, vc(args)); +done: JS_FreeValue(ctx, basename_val); JS_FreeValue(ctx, resolving_funcs[0]); JS_FreeValue(ctx, resolving_funcs[1]); + JS_FreeValue(ctx, specifier_str); + JS_FreeValue(ctx, attributes); return promise; + exception: + JS_FreeValue(ctx, attributes_obj); + err = JS_GetException(ctx); + ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, vc(&err)); + JS_FreeValue(ctx, ret); + JS_FreeValue(ctx, err); + goto done; } static void js_set_module_evaluated(JSContext *ctx, JSModuleDef *m) @@ -29352,27 +31627,132 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m) #ifndef QJS_DISABLE_PARSER -static __exception JSAtom js_parse_from_clause(JSParseState *s) +/* Parse 'with { key: "value", ... }' clause for import attributes. + rme->attributes is set to JS_UNDEFINED if no 'with' clause or an object + containing the attributes as key/value pairs. If rme->attributes is already + set (from a previous import of the same module), we still parse the tokens + but skip adding to the object since they should be the same. */ +static __exception int js_parse_with_clause(JSParseState *s, JSReqModuleEntry *rme) +{ + JSContext *ctx = s->ctx; + JSAtom key; + int ret; + bool already_set; + + if (s->token.val != TOK_WITH) + return 0; /* no 'with' clause */ + + /* If attributes already set from previous import of same module, + just parse to consume tokens but don't modify the object. */ + already_set = !JS_IsUndefined(rme->attributes); + + if (next_token(s)) + return -1; + if (js_parse_expect(s, '{')) + return -1; + while (s->token.val != '}') { + if (s->token.val == TOK_STRING) { + key = JS_ValueToAtom(ctx, s->token.u.str.str); + if (key == JS_ATOM_NULL) + return -1; + } else { + if (!token_is_ident(s->token.val)) { + js_parse_error(s, "identifier expected"); + return -1; + } + key = JS_DupAtom(ctx, s->token.u.ident.atom); + } + if (next_token(s)) { + JS_FreeAtom(ctx, key); + return -1; + } + if (js_parse_expect(s, ':')) { + JS_FreeAtom(ctx, key); + return -1; + } + if (s->token.val != TOK_STRING) { + js_parse_error(s, "string expected"); + JS_FreeAtom(ctx, key); + return -1; + } + if (!already_set) { + if (JS_IsUndefined(rme->attributes)) { + JSValue attributes = JS_NewObjectProto(ctx, JS_NULL); + if (JS_IsException(attributes)) { + JS_FreeAtom(ctx, key); + return -1; + } + rme->attributes = attributes; + } + /* check for duplicate keys */ + ret = JS_HasProperty(ctx, rme->attributes, key); + if (ret != 0) { + if (ret < 0) { + JS_FreeAtom(ctx, key); + return -1; + } else { + js_parse_error(s, "duplicate with key"); + JS_FreeAtom(ctx, key); + return -1; + } + } + ret = JS_DefinePropertyValue(ctx, rme->attributes, key, + js_dup(s->token.u.str.str), JS_PROP_C_W_E); + if (ret < 0) { + JS_FreeAtom(ctx, key); + return -1; + } + } + JS_FreeAtom(ctx, key); + if (next_token(s)) + return -1; + if (s->token.val != '}') { + if (js_parse_expect(s, ',')) + return -1; + } + } + /* check attributes validity if checker function provided */ + if (!already_set && !JS_IsUndefined(rme->attributes) && + ctx->rt->module_check_attrs && + ctx->rt->module_check_attrs(ctx, ctx->rt->module_loader_opaque, rme->attributes) < 0) { + return -1; + } + return js_parse_expect(s, '}'); +} + +/* return the module index in m->req_module_entries[] or < 0 if error */ +static __exception int js_parse_from_clause(JSParseState *s, JSModuleDef *m) { JSAtom module_name; + int idx; + if (!token_is_pseudo_keyword(s, JS_ATOM_from)) { js_parse_error(s, "from clause expected"); - return JS_ATOM_NULL; + return -1; } if (next_token(s)) - return JS_ATOM_NULL; + return -1; if (s->token.val != TOK_STRING) { js_parse_error(s, "string expected"); - return JS_ATOM_NULL; + return -1; } module_name = JS_ValueToAtom(s->ctx, s->token.u.str.str); if (module_name == JS_ATOM_NULL) - return JS_ATOM_NULL; + return -1; if (next_token(s)) { JS_FreeAtom(s->ctx, module_name); - return JS_ATOM_NULL; + return -1; + } + + idx = add_req_module_entry(s->ctx, m, module_name); + JS_FreeAtom(s->ctx, module_name); + if (idx < 0) + return -1; + if (s->token.val == TOK_WITH) { + if (js_parse_with_clause(s, &m->req_module_entries[idx])) + return -1; } - return module_name; + return idx; } static bool has_unmatched_surrogate(const uint16_t *s, size_t n) @@ -29398,7 +31778,6 @@ static __exception int js_parse_export(JSParseState *s) JSModuleDef *m = s->cur_func->module; JSAtom local_name, export_name; int first_export, idx, i, tok; - JSAtom module_name; JSExportEntry *me; if (next_token(s)) @@ -29482,11 +31861,7 @@ static __exception int js_parse_export(JSParseState *s) if (js_parse_expect(s, '}')) return -1; if (token_is_pseudo_keyword(s, JS_ATOM_from)) { - module_name = js_parse_from_clause(s); - if (module_name == JS_ATOM_NULL) - return -1; - idx = add_req_module_entry(ctx, m, module_name); - JS_FreeAtom(ctx, module_name); + idx = js_parse_from_clause(s, m); if (idx < 0) return -1; for(i = first_export; i < m->export_entries_count; i++) { @@ -29516,11 +31891,7 @@ static __exception int js_parse_export(JSParseState *s) } if (next_token(s)) goto fail1; - module_name = js_parse_from_clause(s); - if (module_name == JS_ATOM_NULL) - goto fail1; - idx = add_req_module_entry(ctx, m, module_name); - JS_FreeAtom(ctx, module_name); + idx = js_parse_from_clause(s, m); if (idx < 0) goto fail1; me = add_export_entry(s, m, JS_ATOM__star_, export_name, @@ -29530,11 +31901,7 @@ static __exception int js_parse_export(JSParseState *s) return -1; me->u.req_module_idx = idx; } else { - module_name = js_parse_from_clause(s); - if (module_name == JS_ATOM_NULL) - return -1; - idx = add_req_module_entry(ctx, m, module_name); - JS_FreeAtom(ctx, module_name); + idx = js_parse_from_clause(s, m); if (idx < 0) return -1; if (add_star_export_entry(ctx, m, idx) < 0) @@ -29576,6 +31943,7 @@ static __exception int js_parse_export(JSParseState *s) case TOK_VAR: case TOK_LET: case TOK_CONST: + case TOK_USING: return js_parse_var(s, PF_IN_ACCEPTED, tok, /*export_flag*/true); default: return js_parse_error(s, "invalid export syntax"); @@ -29584,7 +31952,7 @@ static __exception int js_parse_export(JSParseState *s) } static int add_closure_var(JSContext *ctx, JSFunctionDef *s, - bool is_local, bool is_arg, + JSClosureTypeEnum closure_type, int var_idx, JSAtom var_name, bool is_const, bool is_lexical, JSVarKindEnum var_kind); @@ -29595,7 +31963,7 @@ static int add_import(JSParseState *s, JSModuleDef *m, JSContext *ctx = s->ctx; int i, var_idx; JSImportEntry *mi; - bool is_local; + JSClosureTypeEnum closure_type; if (local_name == JS_ATOM_arguments || local_name == JS_ATOM_eval) return js_parse_error(s, "invalid import binding"); @@ -29607,8 +31975,11 @@ static int add_import(JSParseState *s, JSModuleDef *m, } } - is_local = (import_name == JS_ATOM__star_); - var_idx = add_closure_var(ctx, s->cur_func, is_local, false, + if (import_name == JS_ATOM__star_) + closure_type = JS_CLOSURE_MODULE_DECL; + else + closure_type = JS_CLOSURE_MODULE_IMPORT; + var_idx = add_closure_var(ctx, s->cur_func, closure_type, m->import_entries_count, local_name, true, true, JS_VAR_NORMAL); if (var_idx < 0) @@ -29643,6 +32014,14 @@ static __exception int js_parse_import(JSParseState *s) JS_FreeAtom(ctx, module_name); return -1; } + idx = add_req_module_entry(ctx, m, module_name); + JS_FreeAtom(ctx, module_name); + if (idx < 0) + return -1; + if (s->token.val == TOK_WITH) { + if (js_parse_with_clause(s, &m->req_module_entries[idx])) + return -1; + } } else { if (s->token.val == TOK_IDENT) { if (s->token.u.ident.is_reserved) { @@ -29729,14 +32108,10 @@ static __exception int js_parse_import(JSParseState *s) return -1; } end_import_clause: - module_name = js_parse_from_clause(s); - if (module_name == JS_ATOM_NULL) + idx = js_parse_from_clause(s, m); + if (idx < 0) return -1; } - idx = add_req_module_entry(ctx, m, module_name); - JS_FreeAtom(ctx, module_name); - if (idx < 0) - return -1; for(i = first_import; i < m->import_entries_count; i++) m->import_entries[i].req_module_idx = idx; @@ -29822,6 +32197,10 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx, fd->scope_count = 1; fd->scopes[0].first = -1; fd->scopes[0].parent = -1; + fd->scopes[0].has_using = 0; + fd->scopes[0].is_await_using = 0; + fd->scopes[0].using_label_catch = -1; + fd->scopes[0].using_label_end = -1; fd->scope_level = 0; /* 0: var/arg scope */ fd->scope_first = -1; fd->body_scope = -1; @@ -30368,12 +32747,40 @@ static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionB printf(" closure vars:\n"); for(i = 0; i < b->closure_var_count; i++) { JSClosureVar *cv = &b->closure_var[i]; - printf("%5d: %s %s:%s%d %s\n", i, - JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), cv->var_name), - cv->is_local ? "local" : "parent", - cv->is_arg ? "arg" : "loc", cv->var_idx, + printf("%5d: %s %s", + i, cv->is_const ? "const" : - cv->is_lexical ? "let" : "var"); + cv->is_lexical ? "let" : "var", + JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), cv->var_name)); + switch(cv->closure_type) { + case JS_CLOSURE_LOCAL: + printf(" [loc%d]\n", cv->var_idx); + break; + case JS_CLOSURE_ARG: + printf(" [arg%d]\n", cv->var_idx); + break; + case JS_CLOSURE_REF: + printf(" [ref%d]\n", cv->var_idx); + break; + case JS_CLOSURE_GLOBAL_REF: + printf(" [global_ref%d]\n", cv->var_idx); + break; + case JS_CLOSURE_GLOBAL_DECL: + printf(" [global_decl]\n"); + break; + case JS_CLOSURE_GLOBAL: + printf(" [global]\n"); + break; + case JS_CLOSURE_MODULE_DECL: + printf(" [module_decl]\n"); + break; + case JS_CLOSURE_MODULE_IMPORT: + printf(" [module_import]\n"); + break; + default: + printf(" [?]\n"); + break; + } } } printf(" stack_size: %d\n", b->stack_size); @@ -30399,7 +32806,7 @@ static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionB #ifndef QJS_DISABLE_PARSER static int add_closure_var(JSContext *ctx, JSFunctionDef *s, - bool is_local, bool is_arg, + JSClosureTypeEnum closure_type, int var_idx, JSAtom var_name, bool is_const, bool is_lexical, JSVarKindEnum var_kind) @@ -30419,8 +32826,7 @@ static int add_closure_var(JSContext *ctx, JSFunctionDef *s, &s->closure_var_size, s->closure_var_count + 1)) return -1; cv = &s->closure_var[s->closure_var_count++]; - cv->is_local = is_local; - cv->is_arg = is_arg; + cv->closure_type = closure_type; cv->is_const = is_const; cv->is_lexical = is_lexical; cv->var_kind = var_kind; @@ -30441,46 +32847,34 @@ static int find_closure_var(JSContext *ctx, JSFunctionDef *s, return -1; } -/* 'fd' must be a parent of 's'. Create in 's' a closure referencing a - local variable (is_local = true) or a closure (is_local = false) in - 'fd' */ -static int get_closure_var2(JSContext *ctx, JSFunctionDef *s, - JSFunctionDef *fd, bool is_local, - bool is_arg, int var_idx, JSAtom var_name, - bool is_const, bool is_lexical, - JSVarKindEnum var_kind) +/* 'fd' must be a parent of 's'. Create in 's' a closure referencing + another one in 'fd' */ +static int get_closure_var(JSContext *ctx, JSFunctionDef *s, + JSFunctionDef *fd, JSClosureTypeEnum closure_type, + int var_idx, JSAtom var_name, + bool is_const, bool is_lexical, + JSVarKindEnum var_kind) { int i; if (fd != s->parent) { - var_idx = get_closure_var2(ctx, s->parent, fd, is_local, - is_arg, var_idx, var_name, - is_const, is_lexical, var_kind); + var_idx = get_closure_var(ctx, s->parent, fd, closure_type, + var_idx, var_name, + is_const, is_lexical, var_kind); if (var_idx < 0) return -1; - is_local = false; + if (closure_type != JS_CLOSURE_GLOBAL_REF) + closure_type = JS_CLOSURE_REF; } for(i = 0; i < s->closure_var_count; i++) { JSClosureVar *cv = &s->closure_var[i]; - if (cv->var_idx == var_idx && cv->is_arg == is_arg && - cv->is_local == is_local) + if (cv->var_idx == var_idx && cv->closure_type == closure_type) return i; } - return add_closure_var(ctx, s, is_local, is_arg, var_idx, var_name, + return add_closure_var(ctx, s, closure_type, var_idx, var_name, is_const, is_lexical, var_kind); } -static int get_closure_var(JSContext *ctx, JSFunctionDef *s, - JSFunctionDef *fd, bool is_arg, - int var_idx, JSAtom var_name, - bool is_const, bool is_lexical, - JSVarKindEnum var_kind) -{ - return get_closure_var2(ctx, s, fd, true, is_arg, - var_idx, var_name, is_const, is_lexical, - var_kind); -} - static int get_with_scope_opcode(int op) { if (op == OP_scope_get_var_undef) @@ -30559,19 +32953,10 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s, JSAtom var_name) { int label_pos, end_pos, pos, op; - bool is_strict_mode = s->is_strict_mode; /* replace the reference get/put with normal variable accesses */ - if (is_strict_mode) { - /* need to check if the variable exists before evaluating the right - expression */ - /* XXX: need an extra OP_true if destructuring an array */ - dbuf_putc(bc, OP_check_var); - dbuf_put_u32(bc, JS_DupAtom(ctx, var_name)); - } else { - /* XXX: need 2 extra OP_true if destructuring an array */ - } + /* XXX: need 2 extra OP_true if destructuring an array */ if (bc_buf[pos_next] == OP_get_ref_value) { dbuf_putc(bc, OP_get_var); dbuf_put_u32(bc, JS_DupAtom(ctx, var_name)); @@ -30585,34 +32970,10 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s, assert(bc_buf[pos] == OP_label); end_pos = label_pos + 2; op = bc_buf[label_pos]; - if (is_strict_mode) { - if (op != OP_nop) { - switch(op) { - case OP_insert3: - op = OP_insert2; - break; - case OP_perm4: - op = OP_perm3; - break; - case OP_rot3l: - op = OP_swap; - break; - default: - abort(); - } - bc_buf[pos++] = op; - } - } else { - if (op == OP_insert3) - bc_buf[pos++] = OP_dup; - } - if (is_strict_mode) { - bc_buf[pos] = OP_put_var_strict; - /* XXX: need 1 extra OP_drop if destructuring an array */ - } else { - bc_buf[pos] = OP_put_var; - /* XXX: need 2 extra OP_drop if destructuring an array */ - } + if (op == OP_insert3) + bc_buf[pos++] = OP_dup; + bc_buf[pos] = OP_put_var; + /* XXX: need 2 extra OP_drop if destructuring an array */ put_u32(bc_buf + pos + 1, JS_DupAtom(ctx, var_name)); pos += 5; /* pad with OP_nop */ @@ -30694,6 +33055,14 @@ static void var_object_test(JSContext *ctx, JSFunctionDef *s, s->jump_size++; } +static inline void capture_var(JSFunctionDef *s, JSVarDef *vd) +{ + if (!vd->is_captured) { + vd->is_captured = 1; + vd->var_ref_idx = s->var_ref_count++; + } +} + /* return the position of the next opcode */ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, JSAtom var_name, int scope_level, int op, @@ -30803,23 +33172,33 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, /* Create a dummy object with a named slot that is a reference to the local variable */ if (var_idx & ARGUMENT_VAR_OFFSET) { + capture_var(s, &s->args[var_idx - ARGUMENT_VAR_OFFSET]); dbuf_putc(bc, OP_make_arg_ref); dbuf_put_u32(bc, JS_DupAtom(ctx, var_name)); dbuf_put_u16(bc, var_idx - ARGUMENT_VAR_OFFSET); } else { + capture_var(s, &s->vars[var_idx]); dbuf_putc(bc, OP_make_loc_ref); dbuf_put_u32(bc, JS_DupAtom(ctx, var_name)); dbuf_put_u16(bc, var_idx); } } break; + case OP_scope_put_var: + if (!(var_idx & ARGUMENT_VAR_OFFSET) && + s->vars[var_idx].var_kind == JS_VAR_FUNCTION_NAME) { + /* in non strict mode, modifying the function name is ignored */ + dbuf_putc(bc, OP_drop); + goto done; + } + goto local_scope_var; case OP_scope_get_ref: dbuf_putc(bc, OP_undefined); - /* fall thru */ + goto local_scope_var; case OP_scope_get_var_undef: case OP_scope_get_var: - case OP_scope_put_var: case OP_scope_put_var_init: + local_scope_var: is_put = (op == OP_scope_put_var || op == OP_scope_put_var_init); if (var_idx & ARGUMENT_VAR_OFFSET) { dbuf_putc(bc, OP_get_arg + is_put); @@ -30886,8 +33265,8 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, var_idx = idx; break; } else if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) { - vd->is_captured = 1; - idx = get_closure_var(ctx, s, fd, false, idx, vd->var_name, false, false, JS_VAR_NORMAL); + capture_var(fd, vd); + idx = get_closure_var(ctx, s, fd, JS_CLOSURE_LOCAL, idx, vd->var_name, false, false, JS_VAR_NORMAL); if (idx >= 0) { dbuf_putc(bc, OP_get_var_ref); dbuf_put_u16(bc, idx); @@ -30923,8 +33302,8 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, /* check eval object */ if (!is_arg_scope && fd->var_object_idx >= 0 && !is_pseudo_var) { vd = &fd->vars[fd->var_object_idx]; - vd->is_captured = 1; - idx = get_closure_var(ctx, s, fd, false, + capture_var(fd, vd); + idx = get_closure_var(ctx, s, fd, JS_CLOSURE_LOCAL, fd->var_object_idx, vd->var_name, false, false, JS_VAR_NORMAL); dbuf_putc(bc, OP_get_var_ref); @@ -30935,8 +33314,8 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, /* check eval object in argument scope */ if (fd->arg_var_object_idx >= 0 && !is_pseudo_var) { vd = &fd->vars[fd->arg_var_object_idx]; - vd->is_captured = 1; - idx = get_closure_var(ctx, s, fd, false, + capture_var(fd, vd); + idx = get_closure_var(ctx, s, fd, JS_CLOSURE_LOCAL, fd->arg_var_object_idx, vd->var_name, false, false, JS_VAR_NORMAL); dbuf_putc(bc, OP_get_var_ref); @@ -30958,11 +33337,11 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, JSClosureVar *cv = &fd->closure_var[idx1]; if (var_name == cv->var_name) { if (fd != s) { - idx = get_closure_var2(ctx, s, fd, - false, - cv->is_arg, idx1, - cv->var_name, cv->is_const, - cv->is_lexical, cv->var_kind); + idx = get_closure_var(ctx, s, fd, + JS_CLOSURE_REF, + idx1, + cv->var_name, cv->is_const, + cv->is_lexical, cv->var_kind); } else { idx = idx1; } @@ -30972,11 +33351,11 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, cv->var_name == JS_ATOM__with_) && !is_pseudo_var) { int is_with = (cv->var_name == JS_ATOM__with_); if (fd != s) { - idx = get_closure_var2(ctx, s, fd, - false, - cv->is_arg, idx1, - cv->var_name, false, false, - JS_VAR_NORMAL); + idx = get_closure_var(ctx, s, fd, + JS_CLOSURE_REF, + idx1, + cv->var_name, false, false, + JS_VAR_NORMAL); } else { idx = idx1; } @@ -30990,14 +33369,14 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, if (var_idx >= 0) { /* find the corresponding closure variable */ if (var_idx & ARGUMENT_VAR_OFFSET) { - fd->args[var_idx - ARGUMENT_VAR_OFFSET].is_captured = 1; + capture_var(fd, &fd->args[var_idx - ARGUMENT_VAR_OFFSET]); idx = get_closure_var(ctx, s, fd, - true, var_idx - ARGUMENT_VAR_OFFSET, + JS_CLOSURE_ARG, var_idx - ARGUMENT_VAR_OFFSET, var_name, false, false, JS_VAR_NORMAL); } else { - fd->vars[var_idx].is_captured = 1; + capture_var(fd, &fd->vars[var_idx]); idx = get_closure_var(ctx, s, fd, - false, var_idx, + JS_CLOSURE_LOCAL, var_idx, var_name, fd->vars[var_idx].is_const, fd->vars[var_idx].is_lexical, @@ -31042,15 +33421,22 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, dbuf_put_u16(bc, idx); } break; + case OP_scope_put_var: + if (s->closure_var[idx].var_kind == JS_VAR_FUNCTION_NAME) { + /* in non strict mode, modifying the function name is ignored */ + dbuf_putc(bc, OP_drop); + goto done; + } + goto closure_scope_var; case OP_scope_get_ref: /* XXX: should create a dummy object with a named slot that is a reference to the closure variable */ dbuf_putc(bc, OP_undefined); - /* fall thru */ + goto closure_scope_var; case OP_scope_get_var_undef: case OP_scope_get_var: - case OP_scope_put_var: case OP_scope_put_var_init: + closure_scope_var: is_put = (op == OP_scope_put_var || op == OP_scope_put_var_init); if (is_put) { @@ -31169,7 +33555,8 @@ static int resolve_scope_private_field1(JSContext *ctx, if (idx >= 0) { var_kind = fd->vars[idx].var_kind; if (is_ref) { - idx = get_closure_var(ctx, s, fd, false, idx, var_name, + capture_var(fd, &fd->vars[idx]); + idx = get_closure_var(ctx, s, fd, JS_CLOSURE_LOCAL, idx, var_name, true, true, JS_VAR_NORMAL); if (idx < 0) return -1; @@ -31186,12 +33573,12 @@ static int resolve_scope_private_field1(JSContext *ctx, var_kind = cv->var_kind; is_ref = true; if (fd != s) { - idx = get_closure_var2(ctx, s, fd, - false, - cv->is_arg, idx, - cv->var_name, cv->is_const, - cv->is_lexical, - cv->var_kind); + idx = get_closure_var(ctx, s, fd, + JS_CLOSURE_REF, + idx, + cv->var_name, cv->is_const, + cv->is_lexical, + cv->var_kind); if (idx < 0) return -1; } @@ -31324,7 +33711,7 @@ static void mark_eval_captured_variables(JSContext *ctx, JSFunctionDef *s, for (idx = s->scopes[scope_level].first; idx >= 0;) { vd = &s->vars[idx]; - vd->is_captured = 1; + capture_var(s, vd); idx = vd->scope_next; } } @@ -31388,6 +33775,16 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) before. */ assert(s->is_eval || s->closure_var_count == 0); + /* mark all local variables as captured since eval can access any of them */ + if (!s->is_eval) { + for (i = 0; i < s->arg_count; i++) { + capture_var(s, &s->args[i]); + } + for (i = 0; i < s->var_count; i++) { + capture_var(s, &s->vars[i]); + } + } + /* XXX: inefficient, but eval performance is less critical */ fd = s; for(;;) { @@ -31420,8 +33817,8 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) scope_idx = fd->scopes[scope_level].first; while (scope_idx >= 0) { vd = &fd->vars[scope_idx]; - vd->is_captured = 1; - get_closure_var(ctx, s, fd, false, scope_idx, + capture_var(fd, vd); + get_closure_var(ctx, s, fd, JS_CLOSURE_LOCAL, scope_idx, vd->var_name, vd->is_const, vd->is_lexical, vd->var_kind); scope_idx = vd->scope_next; } @@ -31432,8 +33829,9 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) for(i = 0; i < fd->arg_count; i++) { vd = &fd->args[i]; if (vd->var_name != JS_ATOM_NULL) { + capture_var(fd, vd); get_closure_var(ctx, s, fd, - true, i, vd->var_name, false, + JS_CLOSURE_ARG, i, vd->var_name, false, vd->is_lexical, JS_VAR_NORMAL); } } @@ -31443,8 +33841,9 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) if (vd->scope_level == 0 && vd->var_name != JS_ATOM__ret_ && vd->var_name != JS_ATOM_NULL) { + capture_var(fd, vd); get_closure_var(ctx, s, fd, - false, i, vd->var_name, false, + JS_CLOSURE_LOCAL, i, vd->var_name, false, vd->is_lexical, JS_VAR_NORMAL); } } @@ -31453,8 +33852,9 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) vd = &fd->vars[i]; /* do not close top level last result */ if (vd->scope_level == 0 && is_var_in_arg_scope(vd)) { + capture_var(fd, vd); get_closure_var(ctx, s, fd, - false, i, vd->var_name, false, + JS_CLOSURE_LOCAL, i, vd->var_name, false, vd->is_lexical, JS_VAR_NORMAL); } } @@ -31465,10 +33865,10 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) top level) */ for (idx = 0; idx < fd->closure_var_count; idx++) { JSClosureVar *cv = &fd->closure_var[idx]; - get_closure_var2(ctx, s, fd, - false, cv->is_arg, - idx, cv->var_name, cv->is_const, - cv->is_lexical, cv->var_kind); + get_closure_var(ctx, s, fd, + JS_CLOSURE_REF, + idx, cv->var_name, cv->is_const, + cv->is_lexical, cv->var_kind); } } } @@ -31477,8 +33877,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) static void set_closure_from_var(JSContext *ctx, JSClosureVar *cv, JSVarDef *vd, int var_idx) { - cv->is_local = true; - cv->is_arg = false; + cv->closure_type = JS_CLOSURE_LOCAL; cv->is_const = vd->is_const; cv->is_lexical = vd->is_lexical; cv->var_kind = vd->var_kind; @@ -31519,8 +33918,7 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s, for(i = 0; i < b->arg_count; i++) { JSClosureVar *cv = &s->closure_var[s->closure_var_count++]; vd = &b->vardefs[i]; - cv->is_local = true; - cv->is_arg = true; + cv->closure_type = JS_CLOSURE_ARG; cv->is_const = false; cv->is_lexical = false; cv->var_kind = JS_VAR_NORMAL; @@ -31548,8 +33946,7 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s, for(i = 0; i < b->closure_var_count; i++) { JSClosureVar *cv0 = &b->closure_var[i]; JSClosureVar *cv = &s->closure_var[s->closure_var_count++]; - cv->is_local = false; - cv->is_arg = cv0->is_arg; + cv->closure_type = JS_CLOSURE_REF; cv->is_const = cv0->is_const; cv->is_lexical = cv0->is_lexical; cv->var_kind = cv0->var_kind; @@ -32165,6 +34562,62 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) } break; + case OP_dispose_scope: + { + int scope_idx, scope = get_u16(bc_buf + pos + 1); + bool is_async = s->scopes[scope].is_await_using; + + for(scope_idx = s->scopes[scope].first; scope_idx >= 0;) { + JSVarDef *vd = &s->vars[scope_idx]; + if (vd->scope_level == scope) { + if (vd->var_kind == JS_VAR_USING) { + if (is_async) { + int label_catch = new_label_fd(s); + int label_end = new_label_fd(s); + if (label_catch < 0 || label_end < 0) { + dbuf_set_error(&bc_out); + break; + } + + dbuf_putc(&bc_out, OP_catch); + dbuf_put_u32(&bc_out, label_catch); + update_label(s, label_catch, 1); + s->jump_size++; + + dbuf_putc(&bc_out, OP_using_dispose_async); + dbuf_put_u16(&bc_out, scope_idx); + + dbuf_putc(&bc_out, OP_await); + dbuf_putc(&bc_out, OP_drop); + dbuf_putc(&bc_out, OP_drop); + + dbuf_putc(&bc_out, OP_goto); + dbuf_put_u32(&bc_out, label_end); + update_label(s, label_end, 1); + s->jump_size++; + + dbuf_putc(&bc_out, OP_label); + dbuf_put_u32(&bc_out, label_catch); + s->label_slots[label_catch].pos2 = bc_out.size; + + dbuf_putc(&bc_out, OP_using_dispose_merge); + + dbuf_putc(&bc_out, OP_label); + dbuf_put_u32(&bc_out, label_end); + s->label_slots[label_end].pos2 = bc_out.size; + } else { + dbuf_putc(&bc_out, OP_using_dispose); + dbuf_put_u16(&bc_out, scope_idx); + } + } + scope_idx = vd->scope_next; + } else { + break; + } + } + } + break; + case OP_set_name: { /* remove dummy set_name opcodes */ @@ -32557,6 +35010,10 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) dbuf_putc(&bc_out, OP_special_object); dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_ARGUMENTS); } else { + /* mapped arguments need all args to be captured */ + for (i = 0; i < s->arg_count; i++) { + capture_var(s, &s->args[i]); + } dbuf_putc(&bc_out, OP_special_object); dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS); } @@ -33025,13 +35482,12 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) case OP_insert2: /* Transformation: insert2 put_field(a) drop -> put_field(a) - insert2 put_var_strict(a) drop -> put_var_strict(a) */ - if (code_match(&cc, pos_next, M2(OP_put_field, OP_put_var_strict), OP_drop, -1)) { + if (code_match(&cc, pos_next, OP_put_field, OP_drop, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; if (cc.col_num >= 0) col_num = cc.col_num; add_pc2line_info(s, bc_out.size, line_num, col_num); - dbuf_putc(&bc_out, cc.op); + dbuf_putc(&bc_out, OP_put_field); dbuf_put_u32(&bc_out, cc.atom); pos_next = cc.pos; break; @@ -33215,12 +35671,12 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) put_short_code(&bc_out, op1, idx); break; } - if (code_match(&cc, pos_next, OP_perm3, M2(OP_put_field, OP_put_var_strict), OP_drop, -1)) { + if (code_match(&cc, pos_next, OP_perm3, OP_put_field, OP_drop, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; if (cc.col_num >= 0) col_num = cc.col_num; add_pc2line_info(s, bc_out.size, line_num, col_num); dbuf_putc(&bc_out, OP_dec + (op - OP_post_dec)); - dbuf_putc(&bc_out, cc.op); + dbuf_putc(&bc_out, OP_put_field); dbuf_put_u32(&bc_out, cc.atom); pos_next = cc.pos; break; @@ -33663,7 +36119,7 @@ static int add_module_variables(JSContext *ctx, JSFunctionDef *fd) for(i = 0; i < fd->global_var_count; i++) { hf = &fd->global_vars[i]; - if (add_closure_var(ctx, fd, true, false, i, hf->var_name, hf->is_const, + if (add_closure_var(ctx, fd, JS_CLOSURE_MODULE_DECL, i, hf->var_name, hf->is_const, hf->is_lexical, JS_VAR_NORMAL) < 0) return -1; } @@ -33817,6 +36273,7 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) b->var_count = fd->var_count; b->arg_count = fd->arg_count; b->defined_arg_count = fd->defined_arg_count; + b->var_ref_count = fd->var_ref_count; js_free(ctx, fd->args); js_free(ctx, fd->vars); js_free(ctx, fd->vars_htab); @@ -33971,6 +36428,7 @@ static __exception int js_parse_directives(JSParseState *s) case TOK_IF: case TOK_RETURN: case TOK_VAR: + case TOK_USING: case TOK_THIS: case TOK_DELETE: case TOK_TYPEOF: @@ -34535,25 +36993,59 @@ static __exception int js_parse_function_decl2(JSParseState *s, if (js_parse_function_check_names(s, fd, func_name)) goto fail; - while (s->token.val != '}') { - if (js_parse_source_element(s)) + { + BlockEnv using_be; + int has_using_be = 0; + + while (s->token.val != '}') { + if (js_parse_source_element(s)) + goto fail; + /* Check if a 'using' was encountered in the body scope */ + if (!has_using_be && fd->scopes[fd->body_scope].has_using) { + has_using_be = 1; + push_break_entry(fd, &using_be, JS_ATOM_NULL, -1, -1, 1); + using_be.has_using = true; + using_be.using_scope_level = fd->body_scope; + } + } + + /* save the function source code */ + fd->source_len = s->buf_ptr - ptr; + fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len); + if (!fd->source) goto fail; - } - /* save the function source code */ - fd->source_len = s->buf_ptr - ptr; - fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len); - if (!fd->source) - goto fail; + if (next_token(s)) { + /* consume the '}' */ + goto fail; + } - if (next_token(s)) { - /* consume the '}' */ - goto fail; - } + if (has_using_be) { + int label_catch = fd->scopes[fd->body_scope].using_label_catch; + int label_end = fd->scopes[fd->body_scope].using_label_end; - /* in case there is no return, add one */ - if (js_is_live_code(s)) { - emit_return(s, false); + pop_break_entry(fd); + + if (js_is_live_code(s)) { + emit_op(s, OP_drop); /* drop catch_offset */ + emit_op(s, OP_using_dispose_init); /* initial error_state */ + emit_op(s, OP_dispose_scope); + emit_u16(s, fd->body_scope); + emit_op(s, OP_using_dispose_end); + emit_return(s, false); + } + + emit_label(s, label_catch); + emit_op(s, OP_dispose_scope); + emit_u16(s, fd->body_scope); + emit_op(s, OP_throw); + + emit_label(s, label_end); + } else { + if (js_is_live_code(s)) { + emit_return(s, false); + } + } } done: s->cur_func = fd->parent; @@ -34691,6 +37183,8 @@ static __exception int js_parse_program(JSParseState *s) { JSFunctionDef *fd = s->cur_func; int idx; + BlockEnv using_be; + int has_using_be = 0; if (next_token(s)) return -1; @@ -34712,28 +37206,71 @@ static __exception int js_parse_program(JSParseState *s) while (s->token.val != TOK_EOF) { if (js_parse_source_element(s)) return -1; + /* Check if a 'using' was encountered at the body scope level */ + if (!has_using_be && fd->scopes[fd->body_scope].has_using) { + has_using_be = 1; + push_break_entry(fd, &using_be, JS_ATOM_NULL, -1, -1, 1); + using_be.has_using = true; + using_be.using_scope_level = fd->body_scope; + } } - if (!s->is_module) { - /* return the value of the hidden variable eval_ret_idx */ - if (fd->func_kind == JS_FUNC_ASYNC) { - /* wrap the return value in an object so that promises can - be safely returned */ - emit_op(s, OP_object); - emit_op(s, OP_dup); + if (has_using_be) { + int label_catch = fd->scopes[fd->body_scope].using_label_catch; + int label_end = fd->scopes[fd->body_scope].using_label_end; - emit_op(s, OP_get_loc); - emit_u16(s, fd->eval_ret_idx); + pop_break_entry(fd); - emit_op(s, OP_put_field); - emit_atom(s, JS_ATOM_value); + if (js_is_live_code(s)) { + /* Normal path: drop catch_offset, dispose, then return */ + emit_op(s, OP_drop); /* drop catch_offset */ + emit_op(s, OP_using_dispose_init); /* initial error_state */ + emit_op(s, OP_dispose_scope); + emit_u16(s, fd->body_scope); + emit_op(s, OP_using_dispose_end); + } + + if (!s->is_module) { + if (fd->func_kind == JS_FUNC_ASYNC) { + emit_op(s, OP_object); + emit_op(s, OP_dup); + emit_op(s, OP_get_loc); + emit_u16(s, fd->eval_ret_idx); + emit_op(s, OP_put_field); + emit_atom(s, JS_ATOM_value); + } else { + emit_op(s, OP_get_loc); + emit_u16(s, fd->eval_ret_idx); + } + emit_return(s, true); } else { - emit_op(s, OP_get_loc); - emit_u16(s, fd->eval_ret_idx); + emit_return(s, false); } - emit_return(s, true); + + /* Catch handler */ + emit_label(s, label_catch); + emit_op(s, OP_dispose_scope); + emit_u16(s, fd->body_scope); + emit_op(s, OP_throw); + + emit_label(s, label_end); } else { - emit_return(s, false); + if (!s->is_module) { + if (fd->func_kind == JS_FUNC_ASYNC) { + emit_op(s, OP_object); + emit_op(s, OP_dup); + emit_op(s, OP_get_loc); + emit_u16(s, fd->eval_ret_idx); + emit_op(s, OP_put_field); + emit_atom(s, JS_ATOM_value); + } else { + emit_op(s, OP_get_loc); + emit_u16(s, fd->eval_ret_idx); + } + emit_return(s, true); + } else { + emit_return(s, false); + } } return 0; @@ -35152,7 +37689,7 @@ typedef enum BCTagEnum { BC_TAG_SYMBOL, } BCTagEnum; -#define BC_VERSION 21 +#define BC_VERSION 26 typedef struct BCWriterState { JSContext *ctx; @@ -35218,22 +37755,16 @@ static void bc_put_u8(BCWriterState *s, uint8_t v) static void bc_put_u16(BCWriterState *s, uint16_t v) { - if (is_be()) - v = bswap16(v); dbuf_put_u16(&s->dbuf, v); } static __maybe_unused void bc_put_u32(BCWriterState *s, uint32_t v) { - if (is_be()) - v = bswap32(v); dbuf_put_u32(&s->dbuf, v); } static void bc_put_u64(BCWriterState *s, uint64_t v) { - if (is_be()) - v = bswap64(v); dbuf_put(&s->dbuf, (uint8_t *)&v, sizeof(v)); } @@ -35308,64 +37839,30 @@ static int bc_put_atom(BCWriterState *s, JSAtom atom) return 0; } -static void bc_byte_swap(uint8_t *bc_buf, int bc_len) +static uint32_t bc_csum(const uint8_t *p, size_t n) { - int pos, len, op, fmt; + uint32_t a, b, c, h; + size_t i; - pos = 0; - while (pos < bc_len) { - op = bc_buf[pos]; - len = short_opcode_info(op).size; - fmt = short_opcode_info(op).fmt; - switch(fmt) { - case OP_FMT_u16: - case OP_FMT_i16: - case OP_FMT_label16: - case OP_FMT_npop: - case OP_FMT_loc: - case OP_FMT_arg: - case OP_FMT_var_ref: - put_u16(bc_buf + pos + 1, - bswap16(get_u16(bc_buf + pos + 1))); - break; - case OP_FMT_i32: - case OP_FMT_u32: - case OP_FMT_const: - case OP_FMT_label: - case OP_FMT_atom: - case OP_FMT_atom_u8: - put_u32(bc_buf + pos + 1, - bswap32(get_u32(bc_buf + pos + 1))); - break; - case OP_FMT_atom_u16: - case OP_FMT_label_u16: - put_u32(bc_buf + pos + 1, - bswap32(get_u32(bc_buf + pos + 1))); - put_u16(bc_buf + pos + 1 + 4, - bswap16(get_u16(bc_buf + pos + 1 + 4))); - break; - case OP_FMT_atom_label_u8: - case OP_FMT_atom_label_u16: - put_u32(bc_buf + pos + 1, - bswap32(get_u32(bc_buf + pos + 1))); - put_u32(bc_buf + pos + 1 + 4, - bswap32(get_u32(bc_buf + pos + 1 + 4))); - if (fmt == OP_FMT_atom_label_u16) { - put_u16(bc_buf + pos + 1 + 4 + 4, - bswap16(get_u16(bc_buf + pos + 1 + 4 + 4))); - } - break; - case OP_FMT_npop_u16: - put_u16(bc_buf + pos + 1, - bswap16(get_u16(bc_buf + pos + 1))); - put_u16(bc_buf + pos + 1 + 2, - bswap16(get_u16(bc_buf + pos + 1 + 2))); - break; - default: - break; - } - pos += len; + h = 0; + for (i = 0; i+4 < n; i += 4) { + h += get_u32(p+i); + h *= 0x9e370001; } + a = b = c = 0; + switch (n-i) { + case 3: + c = (uint32_t)p[i+2]; + case 2: + b = (uint32_t)p[i+1]; + case 1: + a = (uint32_t)p[i+0]; + case 0: + break; + } + h += a | b<<8 | c<<16; + h *= 0x9e370001; + return h; } static int JS_WriteFunctionBytecode(BCWriterState *s, @@ -35403,9 +37900,6 @@ static int JS_WriteFunctionBytecode(BCWriterState *s, pos += len; } - if (is_be()) - bc_byte_swap(bc_buf, bc_len); - dbuf_put(&s->dbuf, bc_buf, bc_len); js_free(s->ctx, bc_buf); @@ -35502,6 +37996,7 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj) bc_put_leb128(s, b->var_count); bc_put_leb128(s, b->defined_arg_count); bc_put_leb128(s, b->stack_size); + bc_put_leb128(s, b->var_ref_count); bc_put_leb128(s, b->closure_var_count); bc_put_leb128(s, b->cpool_count); bc_put_leb128(s, b->byte_code_len); @@ -35520,6 +38015,8 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj) bc_set_flags(&flags, &idx, vd->is_captured, 1); assert(idx <= 8); bc_put_u8(s, flags); + if (vd->is_captured) + bc_put_leb128(s, vd->var_ref_idx); } } else { bc_put_leb128(s, 0); @@ -35530,13 +38027,12 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj) bc_put_atom(s, cv->var_name); bc_put_leb128(s, cv->var_idx); flags = idx = 0; - bc_set_flags(&flags, &idx, cv->is_local, 1); - bc_set_flags(&flags, &idx, cv->is_arg, 1); + bc_set_flags(&flags, &idx, cv->closure_type, 3); bc_set_flags(&flags, &idx, cv->is_const, 1); bc_set_flags(&flags, &idx, cv->is_lexical, 1); bc_set_flags(&flags, &idx, cv->var_kind, 4); - assert(idx <= 8); - bc_put_u8(s, flags); + assert(idx <= 16); + bc_put_leb128(s, flags); } // write constant pool before code so code can be disassembled @@ -35675,7 +38171,7 @@ static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj) for(pass = 0; pass < 2; pass++) { if (pass == 1) bc_put_leb128(s, prop_count); - for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { + for(i = 0, pr = sh->prop; i < sh->prop_count; i++, pr++) { atom = pr->atom; if (atom != JS_ATOM_NULL && (pr->flags & JS_PROP_ENUMERABLE)) { if (pr->flags & JS_PROP_TMASK) { @@ -35747,17 +38243,8 @@ static int JS_WriteRegExp(BCWriterState *s, JSRegExp regexp) { JSString *bc = regexp.bytecode; assert(!bc->is_wide_char); - JS_WriteString(s, regexp.pattern); - - if (is_be()) - lre_byte_swap(str8(bc), bc->len, /*is_byte_swapped*/false); - JS_WriteString(s, bc); - - if (is_be()) - lre_byte_swap(str8(bc), bc->len, /*is_byte_swapped*/true); - return 0; } @@ -35803,6 +38290,19 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) JS_WriteString(s, p); } break; + case JS_TAG_STRING_ROPE: + { + JSValue str; + int ret; + str = JS_ToString(s->ctx, obj); + if (JS_IsException(str)) + goto fail; + ret = JS_WriteObjectRec(s, str); + JS_FreeValue(s->ctx, str); + if (ret) + goto fail; + } + break; case JS_TAG_FUNCTION_BYTECODE: if (!s->allow_bytecode) goto invalid_tag; @@ -35927,6 +38427,7 @@ static int JS_WriteObjectAtoms(BCWriterState *s) dbuf1 = s->dbuf; js_dbuf_init(s->ctx, &s->dbuf); bc_put_u8(s, BC_VERSION); + bc_put_u32(s, 0); // checksum, filled in after serialization bc_put_leb128(s, s->idx_to_atom_count); for(i = 0; i < s->idx_to_atom_count; i++) { @@ -35950,7 +38451,7 @@ static int JS_WriteObjectAtoms(BCWriterState *s) /* XXX: could just append dbuf1 data, but it uses more memory if dbuf1 is larger than dbuf */ atoms_size = s->dbuf.size; - if (dbuf_realloc(&dbuf1, dbuf1.size + atoms_size)) + if (dbuf_claim(&dbuf1, atoms_size)) goto fail; memmove(dbuf1.buf + atoms_size, dbuf1.buf, dbuf1.size); memcpy(dbuf1.buf, s->dbuf.buf, atoms_size); @@ -35967,6 +38468,8 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, int flags, JSSABTab *psab_tab) { BCWriterState ss, *s = &ss; + uint32_t h; + DynBuf *d; memset(s, 0, sizeof(*s)); s->ctx = ctx; @@ -35997,7 +38500,11 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, } else { js_free(ctx, s->sab_tab); } - return s->dbuf.buf; + // don't include version and checksum fields in checksum + d = &s->dbuf; + h = bc_csum(&d->buf[5], d->size - 5); + put_u32(&d->buf[1], h); + return d->buf; fail: js_object_list_end(ctx, &s->object_list); js_free(ctx, s->atom_to_idx); @@ -36104,8 +38611,6 @@ static int bc_get_u16(BCReaderState *s, uint16_t *pval) return bc_read_error_end(s); } v = get_u16(s->ptr); - if (is_be()) - v = bswap16(v); *pval = v; s->ptr += 2; return 0; @@ -36119,8 +38624,6 @@ static __maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval) return bc_read_error_end(s); } v = get_u32(s->ptr); - if (is_be()) - v = bswap32(v); *pval = v; s->ptr += 4; return 0; @@ -36134,8 +38637,6 @@ static int bc_get_u64(BCReaderState *s, uint64_t *pval) return bc_read_error_end(s); } v = get_u64(s->ptr); - if (is_be()) - v = bswap64(v); *pval = v; s->ptr += 8; return 0; @@ -36252,15 +38753,8 @@ static JSString *JS_ReadString(BCReaderState *s) } memcpy(str8(p), s->ptr, size); s->ptr += size; - if (is_wide_char) { - if (is_be()) { - uint32_t i; - for (i = 0; i < len; i++) - str16(p)[i] = bswap16(str16(p)[i]); - } - } else { + if (!is_wide_char) str8(p)[size] = '\0'; /* add the trailing zero for 8 bit strings */ - } #ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) { bc_read_trace(s, "%s", ""); // hex dump and indentation @@ -36293,9 +38787,6 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b, return -1; b->byte_code_buf = bc_buf; - if (is_be()) - bc_byte_swap(bc_buf, bc_len); - pos = 0; while (pos < bc_len) { op = bc_buf[pos]; @@ -36442,7 +38933,9 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) goto fail; if (bc_get_leb128_u16(s, &bc.stack_size)) goto fail; - if (bc_get_leb128_int(s, &bc.closure_var_count)) + if (bc_get_leb128_u16(s, &bc.var_ref_count)) + goto fail; + if (bc_get_leb128_u16(s, &bc.closure_var_count)) goto fail; if (bc_get_leb128_int(s, &bc.cpool_count)) goto fail; @@ -36516,6 +39009,10 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) vd->is_const = bc_get_flags(v8, &idx, 1); vd->is_lexical = bc_get_flags(v8, &idx, 1); vd->is_captured = bc_get_flags(v8, &idx, 1); + if (vd->is_captured) { + if (bc_get_leb128_u16(s, &vd->var_ref_idx)) + goto fail; + } #ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) { bc_read_trace(s, "%3d %d%c%c%c %4d ", @@ -36536,26 +39033,23 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) bc_read_trace(s, "off flags idx name\n"); for(i = 0; i < b->closure_var_count; i++) { JSClosureVar *cv = &b->closure_var[i]; - int var_idx; + int var_idx, flags; if (bc_get_atom(s, &cv->var_name)) goto fail; if (bc_get_leb128_int(s, &var_idx)) goto fail; cv->var_idx = var_idx; - if (bc_get_u8(s, &v8)) + if (bc_get_leb128_int(s, &flags)) goto fail; idx = 0; - cv->is_local = bc_get_flags(v8, &idx, 1); - cv->is_arg = bc_get_flags(v8, &idx, 1); - cv->is_const = bc_get_flags(v8, &idx, 1); - cv->is_lexical = bc_get_flags(v8, &idx, 1); - cv->var_kind = bc_get_flags(v8, &idx, 4); + cv->closure_type = bc_get_flags(flags, &idx, 3); + cv->is_const = bc_get_flags(flags, &idx, 1); + cv->is_lexical = bc_get_flags(flags, &idx, 1); + cv->var_kind = bc_get_flags(flags, &idx, 4); #ifdef ENABLE_DUMPS // JS_DUMP_READ_OBJECT if (check_dump_flag(s->ctx->rt, JS_DUMP_READ_OBJECT)) { - bc_read_trace(s, "%3d %d%c%c%c%c %3d ", - i, cv->var_kind, - cv->is_local ? 'L' : '.', - cv->is_arg ? 'A' : '.', + bc_read_trace(s, "%3d %d:%d%c%c %3d ", + i, cv->var_kind, cv->closure_type, cv->is_const ? 'C' : '.', cv->is_lexical ? 'X' : '.', cv->var_idx); @@ -36680,7 +39174,8 @@ static JSValue JS_ReadModule(BCReaderState *s) // because that doesn't work for C modules and is also prone // to loading the same JS module twice. *pm = js_host_resolve_imported_module_atom(s->ctx, m->module_name, - rme->module_name); + rme->module_name, + rme->attributes); if (!*pm) goto fail; } @@ -36995,9 +39490,6 @@ static JSValue JS_ReadRegExp(BCReaderState *s) return JS_ThrowInternalError(ctx, "bad regexp bytecode"); } - if (is_be()) - lre_byte_swap(str8(bc), bc->len, /*is_byte_swapped*/true); - return js_regexp_constructor_internal(ctx, JS_UNDEFINED, JS_MKPTR(JS_TAG_STRING, pattern), JS_MKPTR(JS_TAG_STRING, bc)); @@ -37155,7 +39647,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) if (bc_get_leb128(s, &val)) return JS_EXCEPTION; bc_read_trace(s, "%u\n", val); - if (val >= s->objects_count) { + if (val >= s->objects_count || !s->objects[val]) { return JS_ThrowSyntaxError(ctx, "invalid object reference (%u >= %u)", val, s->objects_count); } @@ -37194,6 +39686,7 @@ static int JS_ReadObjectAtoms(BCReaderState *s) { uint8_t v8, type; JSString *p; + uint32_t h; int i; JSAtom atom; @@ -37204,6 +39697,14 @@ static int JS_ReadObjectAtoms(BCReaderState *s) v8, BC_VERSION); return -1; } + if (bc_get_u32(s, &h)) + return -1; + // allow UINT32_MAX as an escape hatch, otherwise updating + // the test corpus in tests/test_bjson.js gets too tedious + if (h != UINT32_MAX && h != bc_csum(s->ptr, s->buf_end - s->ptr)) { + JS_ThrowSyntaxError(s->ctx, "checksum error"); + return -1; + } if (bc_get_leb128(s, &s->idx_to_atom_count)) return -1; if (s->idx_to_atom_count > 1000*1000) { @@ -37355,7 +39856,7 @@ static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque) { const JSCFunctionListEntry *e = opaque; - JSValue val; + JSValue val, proto; switch(e->def_type) { case JS_DEF_CFUNC: @@ -37366,8 +39867,13 @@ static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p, val = JS_NewAtomString(ctx, e->u.str); break; case JS_DEF_OBJECT: - val = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len); + /* XXX: could add a flag */ + if (atom == JS_ATOM_Symbol_unscopables) + proto = JS_NULL; + else + proto = ctx->class_proto[JS_CLASS_OBJECT]; + val = JS_NewObjectProtoList(ctx, proto, + e->u.prop_list.tab, e->u.prop_list.len); break; default: abort(); @@ -37456,6 +39962,12 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj, case JS_DEF_PROP_UNDEFINED: val = JS_UNDEFINED; break; + case JS_DEF_PROP_SYMBOL: + val = JS_AtomToValue(ctx, e->u.i32); + break; + case JS_DEF_PROP_BOOL: + val = JS_NewBool(ctx, e->u.i32); + break; case JS_DEF_PROP_STRING: case JS_DEF_OBJECT: JS_DefineAutoInitProperty(ctx, obj, atom, JS_AUTOINIT_ID_PROP, @@ -37524,8 +40036,8 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, val = js_float64(e->u.f64); break; case JS_DEF_OBJECT: - val = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len); + val = JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_OBJECT], + e->u.prop_list.tab, e->u.prop_list.len); break; default: abort(); @@ -37537,22 +40049,26 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, } /* Note: 'func_obj' is not necessarily a constructor */ -static void JS_SetConstructor2(JSContext *ctx, - JSValueConst func_obj, - JSValueConst proto, - int proto_flags, int ctor_flags) +static int JS_SetConstructor2(JSContext *ctx, + JSValueConst func_obj, + JSValueConst proto, + int proto_flags, int ctor_flags) { - JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_prototype, - js_dup(proto), proto_flags); - JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor, - js_dup(func_obj), ctor_flags); + if (JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_prototype, + js_dup(proto), proto_flags) < 0) + return -1; + if (JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor, + js_dup(func_obj), ctor_flags) < 0) + return -1; + return 0; } -void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, - JSValueConst proto) +/* return 0 if OK, -1 if exception */ +int JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, + JSValueConst proto) { - JS_SetConstructor2(ctx, func_obj, proto, - 0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + return JS_SetConstructor2(ctx, func_obj, proto, + 0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } static void JS_NewGlobalCConstructor2(JSContext *ctx, @@ -37577,16 +40093,113 @@ static JSValue JS_NewGlobalCConstructor(JSContext *ctx, const char *name, return func_obj; } -static JSValue JS_NewGlobalCConstructorOnly(JSContext *ctx, const char *name, - JSCFunction *func, int length, - JSValue proto) +static JSValue JS_NewGlobalCConstructorMagic(JSContext *ctx, const char *name, + JSCFunctionMagic *func, int length, + JSValueConst proto, int magic) { + /* Used to squelch a -Wcast-function-type warning. */ + JSCFunctionType ft = { .constructor_magic = func }; JSValue func_obj; - func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor, 0); + + func_obj = JS_NewCFunction2(ctx, ft.constructor, name, length, + JS_CFUNC_constructor_or_func_magic, magic); JS_NewGlobalCConstructor2(ctx, func_obj, name, proto); return func_obj; } +static JSValue JS_NewObjectProtoList(JSContext *ctx, JSValueConst proto, + const JSCFunctionListEntry *fields, int n_fields) +{ + JSValue obj; + obj = JS_NewObjectProtoClassAlloc(ctx, proto, JS_CLASS_OBJECT, n_fields); + if (JS_IsException(obj)) + return obj; + if (JS_SetPropertyFunctionList(ctx, obj, fields, n_fields)) { + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; + } + return obj; +} + +#define JS_NEW_CTOR_NO_GLOBAL (1 << 0) /* don't create a global binding */ +#define JS_NEW_CTOR_PROTO_CLASS (1 << 1) /* the prototype class is 'class_id' instead of JS_CLASS_OBJECT */ +#define JS_NEW_CTOR_PROTO_EXIST (1 << 2) /* the prototype is already defined */ +#define JS_NEW_CTOR_READONLY (1 << 3) /* read-only constructor field */ + +/* Return the constructor. Define it as a global variable unless + JS_NEW_CTOR_NO_GLOBAL is set. The new class inherits from + parent_ctor if it is not JS_UNDEFINED. If class_id is >= 0, + class_proto[class_id] is set. */ +static JSValue JS_NewCConstructor(JSContext *ctx, int class_id, const char *name, + JSCFunction *func, int length, JSCFunctionEnum cproto, int magic, + JSValueConst parent_ctor, + const JSCFunctionListEntry *ctor_fields, int n_ctor_fields, + const JSCFunctionListEntry *proto_fields, int n_proto_fields, + int flags) +{ + JSValue ctor = JS_UNDEFINED, proto, parent_proto; + int proto_class_id, proto_flags, ctor_flags; + + proto_flags = 0; + if (flags & JS_NEW_CTOR_READONLY) { + ctor_flags = JS_PROP_CONFIGURABLE; + } else { + ctor_flags = JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE; + } + + if (JS_IsUndefined(parent_ctor)) { + parent_proto = js_dup(ctx->class_proto[JS_CLASS_OBJECT]); + parent_ctor = ctx->function_proto; + } else { + parent_proto = JS_GetProperty(ctx, parent_ctor, JS_ATOM_prototype); + if (JS_IsException(parent_proto)) + return JS_EXCEPTION; + } + + if (flags & JS_NEW_CTOR_PROTO_EXIST) { + proto = js_dup(ctx->class_proto[class_id]); + } else { + if (flags & JS_NEW_CTOR_PROTO_CLASS) + proto_class_id = class_id; + else + proto_class_id = JS_CLASS_OBJECT; + /* one additional field: constructor */ + proto = JS_NewObjectProtoClassAlloc(ctx, parent_proto, proto_class_id, + n_proto_fields + 1); + if (JS_IsException(proto)) + goto fail; + if (class_id >= 0) + ctx->class_proto[class_id] = js_dup(proto); + } + if (JS_SetPropertyFunctionList(ctx, proto, proto_fields, n_proto_fields)) + goto fail; + + /* additional fields: name, length, prototype */ + ctor = JS_NewCFunction3(ctx, func, name, length, cproto, magic, parent_ctor, + n_ctor_fields + 3); + if (JS_IsException(ctor)) + goto fail; + if (JS_SetPropertyFunctionList(ctx, ctor, ctor_fields, n_ctor_fields)) + goto fail; + if (!(flags & JS_NEW_CTOR_NO_GLOBAL)) { + if (JS_DefinePropertyValueStr(ctx, ctx->global_obj, name, + js_dup(ctor), + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0) + goto fail; + } + if (JS_SetConstructor2(ctx, ctor, proto, proto_flags, ctor_flags)) + goto fail; + + JS_FreeValue(ctx, proto); + JS_FreeValue(ctx, parent_proto); + return ctor; + fail: + JS_FreeValue(ctx, proto); + JS_FreeValue(ctx, parent_proto); + JS_FreeValue(ctx, ctor); + return JS_EXCEPTION; +} + static JSValue js_global_eval(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -37654,11 +40267,21 @@ JSValue JS_ToObject(JSContext *ctx, JSValueConst val) obj = JS_NewObjectClass(ctx, JS_CLASS_NUMBER); goto set_value; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: /* XXX: should call the string constructor */ { - JSString *p1 = JS_VALUE_GET_STRING(val); + JSValue str; + str = JS_ToString(ctx, val); /* ensure that we never store a rope */ + if (JS_IsException(str)) + return JS_EXCEPTION; obj = JS_NewObjectClass(ctx, JS_CLASS_STRING); - JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, js_int32(p1->len), 0); + if (!JS_IsException(obj)) { + JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, + JS_NewInt32(ctx, JS_VALUE_GET_STRING(str)->len), 0); + JS_SetObjectData(ctx, obj, js_dup(str)); + } + JS_FreeValue(ctx, str); + return obj; } goto set_value; case JS_TAG_BOOL: @@ -37675,6 +40298,8 @@ JSValue JS_ToObject(JSContext *ctx, JSValueConst val) static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val) { + if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) + return val; JSValue obj = JS_ToObject(ctx, val); JS_FreeValue(ctx, val); return obj; @@ -38026,11 +40651,11 @@ static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst t goto exception1; flags = JS_PROP_C_W_E | JS_PROP_THROW; if (desc.flags & JS_PROP_GETSET) { - if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, js_dup(desc.getter), flags) < 0 - || JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, js_dup(desc.setter), flags) < 0) + if (JS_DefinePropertyValueConst(ctx, ret, JS_ATOM_get, desc.getter, flags) < 0 + || JS_DefinePropertyValueConst(ctx, ret, JS_ATOM_set, desc.setter, flags) < 0) goto exception1; } else { - if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, js_dup(desc.value), flags) < 0 + if (JS_DefinePropertyValueConst(ctx, ret, JS_ATOM_value, desc.value, flags) < 0 || JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable, js_bool(desc.flags & JS_PROP_WRITABLE), flags) < 0) @@ -38132,17 +40757,15 @@ static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1, for(j = i = 0; i < len; i++) { JSAtom atom = atoms[i].atom; if (flags & JS_GPN_ENUM_ONLY) { - JSPropertyDescriptor desc; - int res; + int desc_flags, res; /* Check if property is still enumerable */ - res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom); + res = JS_GetOwnPropertyFlagsInternal(ctx, &desc_flags, p, atom); if (res < 0) goto exception; if (!res) continue; - js_free_desc(ctx, &desc); - if (!(desc.flags & JS_PROP_ENUMERABLE)) + if (!(desc_flags & JS_PROP_ENUMERABLE)) continue; } switch(kind) { @@ -38536,18 +41159,17 @@ static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; for(i = 0; i < len; i++) { - JSPropertyDescriptor desc; + int prop_flags; JSAtom prop = props[i].atom; desc_flags = JS_PROP_THROW | JS_PROP_HAS_CONFIGURABLE; if (freeze_flag) { - res = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); + res = JS_GetOwnPropertyFlagsInternal(ctx, &prop_flags, p, prop); if (res < 0) goto exception; if (res) { - if (desc.flags & JS_PROP_WRITABLE) + if (prop_flags & JS_PROP_WRITABLE) desc_flags |= JS_PROP_HAS_WRITABLE; - js_free_desc(ctx, &desc); } } if (JS_DefineProperty(ctx, obj, prop, JS_UNDEFINED, @@ -38580,16 +41202,15 @@ static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; for(i = 0; i < len; i++) { - JSPropertyDescriptor desc; + int prop_flags; JSAtom prop = props[i].atom; - res = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); + res = JS_GetOwnPropertyFlagsInternal(ctx, &prop_flags, p, prop); if (res < 0) goto exception; if (res) { - js_free_desc(ctx, &desc); - if ((desc.flags & JS_PROP_CONFIGURABLE) - || (is_frozen && (desc.flags & JS_PROP_WRITABLE))) { + if ((prop_flags & JS_PROP_CONFIGURABLE) + || (is_frozen && (prop_flags & JS_PROP_WRITABLE))) { res = false; goto done; } @@ -38796,7 +41417,7 @@ static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValueConst this_ { JSValue obj, res = JS_EXCEPTION; JSAtom prop = JS_ATOM_NULL; - JSPropertyDescriptor desc; + int prop_flags; int has_prop; obj = JS_ToObject(ctx, this_val); @@ -38806,12 +41427,11 @@ static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValueConst this_ if (unlikely(prop == JS_ATOM_NULL)) goto exception; - has_prop = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(obj), prop); + has_prop = JS_GetOwnPropertyFlagsInternal(ctx, &prop_flags, JS_VALUE_GET_OBJ(obj), prop); if (has_prop < 0) goto exception; if (has_prop) { - res = js_bool(desc.flags & JS_PROP_ENUMERABLE); - js_free_desc(ctx, &desc); + res = js_bool(prop_flags & JS_PROP_ENUMERABLE); } else { res = JS_FALSE; } @@ -39332,10 +41952,16 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, JS_FreeValue(ctx, proto); if (JS_IsException(obj)) return obj; - if (magic == JS_AGGREGATE_ERROR) { + switch (magic) { + case JS_AGGREGATE_ERROR: message = argv[1]; opts = 2; - } else { + break; + case JS_SUPPRESSED_ERROR: + message = argv[2]; + opts = 3; + break; + default: message = argv[0]; opts = 1; } @@ -39369,6 +41995,15 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } + if (magic == JS_SUPPRESSED_ERROR) { + JS_DefinePropertyValue(ctx, obj, JS_ATOM_error, + js_dup(argv[0]), + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_DefinePropertyValue(ctx, obj, JS_ATOM_suppressed, + js_dup(argv[1]), + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + } + /* skip the Error() function in the backtrace */ build_backtrace(ctx, obj, JS_UNDEFINED, NULL, 0, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL); return obj; @@ -39487,8 +42122,8 @@ static JSValue js_aggregate_error_constructor(JSContext *ctx, JS_CLASS_ERROR); if (JS_IsException(obj)) return obj; - JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, js_dup(errors), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_DefinePropertyValueConst(ctx, obj, JS_ATOM_errors, errors, + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); return obj; } @@ -39719,8 +42354,8 @@ static JSValue js_array_of(JSContext *ctx, JSValueConst this_val, if (JS_IsException(obj)) return JS_EXCEPTION; for(i = 0; i < argc; i++) { - if (JS_CreateDataPropertyUint32(ctx, obj, i, js_dup(argv[i]), - JS_PROP_THROW) < 0) { + if (JS_CreateDataPropertyUint32Const(ctx, obj, i, argv[i], + JS_PROP_THROW) < 0) { goto fail; } } @@ -39857,11 +42492,6 @@ static JSValue js_array_with(JSContext *ctx, JSValueConst this_val, if (js_get_length64(ctx, &len, obj)) goto exception; - if (len > UINT32_MAX) { - JS_ThrowRangeError(ctx, "invalid array length"); - goto exception; - } - if (JS_ToInt64Sat(ctx, &idx, argv[0])) goto exception; @@ -39873,15 +42503,11 @@ static JSValue js_array_with(JSContext *ctx, JSValueConst this_val, goto exception; } - arr = JS_NewArray(ctx); + arr = js_allocate_fast_array(ctx, len); if (JS_IsException(arr)) goto exception; p = JS_VALUE_GET_OBJ(arr); - if (expand_fast_array(ctx, p, len) < 0) - goto exception; - p->u.array.count = len; - i = 0; pval = p->u.array.u.values; if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) { @@ -39893,21 +42519,14 @@ static JSValue js_array_with(JSContext *ctx, JSValueConst this_val, } else { for (; i < idx; i++, pval++) if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) - goto fill_and_fail; + goto exception; *pval = js_dup(argv[1]); for (i++, pval++; i < len; i++, pval++) { - if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) { - fill_and_fail: - for (; i < len; i++, pval++) - *pval = JS_UNDEFINED; + if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) goto exception; - } } } - if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(len)) < 0) - goto exception; - ret = arr; arr = JS_UNDEFINED; @@ -39965,8 +42584,8 @@ static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val, JS_ThrowTypeError(ctx, "Array loo long"); goto exception; } - if (JS_DefinePropertyValueInt64(ctx, arr, n, js_dup(e), - JS_PROP_C_W_E | JS_PROP_THROW) < 0) + if (JS_DefinePropertyValueInt64Const(ctx, arr, n, e, + JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; n++; } @@ -40140,8 +42759,8 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, case special_filter: case special_filter | special_TA: if (JS_ToBoolFree(ctx, res)) { - if (JS_DefinePropertyValueInt64(ctx, ret, n++, js_dup(val), - JS_PROP_C_W_E | JS_PROP_THROW) < 0) + if (JS_DefinePropertyValueInt64Const(ctx, ret, n++, val, + JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; } break; @@ -40330,7 +42949,7 @@ static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val, } if (js_get_fast_array(ctx, obj, &arrp, &count)) { for (; n < count; n++) { - if (js_strict_eq2(ctx, js_dup(argv[0]), js_dup(arrp[n]), + if (js_strict_eq2(ctx, argv[0], arrp[n], JS_EQ_SAME_VALUE_ZERO)) { goto done; } @@ -40340,10 +42959,11 @@ static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val, val = JS_GetPropertyInt64(ctx, obj, n); if (JS_IsException(val)) goto exception; - if (js_strict_eq2(ctx, js_dup(argv[0]), val, - JS_EQ_SAME_VALUE_ZERO)) { + if (js_strict_eq2(ctx, argv[0], val, JS_EQ_SAME_VALUE_ZERO)) { + JS_FreeValue(ctx, val); goto done; } + JS_FreeValue(ctx, val); } } res = false; @@ -40376,8 +42996,7 @@ static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val, } if (js_get_fast_array(ctx, obj, &arrp, &count)) { for (; n < count; n++) { - if (js_strict_eq2(ctx, js_dup(argv[0]), js_dup(arrp[n]), - JS_EQ_STRICT)) { + if (js_strict_eq2(ctx, argv[0], arrp[n], JS_EQ_STRICT)) { goto done; } } @@ -40387,9 +43006,11 @@ static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val, if (present < 0) goto exception; if (present) { - if (js_strict_eq2(ctx, js_dup(argv[0]), val, JS_EQ_STRICT)) { + if (js_strict_eq2(ctx, argv[0], val, JS_EQ_STRICT)) { + JS_FreeValue(ctx, val); goto done; } + JS_FreeValue(ctx, val); } } } @@ -40423,7 +43044,7 @@ static JSValue js_array_lastIndexOf(JSContext *ctx, JSValueConst this_val, } if (js_get_fast_array(ctx, obj, &arrp, &count) && count == len) { for (; n >= 0; n--) { - if (js_strict_eq2(ctx, js_dup(argv[0]), js_dup(arrp[n]), + if (js_strict_eq2(ctx, argv[0], arrp[n], JS_EQ_STRICT)) { goto done; } @@ -40434,9 +43055,11 @@ static JSValue js_array_lastIndexOf(JSContext *ctx, JSValueConst this_val, if (present < 0) goto exception; if (present) { - if (js_strict_eq2(ctx, js_dup(argv[0]), val, JS_EQ_STRICT)) { + if (js_strict_eq2(ctx, argv[0], val, JS_EQ_STRICT)) { + JS_FreeValue(ctx, val); goto done; } + JS_FreeValue(ctx, val); } } } @@ -40668,6 +43291,35 @@ static JSValue js_array_push(JSContext *ctx, JSValueConst this_val, int i; int64_t len, from, newLen; + /* fast path for push on fast arrays */ + if (likely(JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT && !unshift)) { + JSObject *p = JS_VALUE_GET_OBJ(this_val); + if (likely(p->class_id == JS_CLASS_ARRAY && + p->fast_array && + p->extensible && + p->shape->proto == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_ARRAY]) && + ctx->std_array_prototype)) { + uint32_t array_len, new_len; + if (likely(JS_VALUE_GET_TAG(p->prop[0].u.value) == JS_TAG_INT && + (p->shape->prop->flags & JS_PROP_WRITABLE))) { + array_len = JS_VALUE_GET_INT(p->prop[0].u.value); + new_len = array_len + argc; + if (likely(new_len >= array_len && new_len <= (uint32_t)INT32_MAX)) { /* no overflow and within fast-array bounds */ + if (unlikely(new_len > p->u.array.u1.size)) { + if (expand_fast_array(ctx, p, new_len)) + return JS_EXCEPTION; + } + for(i = 0; i < argc; i++) { + p->u.array.u.values[array_len + i] = js_dup(argv[i]); + } + p->u.array.count = new_len; + p->prop[0].u.value = js_uint32(new_len); + return js_int32(new_len); + } + } + } + } + obj = JS_ToObject(ctx, this_val); if (js_get_length64(ctx, &len, obj)) goto exception; @@ -40784,20 +43436,12 @@ static JSValue js_array_toReversed(JSContext *ctx, JSValueConst this_val, if (js_get_length64(ctx, &len, obj)) goto exception; - if (len > UINT32_MAX) { - JS_ThrowRangeError(ctx, "invalid array length"); - goto exception; - } - - arr = JS_NewArray(ctx); + arr = js_allocate_fast_array(ctx, len); if (JS_IsException(arr)) goto exception; if (len > 0) { p = JS_VALUE_GET_OBJ(arr); - if (expand_fast_array(ctx, p, len) < 0) - goto exception; - p->u.array.count = len; i = len - 1; pval = p->u.array.u.values; @@ -40807,17 +43451,10 @@ static JSValue js_array_toReversed(JSContext *ctx, JSValueConst this_val, } else { // Query order is observable; test262 expects descending order. for (; i >= 0; i--, pval++) { - if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) { - // Exception; initialize remaining elements. - for (; i >= 0; i--, pval++) - *pval = JS_UNDEFINED; + if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) goto exception; - } } } - - if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(len)) < 0) - goto exception; } ret = arr; @@ -40889,7 +43526,7 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val, js_is_fast_array(ctx, arr)) { /* XXX: should share code with fast array constructor */ for (; k < final && k < count32; k++, n++) { - if (JS_CreateDataPropertyUint32(ctx, arr, n, js_dup(arrp[k]), JS_PROP_THROW) < 0) + if (JS_CreateDataPropertyUint32Const(ctx, arr, n, arrp[k], JS_PROP_THROW) < 0) goto exception; } } @@ -40943,8 +43580,6 @@ static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val, int64_t i, j, len, newlen, start, add, del; uint32_t count32; - pval = NULL; - last = NULL; ret = JS_EXCEPTION; arr = JS_UNDEFINED; @@ -40969,17 +43604,12 @@ static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val, add = argc - 2; newlen = len + add - del; - if (newlen > UINT32_MAX) { - // Per spec: TypeError if newlen >= 2**53, RangeError below - if (newlen > MAX_SAFE_INTEGER) { - JS_ThrowTypeError(ctx, "invalid array length"); - } else { - JS_ThrowRangeError(ctx, "invalid array length"); - } + if (newlen > MAX_SAFE_INTEGER) { + JS_ThrowTypeError(ctx, "invalid array length"); goto exception; } - arr = JS_NewArray(ctx); + arr = js_allocate_fast_array(ctx, newlen); if (JS_IsException(arr)) goto exception; @@ -40987,10 +43617,6 @@ static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val, goto done; p = JS_VALUE_GET_OBJ(arr); - if (expand_fast_array(ctx, p, newlen) < 0) - goto exception; - - p->u.array.count = newlen; pval = &p->u.array.u.values[0]; last = &p->u.array.u.values[newlen]; @@ -41014,17 +43640,11 @@ static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val, assert(pval == last); - if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(newlen)) < 0) - goto exception; - done: ret = arr; arr = JS_UNDEFINED; exception: - while (pval != last) - *pval++ = JS_UNDEFINED; - JS_FreeValue(ctx, arr); JS_FreeValue(ctx, obj); return ret; @@ -41357,21 +43977,12 @@ static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val, if (js_get_length64(ctx, &len, obj)) goto exception; - if (len > UINT32_MAX) { - JS_ThrowRangeError(ctx, "invalid array length"); - goto exception; - } - - arr = JS_NewArray(ctx); + arr = js_allocate_fast_array(ctx, len); if (JS_IsException(arr)) goto exception; if (len > 0) { p = JS_VALUE_GET_OBJ(arr); - if (expand_fast_array(ctx, p, len) < 0) - goto exception; - p->u.array.count = len; - i = 0; pval = p->u.array.u.values; if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) { @@ -41379,16 +43990,10 @@ static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val, *pval = js_dup(arrp[i]); } else { for (; i < len; i++, pval++) { - if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) { - for (; i < len; i++, pval++) - *pval = JS_UNDEFINED; + if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) goto exception; - } } } - - if (JS_SetProperty(ctx, arr, JS_ATOM_length, js_int64(len)) < 0) - goto exception; } ret = js_array_sort(ctx, arr, argc, argv); @@ -41434,16 +44039,23 @@ static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val, static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab) { JSValue obj; + JSObject *p; int i; obj = JS_NewArray(ctx); if (JS_IsException(obj)) return JS_EXCEPTION; - for(i = 0; i < len; i++) { - if (JS_CreateDataPropertyUint32(ctx, obj, i, js_dup(tab[i]), 0) < 0) { + if (len > 0) { + p = JS_VALUE_GET_OBJ(obj); + if (expand_fast_array(ctx, p, len) < 0) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; } + p->u.array.count = len; + for(i = 0; i < len; i++) + p->u.array.u.values[i] = js_dup(tab[i]); + /* update the 'length' field */ + set_value(ctx, &p->prop[0].u.value, js_int32(len)); } return obj; } @@ -41634,11 +44246,11 @@ static JSValue js_iterator_constructor(JSContext *ctx, JSValueConst new_target, return js_create_from_ctor(ctx, new_target, JS_CLASS_ITERATOR); } -// note: deliberately doesn't use space-saving bit fields for -// |index|, |count| and |running| because tcc miscompiles them typedef struct JSIteratorConcatData { - int index, count; // elements (not pairs!) in values[] array - bool running; + uint32_t index : 31; // elements (not pairs!) in values[] array + uint32_t unused : 1; + uint32_t count : 31; + uint32_t running : 1; JSValue iter, next, values[]; // array of (object, method) pairs } JSIteratorConcatData; @@ -41649,7 +44261,7 @@ static void js_iterator_concat_finalizer(JSRuntime *rt, JSValueConst val) if (it) { JS_FreeValueRT(rt, it->iter); JS_FreeValueRT(rt, it->next); - for (int i = it->index; i < it->count; i++) + for (uint32_t i = it->index; i < it->count; i++) JS_FreeValueRT(rt, it->values[i]); js_free_rt(rt, it); } @@ -41663,56 +44275,61 @@ static void js_iterator_concat_mark(JSRuntime *rt, JSValueConst val, if (it) { JS_MarkValue(rt, it->iter, mark_func); JS_MarkValue(rt, it->next, mark_func); - for (int i = it->index; i < it->count; i++) + for (uint32_t i = it->index; i < it->count; i++) JS_MarkValue(rt, it->values[i], mark_func); } } static JSValue js_iterator_concat_next(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv, + int *pdone, int magic) { JSValue iter, item, next, val, *obj, *meth; JSIteratorConcatData *it; - JSPropertyDescriptor d; - int done, ret; + int done; it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_CONCAT); if (!it) return JS_EXCEPTION; if (it->running) return JS_ThrowTypeError(ctx, "already running"); + it->running = true; next: - if (it->index >= it->count) - return js_create_iterator_result(ctx, JS_UNDEFINED, /*done*/true); + if (it->index >= it->count) { + *pdone = true; + val = JS_UNDEFINED; + goto done; + } obj = &it->values[it->index + 0]; meth = &it->values[it->index + 1]; iter = it->iter; if (JS_IsUndefined(iter)) { iter = JS_GetIterator2(ctx, *obj, *meth); if (JS_IsException(iter)) - return JS_EXCEPTION; + goto fail; it->iter = iter; } next = it->next; if (JS_IsUndefined(next)) { next = JS_GetProperty(ctx, iter, JS_ATOM_next); if (JS_IsException(next)) - return JS_EXCEPTION; + goto fail; it->next = next; } - it->running = true; item = JS_IteratorNext2(ctx, iter, next, 0, NULL, &done); - it->running = false; if (JS_IsException(item)) - return JS_EXCEPTION; - if (!done) - return js_create_iterator_result(ctx, item, /*done*/false); + goto fail; + if (!done) { + *pdone = false; + val = item; + goto done; + } // done==1 means really done, done==2 means "unknown, inspect object" if (done == 2) { val = JS_GetProperty(ctx, item, JS_ATOM_done); if (JS_IsException(val)) { JS_FreeValue(ctx, item); - return JS_EXCEPTION; + goto fail; } done = JS_ToBoolFree(ctx, val); } @@ -41727,45 +44344,22 @@ static JSValue js_iterator_concat_next(JSContext *ctx, JSValueConst this_val, it->index += 2; goto next; } - // not done, construct { done: false, value: xxx } object - // copy .value verbatim from source object, spec doesn't - // allow dereferencing getters here - d = (JSPropertyDescriptor){ - .value = JS_UNDEFINED, - .getter = JS_UNDEFINED, - .setter = JS_UNDEFINED, - }; - ret = JS_GetOwnProperty(ctx, &d, item, JS_ATOM_value); + val = JS_GetProperty(ctx, item, JS_ATOM_value); JS_FreeValue(ctx, item); - if (ret < 0) - return JS_EXCEPTION; - if (d.flags & JS_PROP_GETSET) { - d.flags |= JS_PROP_HAS_GET | JS_PROP_HAS_SET; - } else { - d.flags |= JS_PROP_HAS_VALUE; - } - item = JS_NewObject(ctx); - if (JS_IsException(item)) - goto fail; - if (JS_DefinePropertyValue(ctx, item, JS_ATOM_done, JS_FALSE, - JS_PROP_C_W_E) < 0) { - goto fail; - } - if (JS_DefineProperty(ctx, item, JS_ATOM_value, d.value, d.getter, - d.setter, d.flags | JS_PROP_C_W_E) < 0) { - fail: - JS_FreeValue(ctx, item); - item = JS_EXCEPTION; - } - js_free_desc(ctx, &d); - return item; + *pdone = false; +done: + it->running = false; + return val; +fail: + val = JS_EXCEPTION; + goto done; } static JSValue js_iterator_concat_return(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSIteratorConcatData *it; - JSValue ret; + JSValue ret, *pval; it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_CONCAT); if (!it) @@ -41781,8 +44375,11 @@ static JSValue js_iterator_concat_return(JSContext *ctx, JSValueConst this_val, ret = JS_CallFree(ctx, ret, it->iter, 0, NULL); it->running = false; } - while (it->index < it->count) - JS_FreeValue(ctx, it->values[it->index++]); + while (it->index < it->count) { + pval = &it->values[it->index++]; + JS_FreeValue(ctx, *pval); + *pval = JS_UNDEFINED; + } JS_FreeValue(ctx, it->iter); JS_FreeValue(ctx, it->next); it->iter = JS_UNDEFINED; @@ -41790,13 +44387,8 @@ static JSValue js_iterator_concat_return(JSContext *ctx, JSValueConst this_val, return ret; } -// note: |next| and |return| don't use JS_ITERATOR_NEXT_DEF because |next| -// has to return a full { value: xxx, done: xxx } step object - it must -// copy getters and setters from the inner iterator's step object -// slightly inefficient because of the intermediate step object that is -// created but that can't be helped right now static const JSCFunctionListEntry js_iterator_concat_proto_funcs[] = { - JS_CFUNC_DEF("next", 1, js_iterator_concat_next ), + JS_ITERATOR_NEXT_DEF("next", 1, js_iterator_concat_next, 0 ), JS_CFUNC_DEF("return", 1, js_iterator_concat_return ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Iterator Concat", JS_PROP_CONFIGURABLE ), }; @@ -41838,7 +44430,7 @@ static JSValue js_iterator_concat(JSContext *ctx, JSValueConst this_val, JS_SetOpaqueInternal(obj, it); return obj; fail: - for (int i = 0; i < it->count; i++) + for (uint32_t i = 0; i < it->count; i++) JS_FreeValue(ctx, it->values[i]); js_free(ctx, it); return JS_EXCEPTION; @@ -42259,6 +44851,66 @@ static JSValue js_iterator_proto_toArray(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } +static JSValue js_async_dispose_to_undef(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, + int magic, JSValueConst *func_data); + +static JSValue js_iterator_proto_dispose(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValue method; + + method = JS_GetProperty(ctx, this_val, JS_ATOM_return); + if (JS_IsException(method)) + return JS_EXCEPTION; + if (JS_IsUndefined(method)) + return JS_UNDEFINED; + return JS_CallFree(ctx, method, this_val, 0, NULL); +} + +static JSValue js_async_iterator_proto_dispose(JSContext *ctx, + JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValue method, ret, promise, undef_fn, then_args[1], result; + JSValue undef = JS_UNDEFINED; + + method = JS_GetProperty(ctx, this_val, JS_ATOM_return); + if (JS_IsException(method)) { + JSValue exc = JS_GetException(ctx); + JSValue p = js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&exc), 1); + JS_FreeValue(ctx, exc); + return p; + } + if (JS_IsUndefined(method)) { + return js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&undef), 0); + } + ret = JS_Call(ctx, method, this_val, 0, NULL); + JS_FreeValue(ctx, method); + if (JS_IsException(ret)) { + JSValue exc = JS_GetException(ctx); + JSValue p = js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&exc), 1); + JS_FreeValue(ctx, exc); + return p; + } + /* Wrap in Promise.resolve(ret).then(() => undefined) */ + promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&ret), 0); + JS_FreeValue(ctx, ret); + if (JS_IsException(promise)) + return promise; + undef_fn = JS_NewCFunctionData(ctx, js_async_dispose_to_undef, 0, 0, 0, + NULL); + if (JS_IsException(undef_fn)) { + JS_FreeValue(ctx, promise); + return JS_EXCEPTION; + } + then_args[0] = undef_fn; + result = JS_Invoke(ctx, promise, JS_ATOM_then, 1, vc(then_args)); + JS_FreeValue(ctx, undef_fn); + JS_FreeValue(ctx, promise); + return result; +} + static JSValue js_iterator_proto_iterator(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -42285,7 +44937,7 @@ static JSValue js_iterator_proto_set_toStringTag(JSContext *ctx, JSValueConst th if (JS_SetProperty(ctx, this_val, JS_ATOM_Symbol_toStringTag, js_dup(val)) < 0) return JS_EXCEPTION; } else { - if (JS_DefinePropertyValue(ctx, this_val, JS_ATOM_Symbol_toStringTag, js_dup(val), JS_PROP_C_W_E) < 0) + if (JS_DefinePropertyValueConst(ctx, this_val, JS_ATOM_Symbol_toStringTag, val, JS_PROP_C_W_E) < 0) return JS_EXCEPTION; } return JS_UNDEFINED; @@ -42521,6 +45173,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, args[1] = index_val; ret = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args); JS_FreeValue(ctx, index_val); + JS_FreeValue(ctx, item); if (JS_IsException(ret)) goto fail; goto done; @@ -42586,6 +45239,7 @@ static const JSCFunctionListEntry js_iterator_proto_funcs[] = { JS_CFUNC_MAGIC_DEF("some", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_SOME ), JS_CFUNC_DEF("reduce", 1, js_iterator_proto_reduce ), JS_CFUNC_DEF("toArray", 0, js_iterator_proto_toArray ), + JS_CFUNC_DEF("[Symbol.dispose]", 0, js_iterator_proto_dispose ), JS_CFUNC_DEF("[Symbol.iterator]", 0, js_iterator_proto_iterator ), JS_CGETSET_DEF("[Symbol.toStringTag]", js_iterator_proto_get_toStringTag, js_iterator_proto_set_toStringTag), }; @@ -42596,6 +45250,25 @@ static const JSCFunctionListEntry js_iterator_helper_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Iterator Helper", JS_PROP_CONFIGURABLE ), }; +static const JSCFunctionListEntry js_array_unscopables_funcs[] = { + JS_PROP_BOOL_DEF("at", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("copyWithin", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("entries", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("fill", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("find", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("findIndex", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("findLast", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("findLastIndex", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("flat", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("flatMap", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("includes", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("keys", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("toReversed", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("toSorted", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("toSpliced", 1, JS_PROP_C_W_E), + JS_PROP_BOOL_DEF("values", 1, JS_PROP_C_W_E), +}; + static const JSCFunctionListEntry js_array_proto_funcs[] = { JS_CFUNC_DEF("at", 1, js_array_at ), JS_CFUNC_DEF("with", 2, js_array_with ), @@ -42636,6 +45309,7 @@ static const JSCFunctionListEntry js_array_proto_funcs[] = { JS_ALIAS_DEF("[Symbol.iterator]", "values" ), JS_CFUNC_MAGIC_DEF("keys", 0, js_create_array_iterator, JS_ITERATOR_KIND_KEY ), JS_CFUNC_MAGIC_DEF("entries", 0, js_create_array_iterator, JS_ITERATOR_KIND_KEY_AND_VALUE ), + JS_OBJECT_DEF("[Symbol.unscopables]", js_array_unscopables_funcs, countof(js_array_unscopables_funcs), JS_PROP_CONFIGURABLE ), }; static const JSCFunctionListEntry js_array_iterator_proto_funcs[] = { @@ -42732,12 +45406,14 @@ static const JSCFunctionListEntry js_number_funcs[] = { JS_CFUNC_DEF("isSafeInteger", 1, js_number_isSafeInteger ), JS_PROP_DOUBLE_DEF("MAX_VALUE", 1.7976931348623157e+308, 0 ), JS_PROP_DOUBLE_DEF("MIN_VALUE", 5e-324, 0 ), - JS_PROP_U2D_DEF("NaN", 0x7FF8ull<<48, 0 ), // workaround for msvc - JS_PROP_DOUBLE_DEF("NEGATIVE_INFINITY", -INFINITY, 0 ), - JS_PROP_DOUBLE_DEF("POSITIVE_INFINITY", INFINITY, 0 ), JS_PROP_DOUBLE_DEF("EPSILON", 2.220446049250313e-16, 0 ), /* ES6 */ JS_PROP_DOUBLE_DEF("MAX_SAFE_INTEGER", 9007199254740991.0, 0 ), /* ES6 */ JS_PROP_DOUBLE_DEF("MIN_SAFE_INTEGER", -9007199254740991.0, 0 ), /* ES6 */ + // workarounds for msvc & djgpp where NAN and INFINITY + // are not compile-time expressions + JS_PROP_U2D_DEF("NaN", 0x7FF8ull<<48, 0 ), + JS_PROP_U2D_DEF("NEGATIVE_INFINITY", 0xFFF0ull<<48, 0 ), + JS_PROP_U2D_DEF("POSITIVE_INFINITY", 0x7FF0ull<<48, 0 ), }; static JSValue js_thisNumberValue(JSContext *ctx, JSValueConst this_val) @@ -43112,7 +45788,7 @@ static JSValue js_string_constructor(JSContext *ctx, JSValueConst new_target, static JSValue js_thisStringValue(JSContext *ctx, JSValueConst this_val) { - if (JS_VALUE_GET_TAG(this_val) == JS_TAG_STRING) + if (tag_is_string(JS_VALUE_GET_TAG(this_val))) return js_dup(this_val); if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) { @@ -43370,12 +46046,48 @@ static JSValue js_string_codePointAt(JSContext *ctx, JSValueConst this_val, static JSValue js_string_concat(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { + int i, is_wide_char; + JSString *p, *q; + int64_t len; + uint32_t n; JSValue r; - int i; + char *d; - /* XXX: Use more efficient method */ - /* XXX: This method is OK if r has a single refcount */ - /* XXX: should use string_buffer? */ + if (JS_TAG_STRING != JS_VALUE_GET_TAG(this_val)) + goto slow_path; + p = JS_VALUE_GET_STRING(this_val); + len = p->len; + is_wide_char = p->is_wide_char; + for (i = 0; i < argc; i++) { + if (JS_TAG_STRING != JS_VALUE_GET_TAG(argv[i])) + goto slow_path; + p = JS_VALUE_GET_STRING(argv[i]); + if (p->is_wide_char ^ is_wide_char) + goto slow_path; + len += p->len; + } + if (len > INT_MAX>>is_wide_char) + return JS_ThrowOutOfMemory(ctx); + p = JS_VALUE_GET_STRING(this_val); + if (p->len == len) + return js_dup(this_val); + q = js_alloc_string(ctx, len, is_wide_char); + if (!q) + return JS_EXCEPTION; + d = strv(q); + n = p->len << is_wide_char; + memcpy(d, strv(p), n); + d += n; + for (i = 0; i < argc; i++) { + p = JS_VALUE_GET_STRING(argv[i]); + n = p->len << is_wide_char; + memcpy(d, strv(p), n); + d += n; + } + if (!is_wide_char) + *d = '\0'; + return JS_MKPTR(JS_TAG_STRING, q); +slow_path: r = JS_ToStringCheckObject(ctx, this_val); for (i = 0; i < argc; i++) { if (JS_IsException(r)) @@ -44723,7 +47435,7 @@ static double js_fmin(double a, double b) a1.u64 |= b1.u64; return a1.d; } else { - return fmin(a, b); + return a < b ? a : b; } } @@ -44737,7 +47449,7 @@ static double js_fmax(double a, double b) a1.u64 &= b1.u64; return a1.d; } else { - return fmax(a, b); + return a < b ? b : a; } } @@ -44750,7 +47462,7 @@ static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val, uint32_t tag; if (unlikely(argc == 0)) { - return js_float64(is_max ? NEG_INF : INF); + return js_float64(is_max ? -INFINITY : INFINITY); } tag = JS_VALUE_GET_TAG(argv[0]); @@ -45397,8 +48109,15 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, return JS_EXCEPTION; } - ret = js_new_string8_len(ctx, (char *)re_bytecode_buf, re_bytecode_len); - js_free(ctx, re_bytecode_buf); + ret = js_new_string8_len(ctx, (void *)&re_bytecode_buf, + sizeof(re_bytecode_buf)); + if (JS_IsException(ret)) { + js_free(ctx, re_bytecode_buf); + } else { + JSString *p = JS_VALUE_GET_STRING(ret); + p->kind = JS_STRING_KIND_INDIRECT; + p->len = re_bytecode_len; + } return ret; } @@ -45410,27 +48129,36 @@ static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor, JSValue obj; JSObject *p; JSRegExp *re; + JSProperty prop; /* sanity check */ if (JS_VALUE_GET_TAG(bc) != JS_TAG_STRING || JS_VALUE_GET_TAG(pattern) != JS_TAG_STRING) { JS_ThrowTypeError(ctx, "string expected"); - fail: - JS_FreeValue(ctx, bc); - JS_FreeValue(ctx, pattern); - return JS_EXCEPTION; - } - - obj = js_create_from_ctor(ctx, ctor, JS_CLASS_REGEXP); - if (JS_IsException(obj)) goto fail; + } + prop.u.value = js_int32(0); // lastIndex + if (ctx->regexp_shape && JS_IsUndefined(ctor)) { + obj = JS_NewObjectFromShape(ctx, js_dup_shape(ctx->regexp_shape), + JS_CLASS_REGEXP, &prop); + if (JS_IsException(obj)) + goto fail; + } else { + obj = js_create_from_ctor(ctx, ctor, JS_CLASS_REGEXP); + if (JS_IsException(obj)) + goto fail; + JS_DefinePropertyValue(ctx, obj, JS_ATOM_lastIndex, prop.u.value, + JS_PROP_WRITABLE); + } p = JS_VALUE_GET_OBJ(obj); re = &p->u.regexp; re->pattern = JS_VALUE_GET_STRING(pattern); re->bytecode = JS_VALUE_GET_STRING(bc); - JS_DefinePropertyValue(ctx, obj, JS_ATOM_lastIndex, js_int32(0), - JS_PROP_WRITABLE); return obj; +fail: + JS_FreeValue(ctx, bc); + JS_FreeValue(ctx, pattern); + return JS_EXCEPTION; } static JSRegExp *js_get_regexp(JSContext *ctx, JSValueConst obj, @@ -45822,15 +48550,16 @@ static JSValue js_regexp_escape(JSContext *ctx, JSValueConst this_val, static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { + int rc, capture_count, shift, index, i, re_flags, prop_flags; JSRegExp *re = js_get_regexp(ctx, this_val, true); JSString *str; JSValue t, ret, str_val, obj, val, groups; JSValue indices, indices_groups; uint8_t *re_bytecode; uint8_t **capture, *str_buf; - int rc, capture_count, shift, i, re_flags; int64_t last_index; const char *group_name_ptr; + JSProperty props[4]; // length, index, input, groups, in that order if (!re) return JS_EXCEPTION; @@ -45879,24 +48608,27 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, goto fail; } } else { - if (rc == LRE_RET_TIMEOUT) { + switch(rc) { + case LRE_RET_TIMEOUT: JS_ThrowInterrupted(ctx); - } else { + break; + case LRE_RET_MEMORY_ERROR: JS_ThrowInternalError(ctx, "out of memory in regexp execution"); + break; + case LRE_RET_BYTECODE_ERROR: + JS_ThrowInternalError(ctx, "corrupted bytecode in regexp execution"); + break; + default: + abort(); } goto fail; } } else { - int prop_flags; if (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) { if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex, js_int32((capture[1] - str_buf) >> shift)) < 0) goto fail; } - obj = JS_NewArray(ctx); - if (JS_IsException(obj)) - goto fail; - prop_flags = JS_PROP_C_W_E | JS_PROP_THROW; group_name_ptr = lre_get_groupnames(re_bytecode); if (group_name_ptr) { groups = JS_NewObjectProto(ctx, JS_NULL); @@ -45913,7 +48645,17 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, goto fail; } } - + index = (capture[0] - str_buf) >> shift; + props[0].u.value = js_int32(capture_count); // length + props[1].u.value = js_int32(index); // index + props[2].u.value = str_val; // input + props[3].u.value = js_dup(groups); // groups + str_val = JS_UNDEFINED; + obj = JS_NewObjectFromShape(ctx, js_dup_shape(ctx->regexp_result_shape), + JS_CLASS_ARRAY, props); + if (JS_IsException(obj)) + goto fail; + prop_flags = JS_PROP_C_W_E | JS_PROP_THROW; for(i = 0; i < capture_count; i++) { const char *name = NULL; uint8_t **match = &capture[2 * i]; @@ -45983,20 +48725,6 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, goto fail; } - t = groups, groups = JS_UNDEFINED; - if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_groups, - t, prop_flags) < 0) { - goto fail; - } - - t = js_int32((capture[0] - str_buf) >> shift); - if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_index, t, prop_flags) < 0) - goto fail; - - t = str_val, str_val = JS_UNDEFINED; - if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_input, t, prop_flags) < 0) - goto fail; - if (!JS_IsUndefined(indices)) { t = indices_groups, indices_groups = JS_UNDEFINED; if (JS_DefinePropertyValue(ctx, indices, JS_ATOM_groups, @@ -46078,10 +48806,18 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValue ar goto fail; } } else { - if (ret == LRE_RET_TIMEOUT) { + switch(ret) { + case LRE_RET_TIMEOUT: JS_ThrowInterrupted(ctx); - } else { + break; + case LRE_RET_MEMORY_ERROR: JS_ThrowInternalError(ctx, "out of memory in regexp execution"); + break; + case LRE_RET_BYTECODE_ERROR: + JS_ThrowInternalError(ctx, "corrupted bytecode in regexp execution"); + break; + default: + abort(); } goto fail; } @@ -46585,8 +49321,8 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, tab = JS_NewArray(ctx); if (JS_IsException(tab)) goto exception; - if (JS_DefinePropertyValueInt64(ctx, tab, 0, js_dup(matched), - JS_PROP_C_W_E | JS_PROP_THROW) < 0) + if (JS_DefinePropertyValueInt64Const(ctx, tab, 0, matched, + JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; for(n = 1; n < nCaptures; n++) { JSValue capN; @@ -46609,10 +49345,10 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, if (functionalReplace) { if (JS_DefinePropertyValueInt64(ctx, tab, n++, js_int32(position), JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; - if (JS_DefinePropertyValueInt64(ctx, tab, n++, js_dup(str), JS_PROP_C_W_E | JS_PROP_THROW) < 0) + if (JS_DefinePropertyValueInt64Const(ctx, tab, n++, str, JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; if (!JS_IsUndefined(namedCaptures)) { - if (JS_DefinePropertyValueInt64(ctx, tab, n++, js_dup(namedCaptures), JS_PROP_C_W_E | JS_PROP_THROW) < 0) + if (JS_DefinePropertyValueInt64Const(ctx, tab, n++, namedCaptures, JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; } args[0] = JS_UNDEFINED; @@ -46892,46 +49628,245 @@ void JS_AddIntrinsicRegExpCompiler(JSContext *ctx) ctx->compile_regexp = js_compile_regexp; } -void JS_AddIntrinsicRegExp(JSContext *ctx) +int JS_AddIntrinsicRegExp(JSContext *ctx) { - JSValue obj; - - JS_AddIntrinsicRegExpCompiler(ctx); + JSValue proto, obj; - ctx->class_proto[JS_CLASS_REGEXP] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_REGEXP], js_regexp_proto_funcs, - countof(js_regexp_proto_funcs)); + proto = ctx->class_proto[JS_CLASS_REGEXP] = JS_NewObject(ctx); + if (JS_IsException(proto)) + return -1; + if (JS_SetPropertyFunctionList(ctx, proto, js_regexp_proto_funcs, + countof(js_regexp_proto_funcs))) { + return -1; + } obj = JS_NewGlobalCConstructor(ctx, "RegExp", js_regexp_constructor, 2, - ctx->class_proto[JS_CLASS_REGEXP]); + proto); + if (JS_IsException(obj)) + return -1; ctx->regexp_ctor = js_dup(obj); - JS_SetPropertyFunctionList(ctx, obj, js_regexp_funcs, countof(js_regexp_funcs)); - - ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR] = + if (JS_SetPropertyFunctionList(ctx, obj, js_regexp_funcs, + countof(js_regexp_funcs))) { + return -1; + } + static const JSShapeProperty regexp_props[] = { + {.atom=JS_ATOM_lastIndex, .flags=JS_PROP_WRITABLE}, + }; + static const JSShapeProperty regexp_result_props[] = { + {.atom=JS_ATOM_length, .flags=JS_PROP_WRITABLE|JS_PROP_LENGTH}, + {.atom=JS_ATOM_index, .flags=JS_PROP_C_W_E}, + {.atom=JS_ATOM_input, .flags=JS_PROP_C_W_E}, + {.atom=JS_ATOM_groups, .flags=JS_PROP_C_W_E}, + }; + if (js_new_shape_with(ctx, &ctx->regexp_shape, proto, + countof(regexp_props), regexp_props)) { + return -1; + } + if (js_new_shape_with(ctx, &ctx->regexp_result_shape, + ctx->class_proto[JS_CLASS_ARRAY], + countof(regexp_result_props), regexp_result_props)) { + return -1; + } + proto = ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR], - js_regexp_string_iterator_proto_funcs, - countof(js_regexp_string_iterator_proto_funcs)); + if (JS_IsException(proto)) + return -1; + if (JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR], + js_regexp_string_iterator_proto_funcs, + countof(js_regexp_string_iterator_proto_funcs))) { + return -1; + } + JS_AddIntrinsicRegExpCompiler(ctx); + return 0; } /* JSON */ -static JSValue json_parse_value(JSParseState *s) +typedef struct { + int count; + uint32_t hash_size; + struct JSONParseRecordEntry *entries; + uint32_t *hash_table; +} JSONParseRecordObject; + +typedef struct JSONParseRecord { + JSValue value; + union { + JSONParseRecordObject obj; + struct { + int count; + struct JSONParseRecord *elements; + } array; + struct { + uint32_t source_pos; + uint32_t source_len; + } primitive; + } u; +} JSONParseRecord; + +typedef struct JSONParseRecordEntry { + JSAtom atom; + uint32_t hash_next; + JSONParseRecord parse_record; +} JSONParseRecordEntry; + +static void json_parse_record_init_obj(JSContext *ctx, JSONParseRecord *pr, JSValueConst val) +{ + pr->value = js_dup(val); + pr->u.obj.count = 0; + pr->u.obj.entries = NULL; + pr->u.obj.hash_table = NULL; + pr->u.obj.hash_size = 0; +} + +static void json_parse_record_init_array(JSContext *ctx, JSONParseRecord *pr, JSValueConst val) +{ + pr->value = js_dup(val); + pr->u.array.count = 0; + pr->u.array.elements = NULL; +} + +static void json_parse_record_init_primitive(JSContext *ctx, JSONParseRecord *pr, JSValueConst val, + uint32_t source_pos, uint32_t source_len) +{ + pr->value = js_dup(val); + pr->u.primitive.source_pos = source_pos; + pr->u.primitive.source_len = source_len; +} + +static int json_parse_record_resize_hash(JSContext *ctx, JSONParseRecordObject *po, uint32_t new_hash_size) +{ + uint32_t i, h, *new_hash_table; + JSONParseRecordEntry *e; + + new_hash_table = js_malloc(ctx, sizeof(new_hash_table[0]) * new_hash_size); + if (!new_hash_table) + return -1; + js_free(ctx, po->hash_table); + po->hash_table = new_hash_table; + po->hash_size = new_hash_size; + + for(i = 0; i < po->hash_size; i++) { + po->hash_table[i] = -1; + } + for(i = 0; i < po->count; i++) { + e = &po->entries[i]; + h = e->atom & (po->hash_size - 1); + e->hash_next = po->hash_table[h]; + po->hash_table[h] = i; + } + return 0; +} + +static JSONParseRecord *json_parse_record_add(JSContext *ctx, JSONParseRecord *pr, JSAtom key, int *psize) +{ + JSONParseRecordObject *po = &pr->u.obj; + JSONParseRecordEntry *e; + JSONParseRecord *pr1; + uint32_t h; + + if (js_resize_array(ctx, (void **)&po->entries, sizeof(po->entries[0]), + psize, po->count + 1)) { + return NULL; + } + /* switch to hash table when going over size threshold */ + if (po->count >= 8 && (po->count + 1) > po->hash_size) { + int hash_bits = 32 - clz32(po->count); + if (json_parse_record_resize_hash(ctx, po, 1 << hash_bits)) + return NULL; + } + + e = &po->entries[po->count++]; + e->atom = JS_DupAtom(ctx, key); + pr1 = &e->parse_record; + pr1->value = JS_UNDEFINED; + if (po->hash_size != 0) { + h = key & (po->hash_size - 1); + e->hash_next = po->hash_table[h]; + po->hash_table[h] = po->count - 1; + } + return pr1; +} + +static JSONParseRecord *json_parse_record_find(JSONParseRecord *pr, JSAtom key) +{ + JSONParseRecordObject *po = &pr->u.obj; + JSONParseRecordEntry *e; + uint32_t h, i; + + if (po->hash_size == 0) { + for(i = 0; i < po->count; i++) { + if (po->entries[i].atom == key) + return &po->entries[i].parse_record; + } + } else { + h = key & (po->hash_size - 1); + i = po->hash_table[h]; + while (i != -1) { + e = &po->entries[i]; + if (e->atom == key) + return &e->parse_record; + i = e->hash_next; + } + } + return NULL; +} + +static void json_free_parse_record(JSContext *ctx, JSONParseRecord *pr) +{ + int i; + if (!pr) + return; + if (JS_IsObject(pr->value)) { + if (js_is_array(ctx, pr->value)) { + for(i = 0; i < pr->u.array.count; i++) { + json_free_parse_record(ctx, &pr->u.array.elements[i]); + } + js_free(ctx, pr->u.array.elements); + } else { + for(i = 0; i < pr->u.obj.count; i++) { + JS_FreeAtom(ctx, pr->u.obj.entries[i].atom); + json_free_parse_record(ctx, &pr->u.obj.entries[i].parse_record); + } + js_free(ctx, pr->u.obj.entries); + js_free(ctx, pr->u.obj.hash_table); + } + } + JS_FreeValue(ctx, pr->value); + pr->value = JS_UNDEFINED; /* fail safe */ +} + +/* 'pr' can be NULL */ +static JSValue json_parse_value(JSParseState *s, JSONParseRecord *pr) { JSContext *ctx = s->ctx; JSValue val = JS_NULL; int ret; + if (js_check_stack_overflow(ctx->rt, 0)) { + return JS_ThrowStackOverflow(ctx); + } + + if (pr) { + pr->value = JS_UNDEFINED; + } + switch(s->token.val) { case '{': { JSValue prop_val; JSAtom prop_name; + JSONParseRecord *pr1; + int pr_size; if (json_next_token(s)) goto fail; val = JS_NewObject(ctx); if (JS_IsException(val)) goto fail; + if (pr) { + json_parse_record_init_obj(ctx, pr, val); + pr_size = 0; + } if (s->token.val != '}') { for(;;) { if (s->token.val == TOK_STRING) { @@ -46950,7 +49885,14 @@ static JSValue json_parse_value(JSParseState *s) } if (json_next_token(s)) goto fail1; - prop_val = json_parse_value(s); + if (pr) { + pr1 = json_parse_record_add(ctx, pr, prop_name, &pr_size); + if (!pr1) + goto fail1; + } else { + pr1 = NULL; + } + prop_val = json_parse_value(s, pr1); if (JS_IsException(prop_val)) { fail1: JS_FreeAtom(ctx, prop_name); @@ -46980,15 +49922,30 @@ static JSValue json_parse_value(JSParseState *s) { JSValue el; uint32_t idx; + JSONParseRecord *pr1; + int pr_size; if (json_next_token(s)) goto fail; val = JS_NewArray(ctx); if (JS_IsException(val)) goto fail; + if (pr) { + json_parse_record_init_array(ctx, pr, val); + pr_size = 0; + } if (s->token.val != ']') { for(idx = 0;; idx++) { - el = json_parse_value(s); + if (pr) { + if (js_resize_array(ctx, (void **)&pr->u.array.elements, sizeof(pr->u.array.elements[0]), + &pr_size, pr->u.array.count + 1)) + goto fail; + pr1 = &pr->u.array.elements[pr->u.array.count++]; + pr1->value = JS_UNDEFINED; + } else { + pr1 = NULL; + } + el = json_parse_value(s, pr1); if (JS_IsException(el)) goto fail; ret = JS_DefinePropertyValueUint32(ctx, val, idx, el, JS_PROP_C_W_E); @@ -47010,11 +49967,21 @@ static JSValue json_parse_value(JSParseState *s) break; case TOK_STRING: val = js_dup(s->token.u.str.str); + if (pr) { + json_parse_record_init_primitive(ctx, pr, val, + s->token.ptr - s->buf_start, + s->buf_ptr - s->token.ptr); + } if (json_next_token(s)) goto fail; break; case TOK_NUMBER: val = s->token.u.num.val; + if (pr) { + json_parse_record_init_primitive(ctx, pr, val, + s->token.ptr - s->buf_start, + s->buf_ptr - s->token.ptr); + } if (json_next_token(s)) goto fail; break; @@ -47022,8 +49989,18 @@ static JSValue json_parse_value(JSParseState *s) if (s->token.u.ident.atom == JS_ATOM_false || s->token.u.ident.atom == JS_ATOM_true) { val = js_bool(s->token.u.ident.atom == JS_ATOM_true); + if (pr) { + json_parse_record_init_primitive(ctx, pr, val, + s->token.ptr - s->buf_start, + s->buf_ptr - s->token.ptr); + } } else if (s->token.u.ident.atom == JS_ATOM_null) { val = JS_NULL; + if (pr) { + json_parse_record_init_primitive(ctx, pr, val, + s->token.ptr - s->buf_start, + s->buf_ptr - s->token.ptr); + } } else { goto def_token; } @@ -47042,12 +50019,13 @@ static JSValue json_parse_value(JSParseState *s) } return val; fail: + json_free_parse_record(ctx, pr); JS_FreeValue(ctx, val); return JS_EXCEPTION; } -/* 'buf' must be zero terminated i.e. buf[buf_len] = '\0'. */ -JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, const char *filename) +static JSValue JS_ParseJSON_internal(JSContext *ctx, const char *buf, size_t buf_len, + const char *filename, JSONParseRecord *pr) { JSParseState s1, *s = &s1; JSValue val = JS_UNDEFINED; @@ -47055,12 +50033,14 @@ JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, const char js_parse_init(ctx, s, buf, buf_len, filename, 1); if (json_next_token(s)) goto fail; - val = json_parse_value(s); + val = json_parse_value(s, pr); if (JS_IsException(val)) goto fail; if (s->token.val != TOK_EOF) { - if (js_parse_error(s, "unexpected data at the end")) + if (js_parse_error(s, "unexpected data at the end")) { + json_free_parse_record(ctx, pr); goto fail; + } } return val; fail: @@ -47069,11 +50049,19 @@ JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, const char return JS_EXCEPTION; } +/* 'buf' must be zero terminated i.e. buf[buf_len] = '\0'. */ +JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, const char *filename) +{ + return JS_ParseJSON_internal(ctx, buf, buf_len, filename, NULL); +} + +/* if pr != NULL, then pr->value = holder by construction */ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, - JSAtom name, JSValueConst reviver) + JSAtom name, JSValueConst reviver, + const char *text_str, JSONParseRecord *pr) { - JSValue val, new_el, name_val, res; - JSValueConst args[2]; + JSValue val, new_el, name_val, res, context; + JSValueConst args[3]; int ret, is_array; uint32_t i, len = 0; JSAtom prop; @@ -47086,6 +50074,29 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, val = JS_GetProperty(ctx, holder, name); if (JS_IsException(val)) return val; + + if (pr) { + if (js_is_array(ctx, pr->value)) { + if (__JS_AtomIsTaggedInt(name)) { + uint32_t idx = __JS_AtomToUInt32(name); + if (idx < pr->u.array.count) { + pr = &pr->u.array.elements[idx]; + } else { + pr = NULL; + } + } + } else { + pr = json_parse_record_find(pr, name); + } + if (pr && !js_same_value(ctx, pr->value, val)) { + pr = NULL; + } + } + + context = JS_NewObject(ctx); + if (JS_IsException(context)) + goto fail; + if (JS_IsObject(val)) { is_array = js_is_array(ctx, val); if (is_array < 0) @@ -47106,7 +50117,7 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, } else { prop = JS_DupAtom(ctx, atoms[i].atom); } - new_el = internalize_json_property(ctx, val, prop, reviver); + new_el = internalize_json_property(ctx, val, prop, reviver, text_str, pr); if (JS_IsException(new_el)) { JS_FreeAtom(ctx, prop); goto fail; @@ -47120,6 +50131,15 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, if (ret < 0) goto fail; } + } else { + if (pr) { + new_el = JS_NewStringLen(ctx, text_str + pr->u.primitive.source_pos, + pr->u.primitive.source_len); + if (JS_IsException(new_el)) + goto fail; + if (JS_DefinePropertyValue(ctx, context, JS_ATOM_source, new_el, JS_PROP_C_W_E) < 0) + goto fail; + } } js_free_prop_enum(ctx, atoms, len); atoms = NULL; @@ -47128,12 +50148,15 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, goto fail; args[0] = name_val; args[1] = val; - res = JS_Call(ctx, reviver, holder, 2, args); + args[2] = context; + res = JS_Call(ctx, reviver, holder, 3, args); JS_FreeValue(ctx, name_val); JS_FreeValue(ctx, val); + JS_FreeValue(ctx, context); return res; fail: js_free_prop_enum(ctx, atoms, len); + JS_FreeValue(ctx, context); JS_FreeValue(ctx, val); return JS_EXCEPTION; } @@ -47141,35 +50164,109 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, static JSValue js_json_parse(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue obj, root; - JSValueConst reviver; + JSValue obj; const char *str; size_t len; str = JS_ToCStringLen(ctx, &len, argv[0]); if (!str) return JS_EXCEPTION; - obj = JS_ParseJSON(ctx, str, len, ""); - JS_FreeCString(ctx, str); - if (JS_IsException(obj)) - return obj; if (argc > 1 && JS_IsFunction(ctx, argv[1])) { + JSONParseRecord pr_s, *pr = &pr_s, *pr1; + JSValue root; + JSValueConst reviver; + int size; + reviver = argv[1]; root = JS_NewObject(ctx); - if (JS_IsException(root)) { - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } + if (JS_IsException(root)) + goto fail; + json_parse_record_init_obj(ctx, pr, root); + size = 0; + pr1 = json_parse_record_add(ctx, pr, JS_ATOM_empty_string, &size); + if (!pr1) + goto fail1; + + obj = JS_ParseJSON_internal(ctx, str, len, "", pr1); + if (JS_IsException(obj)) + goto fail1; + if (JS_DefinePropertyValue(ctx, root, JS_ATOM_empty_string, obj, JS_PROP_C_W_E) < 0) { + fail1: + json_free_parse_record(ctx, pr); JS_FreeValue(ctx, root); - return JS_EXCEPTION; + goto fail; } + obj = internalize_json_property(ctx, root, JS_ATOM_empty_string, - reviver); + reviver, str, pr); + json_free_parse_record(ctx, pr); JS_FreeValue(ctx, root); + } else { + obj = JS_ParseJSON_internal(ctx, str, len, "", NULL); + } + JS_FreeCString(ctx, str); + return obj; + fail: + JS_FreeCString(ctx, str); + return JS_EXCEPTION; +} + +static JSValue js_json_isRawJSON(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValueConst obj = argv[0]; + if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { + JSObject *p = JS_VALUE_GET_OBJ(obj); + return js_bool(p->class_id == JS_CLASS_RAWJSON); + } else { + return JS_FALSE; + } +} + +static bool is_valid_raw_json_char(int c) +{ + return ((c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || + c == '-' || + c == '"'); +} + +static JSValue js_json_rawJSON(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValue str, res, obj; + JSString *p; + str = JS_ToString(ctx, argv[0]); + if (JS_IsException(str)) + return str; + p = JS_VALUE_GET_STRING(str); + if (p->len == 0 || + !is_valid_raw_json_char(string_get(p, 0)) || + !is_valid_raw_json_char(string_get(p, p->len - 1))) { + goto syntax_error; + } + res = js_json_parse(ctx, JS_UNDEFINED, 1, (JSValueConst *)&str); + if (JS_IsException(res)) { + syntax_error: + JS_ThrowSyntaxError(ctx, "invalid rawJSON string"); + goto fail; + } + JS_FreeValue(ctx, res); + + obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_RAWJSON); + if (JS_IsException(obj)) + goto fail; + if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_rawJSON, str, JS_PROP_ENUMERABLE) < 0) { + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; } + JS_PreventExtensions(ctx, obj); return obj; + fail: + JS_FreeValue(ctx, str); + return JS_EXCEPTION; } typedef struct JSONStringifyContext { @@ -47224,6 +50321,7 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc, if (JS_IsFunction(ctx, val)) break; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: case JS_TAG_INT: case JS_TAG_FLOAT64: case JS_TAG_BOOL: @@ -47280,6 +50378,14 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, } else if (cl == JS_CLASS_BOOLEAN || cl == JS_CLASS_BIG_INT) { set_value(ctx, &val, js_dup(p->u.object_data)); goto concat_primitive; + } else if (cl == JS_CLASS_RAWJSON) { + JSValue val1; + val1 = JS_GetProperty(ctx, val, JS_ATOM_rawJSON); + if (JS_IsException(val1)) + goto exception; + JS_FreeValue(ctx, val); + val = val1; + goto concat_value; } v = js_array_includes(ctx, jsc->stack, 1, vc(&val)); if (JS_IsException(v)) @@ -47397,6 +50503,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, concat_primitive: switch (JS_VALUE_GET_NORM_TAG(val)) { case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: val = JS_ToQuotedStringFree(ctx, val); if (JS_IsException(val)) goto exception; @@ -47572,7 +50679,9 @@ static JSValue js_json_stringify(JSContext *ctx, JSValueConst this_val, } static const JSCFunctionListEntry js_json_funcs[] = { + JS_CFUNC_DEF("isRawJSON", 1, js_json_isRawJSON ), JS_CFUNC_DEF("parse", 2, js_json_parse ), + JS_CFUNC_DEF("rawJSON", 1, js_json_rawJSON ), JS_CFUNC_DEF("stringify", 3, js_json_stringify ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "JSON", JS_PROP_CONFIGURABLE ), }; @@ -47581,10 +50690,19 @@ static const JSCFunctionListEntry js_json_obj[] = { JS_OBJECT_DEF("JSON", js_json_funcs, countof(js_json_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), }; -void JS_AddIntrinsicJSON(JSContext *ctx) +static const JSClassShortDef js_json_class_def[] = { + { JS_ATOM_Object, NULL, NULL }, /* JS_CLASS_RAWJSON */ +}; + +int JS_AddIntrinsicJSON(JSContext *ctx) { + if (!JS_IsRegisteredClass(ctx->rt, JS_CLASS_RAWJSON)) { + if (init_class_range(ctx->rt, js_json_class_def, JS_CLASS_RAWJSON, + countof(js_json_class_def)) < 0) + return -1; + } /* add JSON as autoinit object */ - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_json_obj, countof(js_json_obj)); + return JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_json_obj, countof(js_json_obj)); } /* Reflect */ @@ -47974,14 +51092,13 @@ static int js_proxy_has(JSContext *ctx, JSValueConst obj, JSAtom atom) return -1; ret = JS_ToBoolFree(ctx, ret1); if (!ret) { - JSPropertyDescriptor desc; + int desc_flags; p = JS_VALUE_GET_OBJ(s->target); - res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom); + res = JS_GetOwnPropertyFlagsInternal(ctx, &desc_flags, p, atom); if (res < 0) return -1; if (res) { - res2 = !(desc.flags & JS_PROP_CONFIGURABLE); - js_free_desc(ctx, &desc); + res2 = !(desc_flags & JS_PROP_CONFIGURABLE); if (res2 || !p->extensible) { JS_ThrowTypeError(ctx, "proxy: inconsistent has"); return -1; @@ -48108,16 +51225,16 @@ static JSValue js_create_desc(JSContext *ctx, JSValueConst val, if (JS_IsException(ret)) return ret; if (flags & JS_PROP_HAS_GET) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, js_dup(getter), - JS_PROP_C_W_E); + JS_DefinePropertyValueConst(ctx, ret, JS_ATOM_get, getter, + JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_SET) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, js_dup(setter), - JS_PROP_C_W_E); + JS_DefinePropertyValueConst(ctx, ret, JS_ATOM_set, setter, + JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_VALUE) { - JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, js_dup(val), - JS_PROP_C_W_E); + JS_DefinePropertyValueConst(ctx, ret, JS_ATOM_value, val, + JS_PROP_C_W_E); } if (flags & JS_PROP_HAS_WRITABLE) { JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable, @@ -48362,25 +51479,23 @@ static int js_proxy_delete_property(JSContext *ctx, JSValueConst obj, return -1; res = JS_ToBoolFree(ctx, ret); if (res) { - JSPropertyDescriptor desc; - res2 = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom); + int desc_flags; + res2 = JS_GetOwnPropertyFlagsInternal(ctx, &desc_flags, JS_VALUE_GET_OBJ(s->target), atom); if (res2 < 0) return -1; if (res2) { - if (!(desc.flags & JS_PROP_CONFIGURABLE)) - goto fail; + if (!(desc_flags & JS_PROP_CONFIGURABLE)) { + JS_ThrowTypeError(ctx, "proxy: inconsistent deleteProperty"); + return -1; + } is_extensible = JS_IsExtensible(ctx, s->target); if (is_extensible < 0) - goto fail1; + return -1; if (!is_extensible) { /* proxy-missing-checks */ - fail: JS_ThrowTypeError(ctx, "proxy: inconsistent deleteProperty"); - fail1: - js_free_desc(ctx, &desc); return -1; } - js_free_desc(ctx, &desc); } } return res; @@ -48407,7 +51522,6 @@ static int js_proxy_get_own_property_names(JSContext *ctx, uint32_t len, i, len2; JSPropertyEnum *tab, *tab2; JSAtom atom; - JSPropertyDescriptor desc; int res, is_extensible, idx; s = get_proxy_method(ctx, &method, obj, JS_ATOM_ownKeys); @@ -48475,21 +51589,23 @@ static int js_proxy_get_own_property_names(JSContext *ctx, JS_ThrowTypeErrorRevokedProxy(ctx); goto fail; } - res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), - tab2[i].atom); - if (res < 0) - goto fail; - if (res) { /* safety, property should be found */ - js_free_desc(ctx, &desc); - if (!(desc.flags & JS_PROP_CONFIGURABLE) || !is_extensible) { - idx = find_prop_key(tab, len, tab2[i].atom); - if (idx < 0) { - JS_ThrowTypeError(ctx, "proxy: target property must be present in proxy ownKeys"); - goto fail; + { + int desc_flags; + res = JS_GetOwnPropertyFlagsInternal(ctx, &desc_flags, JS_VALUE_GET_OBJ(s->target), + tab2[i].atom); + if (res < 0) + goto fail; + if (res) { /* safety, property should be found */ + if (!(desc_flags & JS_PROP_CONFIGURABLE) || !is_extensible) { + idx = find_prop_key(tab, len, tab2[i].atom); + if (idx < 0) { + JS_ThrowTypeError(ctx, "proxy: target property must be present in proxy ownKeys"); + goto fail; + } + /* mark the property as found */ + if (!is_extensible) + tab[idx].is_enumerable = true; } - /* mark the property as found */ - if (!is_extensible) - tab[idx].is_enumerable = true; } } } @@ -48612,23 +51728,19 @@ static const JSClassExoticMethods js_proxy_exotic_methods = { .set_property = js_proxy_set, }; -static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) +JSValue JS_NewProxy(JSContext *ctx, JSValueConst target, JSValueConst handler) { - JSValueConst target, handler; - JSValue obj; JSProxyData *s; + JSValue obj; - target = argv[0]; - handler = argv[1]; if (JS_VALUE_GET_TAG(target) != JS_TAG_OBJECT || - JS_VALUE_GET_TAG(handler) != JS_TAG_OBJECT) + JS_VALUE_GET_TAG(handler) != JS_TAG_OBJECT) { return JS_ThrowTypeErrorNotAnObject(ctx); - + } obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_PROXY); if (JS_IsException(obj)) return obj; - s = js_malloc(ctx, sizeof(JSProxyData)); + s = js_malloc(ctx, sizeof(*s)); if (!s) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; @@ -48642,6 +51754,12 @@ static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val, return obj; } +static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + return JS_NewProxy(ctx, argv[0], argv[1]); +} + static JSValue js_proxy_revoke(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValueConst *func_data) @@ -48695,25 +51813,36 @@ static const JSClassShortDef js_proxy_class_def[] = { { JS_ATOM_Object, js_proxy_finalizer, js_proxy_mark }, /* JS_CLASS_PROXY */ }; -void JS_AddIntrinsicProxy(JSContext *ctx) +int JS_AddIntrinsicProxy(JSContext *ctx) { JSRuntime *rt = ctx->rt; JSValue obj1; if (!JS_IsRegisteredClass(rt, JS_CLASS_PROXY)) { - init_class_range(rt, js_proxy_class_def, JS_CLASS_PROXY, - countof(js_proxy_class_def)); + if (init_class_range(rt, js_proxy_class_def, JS_CLASS_PROXY, + countof(js_proxy_class_def))) + return -1; rt->class_array[JS_CLASS_PROXY].exotic = &js_proxy_exotic_methods; rt->class_array[JS_CLASS_PROXY].call = js_proxy_call; } - obj1 = JS_NewCFunction2(ctx, js_proxy_constructor, "Proxy", 2, - JS_CFUNC_constructor, 0); + /* additional fields: name, length */ + obj1 = JS_NewCFunction3(ctx, js_proxy_constructor, "Proxy", 2, + JS_CFUNC_constructor, 0, + ctx->function_proto, countof(js_proxy_funcs) + 2); + if (JS_IsException(obj1)) + return -1; JS_SetConstructorBit(ctx, obj1, true); - JS_SetPropertyFunctionList(ctx, obj1, js_proxy_funcs, - countof(js_proxy_funcs)); - JS_DefinePropertyValueStr(ctx, ctx->global_obj, "Proxy", - obj1, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + if (JS_SetPropertyFunctionList(ctx, obj1, js_proxy_funcs, + countof(js_proxy_funcs))) + goto fail; + if (JS_DefinePropertyValueStr(ctx, ctx->global_obj, "Proxy", + obj1, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0) + goto fail; + return 0; + fail: + JS_FreeValue(ctx, obj1); + return -1; } bool JS_IsProxy(JSValueConst val) @@ -48859,6 +51988,21 @@ static JSValue js_symbol_keyFor(JSContext *ctx, JSValueConst this_val, static const JSCFunctionListEntry js_symbol_funcs[] = { JS_CFUNC_DEF("for", 1, js_symbol_for ), JS_CFUNC_DEF("keyFor", 1, js_symbol_keyFor ), + JS_PROP_SYMBOL_DEF("toPrimitive", JS_ATOM_Symbol_toPrimitive, 0), + JS_PROP_SYMBOL_DEF("iterator", JS_ATOM_Symbol_iterator, 0), + JS_PROP_SYMBOL_DEF("match", JS_ATOM_Symbol_match, 0), + JS_PROP_SYMBOL_DEF("matchAll", JS_ATOM_Symbol_matchAll, 0), + JS_PROP_SYMBOL_DEF("replace", JS_ATOM_Symbol_replace, 0), + JS_PROP_SYMBOL_DEF("search", JS_ATOM_Symbol_search, 0), + JS_PROP_SYMBOL_DEF("split", JS_ATOM_Symbol_split, 0), + JS_PROP_SYMBOL_DEF("toStringTag", JS_ATOM_Symbol_toStringTag, 0), + JS_PROP_SYMBOL_DEF("isConcatSpreadable", JS_ATOM_Symbol_isConcatSpreadable, 0), + JS_PROP_SYMBOL_DEF("hasInstance", JS_ATOM_Symbol_hasInstance, 0), + JS_PROP_SYMBOL_DEF("species", JS_ATOM_Symbol_species, 0), + JS_PROP_SYMBOL_DEF("unscopables", JS_ATOM_Symbol_unscopables, 0), + JS_PROP_SYMBOL_DEF("asyncIterator", JS_ATOM_Symbol_asyncIterator, 0), + JS_PROP_SYMBOL_DEF("dispose", JS_ATOM_Symbol_dispose, 0), + JS_PROP_SYMBOL_DEF("asyncDispose", JS_ATOM_Symbol_asyncDispose, 0), }; /* Set/Map/WeakSet/WeakMap */ @@ -48903,7 +52047,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target, if (JS_IsException(adder)) goto fail; if (!JS_IsFunction(ctx, adder)) { - JS_ThrowTypeError(ctx, "set/add is not a function"); + JS_ThrowTypeError(ctx, "%s is not a function", is_set ? "set" : "add"); goto fail; } @@ -49006,6 +52150,9 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key) case JS_TAG_STRING: h = hash_string(JS_VALUE_GET_STRING(key), 0); break; + case JS_TAG_STRING_ROPE: + h = hash_string_rope(key, 0); + break; case JS_TAG_OBJECT: case JS_TAG_SYMBOL: h = (uintptr_t)JS_VALUE_GET_PTR(key) * 3163; @@ -50390,37 +53537,50 @@ static const uint8_t js_map_proto_funcs_count[6] = { countof(js_set_iterator_proto_funcs), }; -void JS_AddIntrinsicMapSet(JSContext *ctx) +int JS_AddIntrinsicMapSet(JSContext *ctx) { int i; JSValue obj1; char buf[ATOM_GET_STR_BUF_SIZE]; + /* Used to squelch a -Wcast-function-type warning. */ + JSCFunctionType ft = { .constructor_magic = js_map_constructor }; for(i = 0; i < 4; i++) { const char *name = JS_AtomGetStr(ctx, buf, sizeof(buf), JS_ATOM_Map + i); int class_id = JS_CLASS_MAP + i; - ctx->class_proto[class_id] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[class_id], - js_map_proto_funcs_ptr[i], - js_map_proto_funcs_count[i]); - obj1 = JS_NewCFunctionMagic(ctx, js_map_constructor, name, 0, - JS_CFUNC_constructor_magic, i); - if (class_id == JS_CLASS_MAP) - JS_SetPropertyFunctionList(ctx, obj1, js_map_funcs, countof(js_map_funcs)); - else if (class_id == JS_CLASS_SET) - JS_SetPropertyFunctionList(ctx, obj1, js_set_funcs, countof(js_set_funcs)); - - JS_NewGlobalCConstructor2(ctx, obj1, name, ctx->class_proto[class_id]); + const JSCFunctionListEntry *ctor_funcs; + int n_ctor_funcs; + if (class_id == JS_CLASS_MAP) { + ctor_funcs = js_map_funcs; + n_ctor_funcs = countof(js_map_funcs); + } else if (class_id == JS_CLASS_SET) { + ctor_funcs = js_set_funcs; + n_ctor_funcs = countof(js_set_funcs); + } else { + ctor_funcs = NULL; + n_ctor_funcs = 0; + } + obj1 = JS_NewCConstructor(ctx, class_id, name, + ft.generic, 0, JS_CFUNC_constructor_magic, i, + JS_UNDEFINED, + ctor_funcs, n_ctor_funcs, + js_map_proto_funcs_ptr[i], js_map_proto_funcs_count[i], + 0); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); } for(i = 0; i < 2; i++) { ctx->class_proto[JS_CLASS_MAP_ITERATOR + i] = - JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_MAP_ITERATOR + i], - js_map_proto_funcs_ptr[i + 4], - js_map_proto_funcs_count[i + 4]); + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_map_proto_funcs_ptr[i + 4], + js_map_proto_funcs_count[i + 4]); + if (JS_IsException(ctx->class_proto[JS_CLASS_MAP_ITERATOR + i])) + return -1; } + return 0; } /* Generator */ @@ -50435,6 +53595,658 @@ static const JSCFunctionListEntry js_generator_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Generator", JS_PROP_CONFIGURABLE), }; +/* Explicit resource management */ + +enum { + JS_DISPOSE_HINT_SYNC, /* use: Call(method, value) */ + JS_DISPOSE_HINT_ADOPT, /* adopt: Call(method, undefined, [value]) */ + JS_DISPOSE_HINT_DEFER, /* defer: Call(method, undefined) */ +}; + +typedef struct JSDisposableResource { + JSValue value; + JSValue method; /* dispose method */ + uint8_t hint; +} JSDisposableResource; + +typedef struct JSDisposableStack { + bool disposed; + int resource_count; + int resource_capacity; + JSDisposableResource *resources; +} JSDisposableStack; + +static JSValue js_new_suppressed_error(JSContext *ctx, JSValueConst error, + JSValueConst suppressed) +{ + JSValue obj; + + /* Construct via the intrinsic prototype rather than going through + SuppressedError.prototype.constructor, which is user-writable. */ + obj = JS_NewObjectProtoClass(ctx, + ctx->native_error_proto[JS_SUPPRESSED_ERROR], + JS_CLASS_ERROR); + if (JS_IsException(obj)) + return JS_EXCEPTION; + JS_DefinePropertyValue(ctx, obj, JS_ATOM_error, js_dup(error), + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_DefinePropertyValue(ctx, obj, JS_ATOM_suppressed, js_dup(suppressed), + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + build_backtrace(ctx, obj, JS_UNDEFINED, NULL, 0, 0, + JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL); + return obj; +} + +/* Perform DisposeResources. Returns 0 on success, -1 on exception. + completion_error is the pending error (JS_UNDEFINED if none). + It is consumed (freed) by this function. */ +static int js_dispose_resources(JSContext *ctx, JSDisposableStack *ds, + JSValue completion_error) +{ + JSValue error = completion_error; + bool has_error = !JS_IsUndefined(error); + int i; + + ds->disposed = true; + /* dispose in LIFO order */ + for (i = ds->resource_count - 1; i >= 0; i--) { + JSDisposableResource *res = &ds->resources[i]; + JSValue ret; + if (JS_IsUndefined(res->method)) { + /* null/undefined resource, skip */ + JS_FreeValue(ctx, res->value); + continue; + } + switch (res->hint) { + case JS_DISPOSE_HINT_ADOPT: + ret = JS_Call(ctx, res->method, JS_UNDEFINED, 1, vc(&res->value)); + break; + case JS_DISPOSE_HINT_DEFER: + ret = JS_Call(ctx, res->method, JS_UNDEFINED, 0, NULL); + break; + default: /* JS_DISPOSE_HINT_SYNC */ + ret = JS_Call(ctx, res->method, res->value, 0, NULL); + break; + } + JS_FreeValue(ctx, res->value); + JS_FreeValue(ctx, res->method); + if (JS_IsException(ret)) { + JSValue new_error = JS_GetException(ctx); + if (has_error) { + JSValue suppressed = js_new_suppressed_error(ctx, new_error, error); + JS_FreeValue(ctx, new_error); + JS_FreeValue(ctx, error); + if (JS_IsException(suppressed)) { + error = JS_GetException(ctx); + } else { + error = suppressed; + } + } else { + error = new_error; + has_error = true; + } + } else { + JS_FreeValue(ctx, ret); + } + } + ds->resource_count = 0; + if (has_error) { + JS_Throw(ctx, error); + return -1; + } + return 0; +} + +static void js_disposable_stack_clear(JSRuntime *rt, JSDisposableStack *ds) +{ + int i; + for (i = 0; i < ds->resource_count; i++) { + JS_FreeValueRT(rt, ds->resources[i].value); + JS_FreeValueRT(rt, ds->resources[i].method); + } + js_free_rt(rt, ds->resources); +} + +static int js_disposable_stack_add(JSContext *ctx, JSDisposableStack *ds, + JSValueConst value, JSValueConst method, + int hint) +{ + if (ds->resource_count >= ds->resource_capacity) { + int new_cap = max_int(ds->resource_capacity * 2, 4); + JSDisposableResource *new_res; + new_res = js_realloc(ctx, ds->resources, + new_cap * sizeof(JSDisposableResource)); + if (!new_res) + return -1; + ds->resources = new_res; + ds->resource_capacity = new_cap; + } + ds->resources[ds->resource_count].value = js_dup(value); + ds->resources[ds->resource_count].method = js_dup(method); + ds->resources[ds->resource_count].hint = hint; + ds->resource_count++; + return 0; +} + +static JSValue js_sync_dispose_wrapper(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, + int magic, JSValueConst *func_data) +{ + JSValueConst method = func_data[0]; + JSValue ret = JS_Call(ctx, method, this_val, 0, NULL); + if (JS_IsException(ret)) + return JS_EXCEPTION; + JS_FreeValue(ctx, ret); + return JS_UNDEFINED; +} + +static JSValue js_get_dispose_method(JSContext *ctx, JSValueConst value, int hint) +{ + JSValue method; + + if (hint == 1) { + /* async: try Symbol.asyncDispose first */ + method = JS_GetProperty(ctx, value, JS_ATOM_Symbol_asyncDispose); + if (JS_IsException(method)) + return JS_EXCEPTION; + if (!JS_IsUndefined(method) && !JS_IsNull(method)) { + if (!JS_IsFunction(ctx, method)) { + JS_FreeValue(ctx, method); + return JS_ThrowTypeError(ctx, "property is not a function"); + } + return method; + } + JS_FreeValue(ctx, method); + /* Fall back to Symbol.dispose, but wrap it so its return value is + NOT awaited (per spec GetDisposeMethod). */ + method = JS_GetProperty(ctx, value, JS_ATOM_Symbol_dispose); + if (JS_IsException(method)) + return JS_EXCEPTION; + if (JS_IsUndefined(method) || JS_IsNull(method)) + return JS_ThrowTypeError(ctx, "property is not a function"); + if (!JS_IsFunction(ctx, method)) { + JS_FreeValue(ctx, method); + return JS_ThrowTypeError(ctx, "property is not a function"); + } + + { + JSValue data[1], wrapped; + data[0] = method; + wrapped = JS_NewCFunctionData(ctx, js_sync_dispose_wrapper, 0, 0, + 1, vc(data)); + JS_FreeValue(ctx, method); + return wrapped; + } + } + + /* sync dispose */ + method = JS_GetProperty(ctx, value, JS_ATOM_Symbol_dispose); + if (JS_IsException(method)) + return JS_EXCEPTION; + if (JS_IsUndefined(method) || JS_IsNull(method)) + return JS_ThrowTypeError(ctx, "property is not a function"); + if (!JS_IsFunction(ctx, method)) { + JS_FreeValue(ctx, method); + return JS_ThrowTypeError(ctx, "property is not a function"); + } + return method; +} + +static JSValue js_disposable_stack_constructor(JSContext *ctx, + JSValueConst new_target, + int argc, JSValueConst *argv, + int class_id) +{ + JSDisposableStack *s; + JSValue obj; + + if (JS_IsUndefined(new_target)) + return JS_ThrowTypeError(ctx, "Constructor requires 'new'"); + obj = js_create_from_ctor(ctx, new_target, class_id); + if (JS_IsException(obj)) + return JS_EXCEPTION; + s = js_mallocz(ctx, sizeof(*s)); + if (!s) { + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; + } + JS_SetOpaqueInternal(obj, s); + return obj; +} + +static void js_disposable_stack_finalizer(JSRuntime *rt, JSValueConst val) +{ + JSObject *p; + JSDisposableStack *s; + + p = JS_VALUE_GET_OBJ(val); + s = p->u.opaque; + if (s) { + js_disposable_stack_clear(rt, s); + js_free_rt(rt, s); + } +} + +static void js_disposable_stack_mark(JSRuntime *rt, JSValueConst val, + JS_MarkFunc *mark_func) +{ + JSObject *p; + JSDisposableStack *s; + int i; + + p = JS_VALUE_GET_OBJ(val); + s = p->u.opaque; + if (s) { + for (i = 0; i < s->resource_count; i++) { + JS_MarkValue(rt, s->resources[i].value, mark_func); + JS_MarkValue(rt, s->resources[i].method, mark_func); + } + } +} + +static JSDisposableStack *js_disposable_stack_get(JSContext *ctx, + JSValueConst this_val, + int class_id) +{ + JSDisposableStack *s; + s = JS_GetOpaque2(ctx, this_val, class_id); + if (!s) + return NULL; + if (s->disposed) { + JS_ThrowReferenceError(ctx, "DisposableStack has been disposed"); + return NULL; + } + return s; +} + +static JSValue js_disposable_stack_use(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, int class_id) +{ + JSDisposableStack *s; + JSValueConst value; + JSValue method; + int hint = (class_id == JS_CLASS_ASYNC_DISPOSABLE_STACK) ? 1 : 0; + + s = js_disposable_stack_get(ctx, this_val, class_id); + if (!s) + return JS_EXCEPTION; + value = argv[0]; + if (JS_IsNull(value) || JS_IsUndefined(value)) { + /* For async stacks, a null/undefined resource still needs a record + so disposeAsync performs the required Await(undefined). */ + if (class_id == JS_CLASS_ASYNC_DISPOSABLE_STACK) { + if (js_disposable_stack_add(ctx, s, JS_UNDEFINED, JS_UNDEFINED, + JS_DISPOSE_HINT_SYNC) < 0) + return JS_EXCEPTION; + } + return js_dup(value); + } + if (!JS_IsObject(value)) + return JS_ThrowTypeError(ctx, "not an object"); + method = js_get_dispose_method(ctx, value, hint); + if (JS_IsException(method)) + return JS_EXCEPTION; + if (js_disposable_stack_add(ctx, s, value, method, JS_DISPOSE_HINT_SYNC) < 0) { + JS_FreeValue(ctx, method); + return JS_EXCEPTION; + } + JS_FreeValue(ctx, method); + return js_dup(value); +} + +static JSValue js_disposable_stack_adopt(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, int class_id) +{ + JSDisposableStack *s; + JSValueConst value, on_dispose; + + s = js_disposable_stack_get(ctx, this_val, class_id); + if (!s) + return JS_EXCEPTION; + value = argv[0]; + on_dispose = argv[1]; + if (!JS_IsFunction(ctx, on_dispose)) + return JS_ThrowTypeError(ctx, "not a function"); + if (js_disposable_stack_add(ctx, s, value, on_dispose, JS_DISPOSE_HINT_ADOPT) < 0) + return JS_EXCEPTION; + return js_dup(value); +} + +static JSValue js_disposable_stack_defer(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, int class_id) +{ + JSDisposableStack *s; + JSValueConst on_dispose; + + s = js_disposable_stack_get(ctx, this_val, class_id); + if (!s) + return JS_EXCEPTION; + on_dispose = argv[0]; + if (!JS_IsFunction(ctx, on_dispose)) + return JS_ThrowTypeError(ctx, "not a function"); + if (js_disposable_stack_add(ctx, s, JS_UNDEFINED, on_dispose, JS_DISPOSE_HINT_DEFER) < 0) + return JS_EXCEPTION; + return JS_UNDEFINED; +} + +/* Simple .then handler that discards its argument and returns undefined; + used to normalize the chain's resolved value after all disposals. */ +static JSValue js_async_dispose_to_undef(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, + int magic, JSValueConst *func_data) +{ + return JS_UNDEFINED; +} + +static JSValue js_async_dispose_rethrow(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, + int magic, JSValueConst *func_data) +{ + JSValue prev_err = js_dup(func_data[0]); + if (magic == 0) { + return JS_Throw(ctx, prev_err); + } else { + JSValue se = js_new_suppressed_error(ctx, argv[0], prev_err); + JS_FreeValue(ctx, prev_err); + if (JS_IsException(se)) + return JS_EXCEPTION; + return JS_Throw(ctx, se); + } +} + +static JSValue js_async_dispose_step(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, + int magic, JSValueConst *func_data) +{ + JSValueConst value = func_data[0]; + JSValueConst method = func_data[1]; + int hint = JS_VALUE_GET_INT(func_data[2]); + bool has_prev_err = (magic == 1); + JSValue ret; + + if (JS_IsUndefined(method)) { + /* null/undefined resource on async stack: Await(undefined) */ + if (has_prev_err) + return JS_Throw(ctx, js_dup(argv[0])); + return JS_UNDEFINED; + } + + switch (hint) { + case JS_DISPOSE_HINT_ADOPT: + ret = JS_Call(ctx, method, JS_UNDEFINED, 1, &value); + break; + case JS_DISPOSE_HINT_DEFER: + ret = JS_Call(ctx, method, JS_UNDEFINED, 0, NULL); + break; + default: + ret = JS_Call(ctx, method, value, 0, NULL); + break; + } + + if (JS_IsException(ret)) { + JSValue new_err = JS_GetException(ctx); + if (has_prev_err) { + JSValue se = js_new_suppressed_error(ctx, new_err, argv[0]); + JS_FreeValue(ctx, new_err); + if (JS_IsException(se)) + return JS_EXCEPTION; + return JS_Throw(ctx, se); + } + return JS_Throw(ctx, new_err); + } + + if (!has_prev_err) { + /* Propagate method result; next .then awaits it */ + return ret; + } + + /* Await ret, then rethrow the stored error (possibly wrapped) */ + { + JSValueConst prev_err = argv[0]; + JSValue ret_promise, resolve_fn, reject_fn, then_args[2], result; + ret_promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&ret), 0); + JS_FreeValue(ctx, ret); + if (JS_IsException(ret_promise)) + return JS_EXCEPTION; + resolve_fn = JS_NewCFunctionData(ctx, js_async_dispose_rethrow, 0, 0, + 1, &prev_err); + reject_fn = JS_NewCFunctionData(ctx, js_async_dispose_rethrow, 0, 1, + 1, &prev_err); + then_args[0] = resolve_fn; + then_args[1] = reject_fn; + result = JS_Invoke(ctx, ret_promise, JS_ATOM_then, 2, vc(then_args)); + JS_FreeValue(ctx, resolve_fn); + JS_FreeValue(ctx, reject_fn); + JS_FreeValue(ctx, ret_promise); + return result; + } +} + +static JSValue js_disposable_stack_dispose(JSContext *ctx, + JSValueConst this_val, + int argc, + JSValueConst *argv, + int class_id) +{ + JSDisposableStack *s; + + s = JS_GetOpaque2(ctx, this_val, class_id); + if (!s) { + if (class_id == JS_CLASS_ASYNC_DISPOSABLE_STACK) { + JSValue exc = JS_GetException(ctx); + JSValue p = js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&exc), + /*is_reject*/1); + JS_FreeValue(ctx, exc); + return p; + } + return JS_EXCEPTION; + } + if (s->disposed) { + if (class_id == JS_CLASS_ASYNC_DISPOSABLE_STACK) { + JSValue undef = JS_UNDEFINED; + return js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&undef), + /*is_reject*/0); + } + return JS_UNDEFINED; + } + if (class_id == JS_CLASS_ASYNC_DISPOSABLE_STACK) { + /* Per spec DisposeResources: iterate resources in LIFO order and + for each do Call + Await. The first Call happens synchronously + inside disposeAsync(); subsequent Calls fire in microtasks via a + Promise.then() chain so that each call sees the previous + dispose's promise already settled. */ + int i, count = s->resource_count; + JSValue chain, undef, ret; + + s->disposed = true; + + /* First (top-of-stack) resource: synchronous Call. */ + undef = JS_UNDEFINED; + i = count - 1; + if (i < 0) { + chain = js_promise_resolve(ctx, ctx->promise_ctor, 1, vc(&undef), + /*is_reject*/0); + if (JS_IsException(chain)) + goto async_dispose_fail; + } else { + JSDisposableResource *res = &s->resources[i]; + if (JS_IsUndefined(res->method)) { + /* null/undefined resource: Await(undefined) */ + chain = js_promise_resolve(ctx, ctx->promise_ctor, 1, + vc(&undef), /*is_reject*/0); + } else { + switch (res->hint) { + case JS_DISPOSE_HINT_ADOPT: + ret = JS_Call(ctx, res->method, JS_UNDEFINED, 1, + vc(&res->value)); + break; + case JS_DISPOSE_HINT_DEFER: + ret = JS_Call(ctx, res->method, JS_UNDEFINED, 0, NULL); + break; + default: + ret = JS_Call(ctx, res->method, res->value, 0, NULL); + break; + } + if (JS_IsException(ret)) { + JSValue err = JS_GetException(ctx); + chain = js_promise_resolve(ctx, ctx->promise_ctor, 1, + vc(&err), /*is_reject*/1); + JS_FreeValue(ctx, err); + } else { + chain = js_promise_resolve(ctx, ctx->promise_ctor, 1, + vc(&ret), /*is_reject*/0); + JS_FreeValue(ctx, ret); + } + } + JS_FreeValue(ctx, res->value); + JS_FreeValue(ctx, res->method); + res->value = JS_UNDEFINED; + res->method = JS_UNDEFINED; + if (JS_IsException(chain)) { + i--; + goto async_dispose_fail; + } + i--; + } + + /* Remaining resources: chain lazy steps. */ + for (; i >= 0; i--) { + JSDisposableResource *res = &s->resources[i]; + JSValueConst data[3]; + JSValue hint_val, resolve_fn, reject_fn, then_args[2], new_chain; + + hint_val = JS_NewInt32(ctx, res->hint); + data[0] = res->value; + data[1] = res->method; + data[2] = hint_val; + resolve_fn = JS_NewCFunctionData(ctx, js_async_dispose_step, 0, 0, + 3, data); + reject_fn = JS_NewCFunctionData(ctx, js_async_dispose_step, 0, 1, + 3, data); + JS_FreeValue(ctx, hint_val); + JS_FreeValue(ctx, res->value); + JS_FreeValue(ctx, res->method); + res->value = JS_UNDEFINED; + res->method = JS_UNDEFINED; + if (JS_IsException(resolve_fn) || JS_IsException(reject_fn)) { + JS_FreeValue(ctx, resolve_fn); + JS_FreeValue(ctx, reject_fn); + JS_FreeValue(ctx, chain); + chain = JS_EXCEPTION; + goto async_dispose_fail; + } + then_args[0] = resolve_fn; + then_args[1] = reject_fn; + new_chain = JS_Invoke(ctx, chain, JS_ATOM_then, 2, vc(then_args)); + JS_FreeValue(ctx, resolve_fn); + JS_FreeValue(ctx, reject_fn); + JS_FreeValue(ctx, chain); + if (JS_IsException(new_chain)) { + chain = JS_EXCEPTION; + goto async_dispose_fail; + } + chain = new_chain; + } + s->resource_count = 0; + + if (count > 0) { + JSValue undef_fn, then_args[1], new_chain; + undef_fn = JS_NewCFunctionData(ctx, js_async_dispose_to_undef, + 0, 0, 0, NULL); + if (JS_IsException(undef_fn)) { + JS_FreeValue(ctx, chain); + return JS_EXCEPTION; + } + then_args[0] = undef_fn; + new_chain = JS_Invoke(ctx, chain, JS_ATOM_then, 1, vc(then_args)); + JS_FreeValue(ctx, undef_fn); + JS_FreeValue(ctx, chain); + return new_chain; + } + return chain; + + async_dispose_fail: + for (; i >= 0; i--) { + JSDisposableResource *res = &s->resources[i]; + JS_FreeValue(ctx, res->value); + JS_FreeValue(ctx, res->method); + res->value = JS_UNDEFINED; + res->method = JS_UNDEFINED; + } + s->resource_count = 0; + return JS_EXCEPTION; + } + if (js_dispose_resources(ctx, s, JS_UNDEFINED) < 0) + return JS_EXCEPTION; + return JS_UNDEFINED; +} + +static JSValue js_disposable_stack_move(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, int class_id) +{ + JSDisposableStack *s, *ns; + JSValue new_obj; + + s = js_disposable_stack_get(ctx, this_val, class_id); + if (!s) + return JS_EXCEPTION; + /* Use the intrinsic prototype directly so tampering with the global + binding or subclassing cannot redirect move(). */ + new_obj = JS_NewObjectProtoClass(ctx, ctx->class_proto[class_id], + class_id); + if (JS_IsException(new_obj)) + return JS_EXCEPTION; + ns = js_mallocz(ctx, sizeof(*ns)); + if (!ns) { + JS_FreeValue(ctx, new_obj); + return JS_EXCEPTION; + } + JS_SetOpaqueInternal(new_obj, ns); + /* Transfer resources to new stack */ + ns->resources = s->resources; + ns->resource_count = s->resource_count; + ns->resource_capacity = s->resource_capacity; + /* Reset original stack */ + s->resources = NULL; + s->resource_count = 0; + s->resource_capacity = 0; + s->disposed = true; + return new_obj; +} + +static JSValue js_disposable_stack_get_disposed(JSContext *ctx, + JSValueConst this_val, int class_id) +{ + JSDisposableStack *s; + + s = JS_GetOpaque2(ctx, this_val, class_id); + if (!s) + return JS_EXCEPTION; + return js_bool(s->disposed); +} + +static const JSCFunctionListEntry js_disposable_stack_proto_funcs[] = { + JS_CFUNC_MAGIC_DEF("adopt", 2, js_disposable_stack_adopt, JS_CLASS_DISPOSABLE_STACK ), + JS_CFUNC_MAGIC_DEF("defer", 1, js_disposable_stack_defer, JS_CLASS_DISPOSABLE_STACK ), + JS_CFUNC_MAGIC_DEF("dispose", 0, js_disposable_stack_dispose, JS_CLASS_DISPOSABLE_STACK ), + JS_CFUNC_MAGIC_DEF("move", 0, js_disposable_stack_move, JS_CLASS_DISPOSABLE_STACK ), + JS_CFUNC_MAGIC_DEF("use", 1, js_disposable_stack_use, JS_CLASS_DISPOSABLE_STACK ), + JS_CGETSET_MAGIC_DEF("disposed", js_disposable_stack_get_disposed, NULL, JS_CLASS_DISPOSABLE_STACK ), + JS_ALIAS_DEF("[Symbol.dispose]", "dispose" ), + JS_PROP_STRING_DEF("[Symbol.toStringTag]", "DisposableStack", JS_PROP_CONFIGURABLE ), +}; + +static const JSCFunctionListEntry js_async_disposable_stack_proto_funcs[] = { + JS_CFUNC_MAGIC_DEF("adopt", 2, js_disposable_stack_adopt, JS_CLASS_ASYNC_DISPOSABLE_STACK ), + JS_CFUNC_MAGIC_DEF("defer", 1, js_disposable_stack_defer, JS_CLASS_ASYNC_DISPOSABLE_STACK ), + JS_CFUNC_MAGIC_DEF("disposeAsync", 0, js_disposable_stack_dispose, JS_CLASS_ASYNC_DISPOSABLE_STACK ), + JS_CFUNC_MAGIC_DEF("move", 0, js_disposable_stack_move, JS_CLASS_ASYNC_DISPOSABLE_STACK ), + JS_CFUNC_MAGIC_DEF("use", 1, js_disposable_stack_use, JS_CLASS_ASYNC_DISPOSABLE_STACK ), + JS_CGETSET_MAGIC_DEF("disposed", js_disposable_stack_get_disposed, NULL, JS_CLASS_ASYNC_DISPOSABLE_STACK ), + JS_ALIAS_DEF("[Symbol.asyncDispose]", "disposeAsync" ), + JS_PROP_STRING_DEF("[Symbol.toStringTag]", "AsyncDisposableStack", JS_PROP_CONFIGURABLE), +}; + /* Promise */ typedef struct JSPromiseData { @@ -50465,7 +54277,7 @@ JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValueConst promise) { JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE); if (!s) - return -1; + return JS_PROMISE_NOT_A_PROMISE; return s->promise_state; } @@ -50484,6 +54296,11 @@ bool JS_IsPromise(JSValueConst val) return JS_VALUE_GET_OBJ(val)->class_id == JS_CLASS_PROMISE; } +JSValue JS_NewSettledPromise(JSContext *ctx, bool is_reject, JSValueConst value) +{ + return js_promise_resolve(ctx, ctx->promise_ctor, 1, &value, is_reject); +} + static int js_create_resolving_functions(JSContext *ctx, JSValue *args, JSValueConst promise); @@ -50814,33 +54631,33 @@ static void js_promise_mark(JSRuntime *rt, JSValueConst val, JS_MarkValue(rt, s->promise_result, mark_func); } -static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) +/* Create a new promise object with resolving functions. Returns the promise + and sets resolving_funcs[0] (resolve) and resolving_funcs[1] (reject). */ +static JSValue js_promise_new(JSContext *ctx, JSValueConst new_target, + JSValue *resolving_funcs) { - JSValueConst executor; JSValue obj; JSPromiseData *s; JSRuntime *rt; - JSValue args[2], ret; - int i; - executor = argv[0]; - if (check_function(ctx, executor)) - return JS_EXCEPTION; obj = js_create_from_ctor(ctx, new_target, JS_CLASS_PROMISE); if (JS_IsException(obj)) return JS_EXCEPTION; s = js_mallocz(ctx, sizeof(*s)); - if (!s) - goto fail; + if (!s) { + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; + } s->promise_state = JS_PROMISE_PENDING; s->is_handled = false; - for(i = 0; i < 2; i++) - init_list_head(&s->promise_reactions[i]); + init_list_head(&s->promise_reactions[0]); + init_list_head(&s->promise_reactions[1]); s->promise_result = JS_UNDEFINED; JS_SetOpaqueInternal(obj, s); - if (js_create_resolving_functions(ctx, args, obj)) - goto fail; + if (js_create_resolving_functions(ctx, resolving_funcs, obj)) { + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; + } rt = ctx->rt; if (rt->promise_hook) { JSValueConst parent_promise = JS_UNDEFINED; @@ -50849,6 +54666,22 @@ static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target, rt->promise_hook(ctx, JS_PROMISE_HOOK_INIT, obj, parent_promise, rt->promise_hook_opaque); } + return obj; +} + +static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target, + int argc, JSValueConst *argv) +{ + JSValueConst executor; + JSValue obj; + JSValue args[2], ret; + + executor = argv[0]; + if (check_function(ctx, executor)) + return JS_EXCEPTION; + obj = js_promise_new(ctx, new_target, args); + if (JS_IsException(obj)) + return JS_EXCEPTION; ret = JS_Call(ctx, executor, JS_UNDEFINED, 2, vc(args)); if (JS_IsException(ret)) { JSValue ret2, error; @@ -50856,17 +54689,16 @@ static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target, ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, vc(&error)); JS_FreeValue(ctx, error); if (JS_IsException(ret2)) - goto fail1; + goto fail; JS_FreeValue(ctx, ret2); } JS_FreeValue(ctx, ret); JS_FreeValue(ctx, args[0]); JS_FreeValue(ctx, args[1]); return obj; - fail1: + fail: JS_FreeValue(ctx, args[0]); JS_FreeValue(ctx, args[1]); - fail: JS_FreeValue(ctx, obj); return JS_EXCEPTION; } @@ -50904,14 +54736,12 @@ static JSValue js_new_promise_capability(JSContext *ctx, JSCFunctionDataRecord *s; int i; + if (JS_IsUndefined(ctor) || js_same_value(ctx, ctor, ctx->promise_ctor)) + return js_promise_new(ctx, JS_UNDEFINED, resolving_funcs); executor = js_promise_executor_new(ctx); if (JS_IsException(executor)) return JS_EXCEPTION; - if (JS_IsUndefined(ctor)) { - result_promise = js_promise_constructor(ctx, ctor, 1, vc(&executor)); - } else { - result_promise = JS_CallConstructor(ctx, ctor, 1, vc(&executor)); - } + result_promise = JS_CallConstructor(ctx, ctor, 1, vc(&executor)); if (JS_IsException(result_promise)) goto fail; s = JS_GetOpaque(executor, JS_CLASS_C_FUNCTION_DATA); @@ -51565,6 +55395,7 @@ static JSValue js_async_from_sync_iterator_unwrap_func_create(JSContext *ctx, static const JSCFunctionListEntry js_async_iterator_proto_funcs[] = { JS_CFUNC_DEF("[Symbol.asyncIterator]", 0, js_iterator_proto_iterator ), + JS_CFUNC_DEF("[Symbol.asyncDispose]", 0, js_async_iterator_proto_dispose ), }; /* AsyncFromSyncIteratorPrototype */ @@ -51763,16 +55594,19 @@ static JSClassShortDef const js_async_class_def[] = { { JS_ATOM_empty_string, js_async_from_sync_iterator_finalizer, js_async_from_sync_iterator_mark }, /* JS_CLASS_ASYNC_FROM_SYNC_ITERATOR */ { JS_ATOM_AsyncGeneratorFunction, js_bytecode_function_finalizer, js_bytecode_function_mark }, /* JS_CLASS_ASYNC_GENERATOR_FUNCTION */ { JS_ATOM_AsyncGenerator, js_async_generator_finalizer, js_async_generator_mark }, /* JS_CLASS_ASYNC_GENERATOR */ + { JS_ATOM_AsyncDisposableStack, js_disposable_stack_finalizer, js_disposable_stack_mark }, /* JS_CLASS_ASYNC_DISPOSABLE_STACK */ }; -void JS_AddIntrinsicPromise(JSContext *ctx) +int JS_AddIntrinsicPromise(JSContext *ctx) { JSRuntime *rt = ctx->rt; JSValue obj1; + JSCFunctionType ft; if (!JS_IsRegisteredClass(rt, JS_CLASS_PROMISE)) { - init_class_range(rt, js_async_class_def, JS_CLASS_PROMISE, - countof(js_async_class_def)); + if (init_class_range(rt, js_async_class_def, JS_CLASS_PROMISE, + countof(js_async_class_def))) + return -1; rt->class_array[JS_CLASS_PROMISE_RESOLVE_FUNCTION].call = js_promise_resolve_function_call; rt->class_array[JS_CLASS_PROMISE_REJECT_FUNCTION].call = js_promise_resolve_function_call; rt->class_array[JS_CLASS_ASYNC_FUNCTION].call = js_async_function_call; @@ -51782,77 +55616,79 @@ void JS_AddIntrinsicPromise(JSContext *ctx) } /* Promise */ - ctx->class_proto[JS_CLASS_PROMISE] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_PROMISE], - js_promise_proto_funcs, - countof(js_promise_proto_funcs)); - obj1 = JS_NewCFunction2(ctx, js_promise_constructor, "Promise", 1, - JS_CFUNC_constructor, 0); - ctx->promise_ctor = js_dup(obj1); - JS_SetPropertyFunctionList(ctx, obj1, - js_promise_funcs, - countof(js_promise_funcs)); - JS_NewGlobalCConstructor2(ctx, obj1, "Promise", - ctx->class_proto[JS_CLASS_PROMISE]); - - /* Used to squelch a -Wcast-function-type warning. */ - JSCFunctionType ft; + obj1 = JS_NewCConstructor(ctx, JS_CLASS_PROMISE, "Promise", + js_promise_constructor, 1, JS_CFUNC_constructor, 0, + JS_UNDEFINED, + js_promise_funcs, countof(js_promise_funcs), + js_promise_proto_funcs, countof(js_promise_proto_funcs), + 0); + if (JS_IsException(obj1)) + return -1; + ctx->promise_ctor = obj1; /* AsyncFunction */ - ctx->class_proto[JS_CLASS_ASYNC_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto); ft.generic_magic = js_function_constructor; - obj1 = JS_NewCFunction3(ctx, ft.generic, - "AsyncFunction", 1, - JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC, - ctx->function_ctor); - JS_SetPropertyFunctionList(ctx, - ctx->class_proto[JS_CLASS_ASYNC_FUNCTION], - js_async_function_proto_funcs, - countof(js_async_function_proto_funcs)); - JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_ASYNC_FUNCTION], - 0, JS_PROP_CONFIGURABLE); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_ASYNC_FUNCTION, "AsyncFunction", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC, + ctx->function_ctor, + NULL, 0, + js_async_function_proto_funcs, countof(js_async_function_proto_funcs), + JS_NEW_CTOR_NO_GLOBAL | JS_NEW_CTOR_READONLY); + if (JS_IsException(obj1)) + return -1; JS_FreeValue(ctx, obj1); /* AsyncIteratorPrototype */ - ctx->async_iterator_proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->async_iterator_proto, - js_async_iterator_proto_funcs, - countof(js_async_iterator_proto_funcs)); + ctx->async_iterator_proto = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_OBJECT], + js_async_iterator_proto_funcs, + countof(js_async_iterator_proto_funcs)); + if (JS_IsException(ctx->async_iterator_proto)) + return -1; /* AsyncFromSyncIteratorPrototype */ ctx->class_proto[JS_CLASS_ASYNC_FROM_SYNC_ITERATOR] = - JS_NewObjectProto(ctx, ctx->async_iterator_proto); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ASYNC_FROM_SYNC_ITERATOR], - js_async_from_sync_iterator_proto_funcs, - countof(js_async_from_sync_iterator_proto_funcs)); + JS_NewObjectProtoList(ctx, ctx->async_iterator_proto, + js_async_from_sync_iterator_proto_funcs, + countof(js_async_from_sync_iterator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ASYNC_FROM_SYNC_ITERATOR])) + return -1; /* AsyncGeneratorPrototype */ ctx->class_proto[JS_CLASS_ASYNC_GENERATOR] = - JS_NewObjectProto(ctx, ctx->async_iterator_proto); - JS_SetPropertyFunctionList(ctx, - ctx->class_proto[JS_CLASS_ASYNC_GENERATOR], - js_async_generator_proto_funcs, - countof(js_async_generator_proto_funcs)); + JS_NewObjectProtoList(ctx, ctx->async_iterator_proto, + js_async_generator_proto_funcs, + countof(js_async_generator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ASYNC_GENERATOR])) + return -1; /* AsyncGeneratorFunction */ - ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION] = - JS_NewObjectProto(ctx, ctx->function_proto); ft.generic_magic = js_function_constructor; - obj1 = JS_NewCFunction3(ctx, ft.generic, - "AsyncGeneratorFunction", 1, - JS_CFUNC_constructor_or_func_magic, - JS_FUNC_ASYNC_GENERATOR, - ctx->function_ctor); - JS_SetPropertyFunctionList(ctx, - ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION], - js_async_generator_function_proto_funcs, - countof(js_async_generator_function_proto_funcs)); - JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION], - ctx->class_proto[JS_CLASS_ASYNC_GENERATOR], - JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE); - JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION], - 0, JS_PROP_CONFIGURABLE); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_ASYNC_GENERATOR_FUNCTION, "AsyncGeneratorFunction", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC_GENERATOR, + ctx->function_ctor, + NULL, 0, + js_async_generator_function_proto_funcs, countof(js_async_generator_function_proto_funcs), + JS_NEW_CTOR_NO_GLOBAL | JS_NEW_CTOR_READONLY); + if (JS_IsException(obj1)) + return -1; JS_FreeValue(ctx, obj1); + + if (JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION], + ctx->class_proto[JS_CLASS_ASYNC_GENERATOR], + JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE)) + return -1; + + /* AsyncDisposableStack */ + ctx->class_proto[JS_CLASS_ASYNC_DISPOSABLE_STACK] = JS_NewObject(ctx); + JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ASYNC_DISPOSABLE_STACK], + js_async_disposable_stack_proto_funcs, + countof(js_async_disposable_stack_proto_funcs)); + JS_NewGlobalCConstructorMagic(ctx, "AsyncDisposableStack", + js_disposable_stack_constructor, 0, + ctx->class_proto[JS_CLASS_ASYNC_DISPOSABLE_STACK], + JS_CLASS_ASYNC_DISPOSABLE_STACK); + return 0; } /* URI handling */ @@ -52144,10 +55980,13 @@ static const JSCFunctionListEntry js_global_funcs[] = { JS_CFUNC_MAGIC_DEF("encodeURIComponent", 1, js_global_encodeURI, 1 ), JS_CFUNC_DEF("escape", 1, js_global_escape ), JS_CFUNC_DEF("unescape", 1, js_global_unescape ), - JS_PROP_DOUBLE_DEF("Infinity", 1.0 / 0.0, 0 ), - JS_PROP_U2D_DEF("NaN", 0x7FF8ull<<48, 0 ), // workaround for msvc + // workarounds for msvc & djgpp where NAN and INFINITY + // are not compile-time expressions + JS_PROP_U2D_DEF("Infinity", 0x7FF0ull<<48, 0 ), + JS_PROP_U2D_DEF("NaN", 0x7FF8ull<<48, 0 ), JS_PROP_UNDEFINED_DEF("undefined", 0 ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "global", JS_PROP_CONFIGURABLE ), + JS_CFUNC_DEF("eval", 1, js_global_eval ), }; /* Date */ @@ -53296,26 +57135,30 @@ bool JS_IsDate(JSValueConst v) return JS_VALUE_GET_OBJ(v)->class_id == JS_CLASS_DATE; } -void JS_AddIntrinsicDate(JSContext *ctx) +int JS_AddIntrinsicDate(JSContext *ctx) { JSValue obj; - /* Date */ - ctx->class_proto[JS_CLASS_DATE] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_DATE], js_date_proto_funcs, - countof(js_date_proto_funcs)); - obj = JS_NewGlobalCConstructor(ctx, "Date", js_date_constructor, 7, - ctx->class_proto[JS_CLASS_DATE]); - JS_SetPropertyFunctionList(ctx, obj, js_date_funcs, countof(js_date_funcs)); + obj = JS_NewCConstructor(ctx, JS_CLASS_DATE, "Date", + js_date_constructor, 7, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_date_funcs, countof(js_date_funcs), + js_date_proto_funcs, countof(js_date_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); + return 0; } /* eval */ -void JS_AddIntrinsicEval(JSContext *ctx) +int JS_AddIntrinsicEval(JSContext *ctx) { #ifndef QJS_DISABLE_PARSER ctx->eval_internal = __JS_EvalInternal; #endif // QJS_DISABLE_PARSER + return 0; } /* BigInt */ @@ -53353,6 +57196,7 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val) } break; case JS_TAG_STRING: + case JS_TAG_STRING_ROPE: val = JS_StringToBigIntErr(ctx, val); break; case JS_TAG_OBJECT: @@ -53498,40 +57342,63 @@ static const JSCFunctionListEntry js_bigint_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "BigInt", JS_PROP_CONFIGURABLE ), }; -void JS_AddIntrinsicBigInt(JSContext *ctx) +int JS_AddIntrinsicBigInt(JSContext *ctx) { JSValue obj1; - ctx->class_proto[JS_CLASS_BIG_INT] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_INT], - js_bigint_proto_funcs, - countof(js_bigint_proto_funcs)); - obj1 = JS_NewGlobalCConstructor(ctx, "BigInt", js_bigint_constructor, 1, - ctx->class_proto[JS_CLASS_BIG_INT]); - JS_SetPropertyFunctionList(ctx, obj1, js_bigint_funcs, - countof(js_bigint_funcs)); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_BIG_INT, "BigInt", + js_bigint_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_bigint_funcs, countof(js_bigint_funcs), + js_bigint_proto_funcs, countof(js_bigint_proto_funcs), + 0); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + return 0; } static const char * const native_error_name[JS_NATIVE_ERROR_COUNT] = { "EvalError", "RangeError", "ReferenceError", "SyntaxError", "TypeError", "URIError", "InternalError", "AggregateError", + "SuppressedError", }; /* Minimum amount of objects to be able to compile code and display error messages. No JSAtom should be allocated by this function. */ -static void JS_AddIntrinsicBasicObjects(JSContext *ctx) +/* Minimum amount of objects to be able to compile code and display + error messages. */ +static int JS_AddIntrinsicBasicObjects(JSContext *ctx) { JSValue proto; int i; - ctx->class_proto[JS_CLASS_OBJECT] = JS_NewObjectProto(ctx, JS_NULL); - ctx->global_obj = JS_NewObject(ctx); - ctx->global_var_obj = JS_NewObjectProto(ctx, JS_NULL); + /* warning: ordering is tricky */ + ctx->class_proto[JS_CLASS_OBJECT] = + JS_NewObjectProtoClassAlloc(ctx, JS_NULL, JS_CLASS_OBJECT, + countof(js_object_proto_funcs) + 1); + if (JS_IsException(ctx->class_proto[JS_CLASS_OBJECT])) + return -1; + + /* 2 more properties: caller and arguments */ ctx->function_proto = JS_NewCFunction3(ctx, js_function_proto, "", 0, JS_CFUNC_generic, 0, - ctx->class_proto[JS_CLASS_OBJECT]); + ctx->class_proto[JS_CLASS_OBJECT], + countof(js_function_proto_funcs) + 3 + 2); + if (JS_IsException(ctx->function_proto)) + return -1; ctx->class_proto[JS_CLASS_BYTECODE_FUNCTION] = js_dup(ctx->function_proto); + + ctx->global_obj = JS_NewObjectProtoClassAlloc(ctx, ctx->class_proto[JS_CLASS_OBJECT], + JS_CLASS_OBJECT, 64); + if (JS_IsException(ctx->global_obj)) + return -1; + ctx->global_var_obj = JS_NewObjectProtoClassAlloc(ctx, JS_NULL, + JS_CLASS_OBJECT, 16); + if (JS_IsException(ctx->global_var_obj)) + return -1; + ctx->class_proto[JS_CLASS_ERROR] = JS_NewObject(ctx); JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ERROR], js_error_proto_funcs, @@ -53552,266 +57419,329 @@ static void JS_AddIntrinsicBasicObjects(JSContext *ctx) ctx->class_proto[JS_CLASS_ARRAY] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], JS_CLASS_ARRAY); + ctx->std_array_prototype = true; - ctx->array_shape = js_new_shape2(ctx, get_proto_obj(ctx->class_proto[JS_CLASS_ARRAY]), - JS_PROP_INITIAL_HASH_SIZE, 1); - add_shape_property(ctx, &ctx->array_shape, NULL, - JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_LENGTH); + static const JSShapeProperty array_props[] = { + {.atom=JS_ATOM_length, .flags=JS_PROP_WRITABLE|JS_PROP_LENGTH}, + }; + static const JSShapeProperty arguments_props[] = { + {.atom=JS_ATOM_length, .flags=JS_PROP_WRITABLE|JS_PROP_CONFIGURABLE}, + {.atom=JS_ATOM_Symbol_iterator, .flags=JS_PROP_WRITABLE|JS_PROP_CONFIGURABLE}, + {.atom=JS_ATOM_callee, .flags=JS_PROP_GETSET}, + }; + static const JSShapeProperty mapped_arguments_props[] = { + {.atom=JS_ATOM_length, .flags=JS_PROP_WRITABLE|JS_PROP_CONFIGURABLE}, + {.atom=JS_ATOM_Symbol_iterator, .flags=JS_PROP_WRITABLE|JS_PROP_CONFIGURABLE}, + {.atom=JS_ATOM_callee, .flags=JS_PROP_WRITABLE|JS_PROP_CONFIGURABLE}, + }; + if (js_new_shape_with(ctx, &ctx->array_shape, + ctx->class_proto[JS_CLASS_ARRAY], + countof(array_props), array_props)) { + return -1; + } + if (js_new_shape_with(ctx, &ctx->arguments_shape, + ctx->class_proto[JS_CLASS_OBJECT], + countof(arguments_props), arguments_props)) { + return -1; + } + if (js_new_shape_with(ctx, &ctx->mapped_arguments_shape, + ctx->class_proto[JS_CLASS_OBJECT], + countof(mapped_arguments_props), mapped_arguments_props)) { + return -1; + } - /* XXX: could test it on first context creation to ensure that no - new atoms are created in JS_AddIntrinsicBasicObjects(). It is - necessary to avoid useless renumbering of atoms after - JS_EvalBinary() if it is done just after - JS_AddIntrinsicBasicObjects(). */ - // assert(ctx->rt->atom_count == JS_ATOM_END); + return 0; } -void JS_AddIntrinsicBaseObjects(JSContext *ctx) +int JS_AddIntrinsicBaseObjects(JSContext *ctx) { - int i; - JSValue obj, number_obj; - JSValue obj1; + JSValue obj1, obj2; + JSCFunctionType ft; ctx->throw_type_error = JS_NewCFunction(ctx, js_throw_type_error, NULL, 0); - + if (JS_IsException(ctx->throw_type_error)) + return -1; /* add caller and arguments properties to throw a TypeError */ - JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_caller, JS_UNDEFINED, - ctx->throw_type_error, ctx->throw_type_error, - JS_PROP_HAS_GET | JS_PROP_HAS_SET | - JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE); - JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_arguments, JS_UNDEFINED, - ctx->throw_type_error, ctx->throw_type_error, - JS_PROP_HAS_GET | JS_PROP_HAS_SET | - JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE); + if (JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_caller, JS_UNDEFINED, + ctx->throw_type_error, ctx->throw_type_error, + JS_PROP_HAS_GET | JS_PROP_HAS_SET | + JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE) < 0) + return -1; + if (JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_arguments, JS_UNDEFINED, + ctx->throw_type_error, ctx->throw_type_error, + JS_PROP_HAS_GET | JS_PROP_HAS_SET | + JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE) < 0) + return -1; JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, vc(&ctx->throw_type_error), 1)); /* Object */ - obj = JS_NewGlobalCConstructor(ctx, "Object", js_object_constructor, 1, - ctx->class_proto[JS_CLASS_OBJECT]); - JS_SetPropertyFunctionList(ctx, obj, js_object_funcs, countof(js_object_funcs)); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_OBJECT], - js_object_proto_funcs, countof(js_object_proto_funcs)); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_OBJECT, "Object", + js_object_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_object_funcs, countof(js_object_funcs), + js_object_proto_funcs, countof(js_object_proto_funcs), + JS_NEW_CTOR_PROTO_EXIST); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); /* Function */ - JS_SetPropertyFunctionList(ctx, ctx->function_proto, js_function_proto_funcs, countof(js_function_proto_funcs)); - ctx->function_ctor = JS_NewCFunctionMagic(ctx, js_function_constructor, - "Function", 1, JS_CFUNC_constructor_or_func_magic, - JS_FUNC_NORMAL); - JS_NewGlobalCConstructor2(ctx, js_dup(ctx->function_ctor), "Function", - ctx->function_proto); + ft.generic_magic = js_function_constructor; + obj1 = JS_NewCConstructor(ctx, JS_CLASS_BYTECODE_FUNCTION, "Function", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_NORMAL, + JS_UNDEFINED, + NULL, 0, + js_function_proto_funcs, countof(js_function_proto_funcs), + JS_NEW_CTOR_PROTO_EXIST); + if (JS_IsException(obj1)) + return -1; + ctx->function_ctor = obj1; /* Error */ + ft.generic_magic = js_error_constructor; ctx->error_ctor = JS_NewCFunctionMagic(ctx, js_error_constructor, "Error", 1, JS_CFUNC_constructor_or_func_magic, -1); + if (JS_IsException(ctx->error_ctor)) + return -1; JS_NewGlobalCConstructor2(ctx, js_dup(ctx->error_ctor), "Error", ctx->class_proto[JS_CLASS_ERROR]); - JS_SetPropertyFunctionList(ctx, ctx->error_ctor, js_error_funcs, countof(js_error_funcs)); + if (JS_SetPropertyFunctionList(ctx, ctx->error_ctor, js_error_funcs, countof(js_error_funcs))) + return -1; - /* Used to squelch a -Wcast-function-type warning. */ - JSCFunctionType ft = { .generic_magic = js_error_constructor }; - for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { + for(int i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { JSValue func_obj; int n_args; - n_args = 1 + (i == JS_AGGREGATE_ERROR); + switch (i) { + case JS_AGGREGATE_ERROR: + n_args = 2; + break; + case JS_SUPPRESSED_ERROR: + n_args = 3; + break; + default: + n_args = 1; + } func_obj = JS_NewCFunction3(ctx, ft.generic, native_error_name[i], n_args, JS_CFUNC_constructor_or_func_magic, i, - ctx->error_ctor); + ctx->error_ctor, 0); + if (JS_IsException(func_obj)) + return -1; JS_NewGlobalCConstructor2(ctx, func_obj, native_error_name[i], ctx->native_error_proto[i]); } /* CallSite */ - _JS_AddIntrinsicCallSite(ctx); + if (_JS_AddIntrinsicCallSite(ctx)) + return -1; /* Iterator */ - ctx->class_proto[JS_CLASS_ITERATOR] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], - js_iterator_proto_funcs, - countof(js_iterator_proto_funcs)); - obj = JS_NewGlobalCConstructor(ctx, "Iterator", js_iterator_constructor, 0, - ctx->class_proto[JS_CLASS_ITERATOR]); + obj2 = JS_NewCConstructor(ctx, JS_CLASS_ITERATOR, "Iterator", + js_iterator_constructor, 0, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_iterator_funcs, countof(js_iterator_funcs), + js_iterator_proto_funcs, countof(js_iterator_proto_funcs), + 0); + if (JS_IsException(obj2)) + return -1; // quirk: Iterator.prototype.constructor is an accessor property - // TODO(bnoordhuis) mildly inefficient because JS_NewGlobalCConstructor + // TODO(bnoordhuis) mildly inefficient because JS_NewCConstructor // first creates a .constructor value property that we then replace with // an accessor - ctx->iterator_ctor_getset = JS_NewCFunctionData(ctx, js_iterator_constructor_getset, - 0, 0, 1, vc(&obj)); - JS_DefineProperty(ctx, ctx->class_proto[JS_CLASS_ITERATOR], - JS_ATOM_constructor, JS_UNDEFINED, - ctx->iterator_ctor_getset, ctx->iterator_ctor_getset, - JS_PROP_HAS_GET|JS_PROP_HAS_SET|JS_PROP_WRITABLE|JS_PROP_CONFIGURABLE); - ctx->iterator_ctor = js_dup(obj); - JS_SetPropertyFunctionList(ctx, obj, - js_iterator_funcs, - countof(js_iterator_funcs)); - - ctx->class_proto[JS_CLASS_ITERATOR_CONCAT] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_CONCAT], - js_iterator_concat_proto_funcs, - countof(js_iterator_concat_proto_funcs)); - - ctx->class_proto[JS_CLASS_ITERATOR_HELPER] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_HELPER], - js_iterator_helper_proto_funcs, - countof(js_iterator_helper_proto_funcs)); - - ctx->class_proto[JS_CLASS_ITERATOR_WRAP] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_WRAP], - js_iterator_wrap_proto_funcs, - countof(js_iterator_wrap_proto_funcs)); + obj1 = JS_NewCFunctionData(ctx, js_iterator_constructor_getset, + 0, 0, 1, vc(&obj2)); + if (JS_IsException(obj1)) { + JS_FreeValue(ctx, obj2); + return -1; + } + ctx->iterator_ctor_getset = js_dup(obj1); + if (JS_DefineProperty(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + JS_ATOM_constructor, JS_UNDEFINED, + obj1, obj1, + JS_PROP_HAS_GET | JS_PROP_HAS_SET | JS_PROP_CONFIGURABLE) < 0) { + JS_FreeValue(ctx, obj2); + JS_FreeValue(ctx, obj1); + return -1; + } + JS_FreeValue(ctx, obj1); + ctx->iterator_ctor = obj2; + JS_DefineAutoInitProperty(ctx, obj2, JS_ATOM_zip, JS_AUTOINIT_ID_BYTECODE, + (void *)(uintptr_t)JS_BUILTIN_ITERATOR_ZIP, + JS_PROP_WRITABLE|JS_PROP_CONFIGURABLE); + JS_DefineAutoInitProperty(ctx, obj2, JS_ATOM_zipKeyed, JS_AUTOINIT_ID_BYTECODE, + (void *)(uintptr_t)JS_BUILTIN_ITERATOR_ZIP_KEYED, + JS_PROP_WRITABLE|JS_PROP_CONFIGURABLE); + + ctx->class_proto[JS_CLASS_ITERATOR_CONCAT] = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_iterator_concat_proto_funcs, + countof(js_iterator_concat_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ITERATOR_CONCAT])) + return -1; + + ctx->class_proto[JS_CLASS_ITERATOR_HELPER] = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_iterator_helper_proto_funcs, + countof(js_iterator_helper_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ITERATOR_HELPER])) + return -1; + + ctx->class_proto[JS_CLASS_ITERATOR_WRAP] = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_iterator_wrap_proto_funcs, + countof(js_iterator_wrap_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ITERATOR_WRAP])) + return -1; /* Array */ - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY], - js_array_proto_funcs, - countof(js_array_proto_funcs)); - - obj = JS_NewGlobalCConstructor(ctx, "Array", js_array_constructor, 1, - ctx->class_proto[JS_CLASS_ARRAY]); - ctx->array_ctor = js_dup(obj); - JS_SetPropertyFunctionList(ctx, obj, js_array_funcs, - countof(js_array_funcs)); - JS_DefineAutoInitProperty(ctx, obj, JS_ATOM_fromAsync, + obj1 = JS_NewCConstructor(ctx, JS_CLASS_ARRAY, "Array", + js_array_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_array_funcs, countof(js_array_funcs), + js_array_proto_funcs, countof(js_array_proto_funcs), + JS_NEW_CTOR_PROTO_EXIST); + if (JS_IsException(obj1)) + return -1; + ctx->array_ctor = obj1; + JS_DefineAutoInitProperty(ctx, obj1, JS_ATOM_fromAsync, JS_AUTOINIT_ID_BYTECODE, (void *)(uintptr_t)JS_BUILTIN_ARRAY_FROMASYNC, JS_PROP_WRITABLE|JS_PROP_CONFIGURABLE); - /* XXX: create auto_initializer */ - { - /* initialize Array.prototype[Symbol.unscopables] */ - static const char unscopables[] = - "copyWithin" "\0" - "entries" "\0" - "fill" "\0" - "find" "\0" - "findIndex" "\0" - "findLast" "\0" - "findLastIndex" "\0" - "flat" "\0" - "flatMap" "\0" - "includes" "\0" - "keys" "\0" - "toReversed" "\0" - "toSorted" "\0" - "toSpliced" "\0" - "values" "\0"; - const char *p = unscopables; - obj1 = JS_NewObjectProto(ctx, JS_NULL); - for(p = unscopables; *p; p += strlen(p) + 1) { - JS_DefinePropertyValueStr(ctx, obj1, p, JS_TRUE, JS_PROP_C_W_E); - } - JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ARRAY], - JS_ATOM_Symbol_unscopables, obj1, - JS_PROP_CONFIGURABLE); - } - /* needed to initialize arguments[Symbol.iterator] */ ctx->array_proto_values = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_values); + if (JS_IsException(ctx->array_proto_values)) + return -1; - ctx->class_proto[JS_CLASS_ARRAY_ITERATOR] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY_ITERATOR], - js_array_iterator_proto_funcs, - countof(js_array_iterator_proto_funcs)); + ctx->class_proto[JS_CLASS_ARRAY_ITERATOR] = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_array_iterator_proto_funcs, + countof(js_array_iterator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_ARRAY_ITERATOR])) + return -1; /* parseFloat and parseInteger must be defined before Number because of the Number.parseFloat and Number.parseInteger aliases */ - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_global_funcs, - countof(js_global_funcs)); + if (JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_global_funcs, + countof(js_global_funcs))) + return -1; /* Number */ - ctx->class_proto[JS_CLASS_NUMBER] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], - JS_CLASS_NUMBER); - JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_NUMBER], js_int32(0)); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_NUMBER], - js_number_proto_funcs, - countof(js_number_proto_funcs)); - number_obj = JS_NewGlobalCConstructor(ctx, "Number", js_number_constructor, 1, - ctx->class_proto[JS_CLASS_NUMBER]); - JS_SetPropertyFunctionList(ctx, number_obj, js_number_funcs, countof(js_number_funcs)); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_NUMBER, "Number", + js_number_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_number_funcs, countof(js_number_funcs), + js_number_proto_funcs, countof(js_number_proto_funcs), + JS_NEW_CTOR_PROTO_CLASS); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + if (JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_NUMBER], js_int32(0))) + return -1; /* Boolean */ - ctx->class_proto[JS_CLASS_BOOLEAN] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], - JS_CLASS_BOOLEAN); - JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], JS_FALSE); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], js_boolean_proto_funcs, - countof(js_boolean_proto_funcs)); - JS_NewGlobalCConstructor(ctx, "Boolean", js_boolean_constructor, 1, - ctx->class_proto[JS_CLASS_BOOLEAN]); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_BOOLEAN, "Boolean", + js_boolean_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + NULL, 0, + js_boolean_proto_funcs, countof(js_boolean_proto_funcs), + JS_NEW_CTOR_PROTO_CLASS); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + if (JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], JS_FALSE)) + return -1; /* String */ - ctx->class_proto[JS_CLASS_STRING] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], - JS_CLASS_STRING); - JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_STRING], js_empty_string(ctx->rt)); - obj = JS_NewGlobalCConstructor(ctx, "String", js_string_constructor, 1, - ctx->class_proto[JS_CLASS_STRING]); - JS_SetPropertyFunctionList(ctx, obj, js_string_funcs, - countof(js_string_funcs)); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_funcs, - countof(js_string_proto_funcs)); - - ctx->class_proto[JS_CLASS_STRING_ITERATOR] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING_ITERATOR], - js_string_iterator_proto_funcs, - countof(js_string_iterator_proto_funcs)); + obj1 = JS_NewCConstructor(ctx, JS_CLASS_STRING, "String", + js_string_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_string_funcs, countof(js_string_funcs), + js_string_proto_funcs, countof(js_string_proto_funcs), + JS_NEW_CTOR_PROTO_CLASS); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); + if (JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_STRING], js_empty_string(ctx->rt))) + return -1; + + ctx->class_proto[JS_CLASS_STRING_ITERATOR] = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_string_iterator_proto_funcs, + countof(js_string_iterator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_STRING_ITERATOR])) + return -1; /* Math: create as autoinit object */ js_random_init(ctx); - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_math_obj, countof(js_math_obj)); + if (JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_math_obj, countof(js_math_obj))) + return -1; /* ES6 Reflect: create as autoinit object */ - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_reflect_obj, countof(js_reflect_obj)); + if (JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_reflect_obj, countof(js_reflect_obj))) + return -1; /* ES6 Symbol */ - ctx->class_proto[JS_CLASS_SYMBOL] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_SYMBOL], js_symbol_proto_funcs, - countof(js_symbol_proto_funcs)); - obj = JS_NewGlobalCConstructor(ctx, "Symbol", js_symbol_constructor, 0, - ctx->class_proto[JS_CLASS_SYMBOL]); - JS_SetPropertyFunctionList(ctx, obj, js_symbol_funcs, - countof(js_symbol_funcs)); - for(i = JS_ATOM_Symbol_toPrimitive; i < JS_ATOM_END; i++) { - char buf[ATOM_GET_STR_BUF_SIZE]; - const char *str, *p; - str = JS_AtomGetStr(ctx, buf, sizeof(buf), i); - /* skip "Symbol." */ - p = strchr(str, '.'); - if (p) - str = p + 1; - JS_DefinePropertyValueStr(ctx, obj, str, JS_AtomToValue(ctx, i), 0); - } + obj1 = JS_NewCConstructor(ctx, JS_CLASS_SYMBOL, "Symbol", + js_symbol_constructor, 0, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_symbol_funcs, countof(js_symbol_funcs), + js_symbol_proto_funcs, countof(js_symbol_proto_funcs), + 0); + if (JS_IsException(obj1)) + return -1; + JS_FreeValue(ctx, obj1); /* ES6 Generator */ - ctx->class_proto[JS_CLASS_GENERATOR] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_GENERATOR], - js_generator_proto_funcs, - countof(js_generator_proto_funcs)); - - ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto); - obj1 = JS_NewCFunctionMagic(ctx, js_function_constructor, - "GeneratorFunction", 1, - JS_CFUNC_constructor_or_func_magic, JS_FUNC_GENERATOR); - JS_SetPropertyFunctionList(ctx, - ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION], - js_generator_function_proto_funcs, - countof(js_generator_function_proto_funcs)); - JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION], - ctx->class_proto[JS_CLASS_GENERATOR], - JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE); - JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION], - 0, JS_PROP_CONFIGURABLE); + ctx->class_proto[JS_CLASS_GENERATOR] = + JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + js_generator_proto_funcs, + countof(js_generator_proto_funcs)); + if (JS_IsException(ctx->class_proto[JS_CLASS_GENERATOR])) + return -1; + + ft.generic_magic = js_function_constructor; + obj1 = JS_NewCConstructor(ctx, JS_CLASS_GENERATOR_FUNCTION, "GeneratorFunction", + ft.generic, 1, JS_CFUNC_constructor_or_func_magic, JS_FUNC_GENERATOR, + ctx->function_ctor, + NULL, 0, + js_generator_function_proto_funcs, + countof(js_generator_function_proto_funcs), + JS_NEW_CTOR_NO_GLOBAL | JS_NEW_CTOR_READONLY); + if (JS_IsException(obj1)) + return -1; JS_FreeValue(ctx, obj1); + if (JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION], + ctx->class_proto[JS_CLASS_GENERATOR], + JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE)) + return -1; + + /* explicit resource management */ + ctx->class_proto[JS_CLASS_DISPOSABLE_STACK] = JS_NewObject(ctx); + JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_DISPOSABLE_STACK], + js_disposable_stack_proto_funcs, + countof(js_disposable_stack_proto_funcs)); + JS_NewGlobalCConstructorMagic(ctx, "DisposableStack", + js_disposable_stack_constructor, 0, + ctx->class_proto[JS_CLASS_DISPOSABLE_STACK], + JS_CLASS_DISPOSABLE_STACK); /* global properties */ - ctx->eval_obj = JS_NewCFunction(ctx, js_global_eval, "eval", 1); - JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_eval, - js_dup(ctx->eval_obj), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + ctx->eval_obj = JS_GetProperty(ctx, ctx->global_obj, JS_ATOM_eval); + if (JS_IsException(ctx->eval_obj)) + return -1; + + if (JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis, + js_dup(ctx->global_obj), + JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE) < 0) + return -1; - JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis, - js_dup(ctx->global_obj), - JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); + /* BigInt */ + if (JS_AddIntrinsicBigInt(ctx)) + return -1; + return 0; } /* Typed Arrays */ @@ -53854,6 +57784,13 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, JS_ThrowRangeError(ctx, "invalid max array buffer length"); goto fail; } + if (alloc_flag && class_id == JS_CLASS_SHARED_ARRAY_BUFFER && max_len && + *max_len > len && !rt->sab_funcs.sab_alloc) { + JS_ThrowTypeError(ctx, + "growable SharedArrayBuffer requires " + "SAB allocator hooks"); + goto fail; + } abuf = js_malloc(ctx, sizeof(*abuf)); if (!abuf) goto fail; @@ -53881,10 +57818,18 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, rt->sab_funcs.sab_dup) { rt->sab_funcs.sab_dup(rt->sab_funcs.sab_opaque, buf); } - abuf->data = buf; + if (buf) { + abuf->data = buf; + } else { + abuf->data = js_mallocz(ctx, 1); + if (!abuf->data) + goto fail; + free_func = js_array_buffer_free; + } } init_list_head(&abuf->array_list); abuf->detached = false; + abuf->immutable = false; abuf->shared = (class_id == JS_CLASS_SHARED_ARRAY_BUFFER); abuf->opaque = opaque; abuf->free_func = free_func; @@ -54054,6 +57999,11 @@ static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx) return JS_ThrowTypeError(ctx, "ArrayBuffer is detached"); } +static JSValue JS_ThrowTypeErrorImmutableArrayBuffer(JSContext *ctx) +{ + return JS_ThrowTypeError(ctx, "ArrayBuffer is immutable"); +} + static JSValue JS_ThrowTypeErrorArrayBufferOOB(JSContext *ctx) { return JS_ThrowTypeError(ctx, "ArrayBuffer is detached or resized"); @@ -54071,6 +58021,15 @@ static JSValue js_array_buffer_get_detached(JSContext *ctx, return js_bool(abuf->detached); } +static JSValue js_array_buffer_get_immutable(JSContext *ctx, + JSValueConst this_val) +{ + JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, JS_CLASS_ARRAY_BUFFER); + if (!abuf) + return JS_EXCEPTION; + return js_bool(abuf->immutable); +} + static JSValue js_array_buffer_get_byteLength(JSContext *ctx, JSValueConst this_val, int class_id) @@ -54131,6 +58090,23 @@ void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj) } } +int JS_IsImmutableArrayBuffer(JSValueConst obj) +{ + JSArrayBuffer *abuf = JS_GetOpaque(obj, JS_CLASS_ARRAY_BUFFER); + if (!abuf) + return -1; + return abuf->immutable; +} + +int JS_SetImmutableArrayBuffer(JSValueConst obj, bool immutable) +{ + JSArrayBuffer *abuf = JS_GetOpaque(obj, JS_CLASS_ARRAY_BUFFER); + if (!abuf) + return -1; + abuf->immutable = immutable; + return 0; +} + /* get an ArrayBuffer or SharedArrayBuffer */ static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj) { @@ -54207,28 +58183,38 @@ static void js_array_buffer_update_typed_arrays(JSArrayBuffer *abuf) } } +enum { + JS_ARRAY_BUFFER_TRANSFER, + JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE, + JS_ARRAY_BUFFER_TRANSFER_TO_FIXED_LENGTH, +}; + // ES #sec-arraybuffer.prototype.transfer static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { - bool transfer_to_fixed_length = magic & 1; JSArrayBuffer *abuf; uint64_t new_len, old_len, max_len, *pmax_len; uint8_t *bs, *new_bs; + JSValue ret; abuf = JS_GetOpaque2(ctx, this_val, JS_CLASS_ARRAY_BUFFER); if (!abuf) return JS_EXCEPTION; if (abuf->shared) return JS_ThrowTypeError(ctx, "cannot transfer a SharedArrayBuffer"); + if (magic == JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE && abuf->immutable) + return JS_ThrowTypeErrorImmutableArrayBuffer(ctx); if (argc < 1 || JS_IsUndefined(argv[0])) new_len = abuf->byte_length; else if (JS_ToIndex(ctx, &new_len, argv[0])) return JS_EXCEPTION; + if (magic != JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE && abuf->immutable) + return JS_ThrowTypeErrorImmutableArrayBuffer(ctx); if (abuf->detached) return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); pmax_len = NULL; - if (!transfer_to_fixed_length) { + if (magic == JS_ARRAY_BUFFER_TRANSFER) { if (array_buffer_is_resizable(abuf)) { // carry over maxByteLength max_len = abuf->max_byte_length; if (new_len > max_len) @@ -54241,8 +58227,9 @@ static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val, /* create an empty AB */ if (new_len == 0) { JS_DetachArrayBuffer(ctx, this_val); - return js_array_buffer_constructor2(ctx, JS_UNDEFINED, 0, pmax_len, - JS_CLASS_ARRAY_BUFFER); + ret = js_array_buffer_constructor2(ctx, JS_UNDEFINED, 0, pmax_len, + JS_CLASS_ARRAY_BUFFER); + goto fini; } bs = abuf->data; old_len = abuf->byte_length; @@ -54260,10 +58247,20 @@ static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val, abuf->byte_length = 0; abuf->detached = true; js_array_buffer_update_typed_arrays(abuf); - return js_array_buffer_constructor3(ctx, JS_UNDEFINED, new_len, pmax_len, - JS_CLASS_ARRAY_BUFFER, - bs, abuf->free_func, - NULL, false); + ret = js_array_buffer_constructor3(ctx, JS_UNDEFINED, new_len, pmax_len, + JS_CLASS_ARRAY_BUFFER, bs, + abuf->free_func, NULL, + /*alloc_flag*/false); +fini: + if (magic == JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE) { + if (JS_IsException(ret)) + return JS_EXCEPTION; + abuf = JS_GetOpaque2(ctx, ret, JS_CLASS_ARRAY_BUFFER); + if (!abuf) + return JS_EXCEPTION; + abuf->immutable = true; + } + return ret; } static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val, @@ -54276,6 +58273,8 @@ static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val, abuf = JS_GetOpaque2(ctx, this_val, class_id); if (!abuf) return JS_EXCEPTION; + if (abuf->immutable) + return JS_ThrowTypeErrorImmutableArrayBuffer(ctx); if (JS_ToInt64(ctx, &len, argv[0])) return JS_EXCEPTION; if (abuf->detached) @@ -54318,17 +58317,23 @@ static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val, static JSValue js_array_buffer_slice(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int class_id) + int argc, JSValueConst *argv, int magic) { JSArrayBuffer *abuf, *new_abuf; int64_t len, start, end, new_len; JSValue ctor, new_obj; + bool immutable; + int class_id; + immutable = magic & 1; + class_id = magic >> 1; abuf = JS_GetOpaque2(ctx, this_val, class_id); if (!abuf) return JS_EXCEPTION; if (abuf->detached) return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + if (abuf->immutable) + return JS_ThrowTypeErrorImmutableArrayBuffer(ctx); len = abuf->byte_length; if (JS_ToInt64Clamp(ctx, &start, argv[0], 0, len, len)) @@ -54340,9 +58345,15 @@ static JSValue js_array_buffer_slice(JSContext *ctx, return JS_EXCEPTION; } new_len = max_int64(end - start, 0); - ctor = JS_SpeciesConstructor(ctx, this_val, JS_UNDEFINED); - if (JS_IsException(ctor)) - return ctor; + // note: difference between slice and sliceToImmutable is that the + // latter does not have this step: + // 1. Let _ctor_ be ? SpeciesConstructor(_O_, %ArrayBuffer%) + ctor = JS_UNDEFINED; + if (!immutable) { + ctor = JS_SpeciesConstructor(ctx, this_val, JS_UNDEFINED); + if (JS_IsException(ctor)) + return ctor; + } if (JS_IsUndefined(ctor)) { new_obj = js_array_buffer_constructor2(ctx, JS_UNDEFINED, new_len, NULL, class_id); @@ -54358,6 +58369,10 @@ static JSValue js_array_buffer_slice(JSContext *ctx, new_abuf = JS_GetOpaque2(ctx, new_obj, class_id); if (!new_abuf) goto fail; + if (new_abuf->immutable) { + JS_ThrowTypeErrorImmutableArrayBuffer(ctx); + goto fail; + } if (js_same_value(ctx, new_obj, this_val)) { JS_ThrowTypeError(ctx, "cannot use identical ArrayBuffer"); goto fail; @@ -54376,6 +58391,7 @@ static JSValue js_array_buffer_slice(JSContext *ctx, goto fail; } memcpy(new_abuf->data, abuf->data + start, new_len); + new_abuf->immutable = immutable; return new_obj; fail: JS_FreeValue(ctx, new_obj); @@ -54387,10 +58403,13 @@ static const JSCFunctionListEntry js_array_buffer_proto_funcs[] = { JS_CGETSET_MAGIC_DEF("maxByteLength", js_array_buffer_get_maxByteLength, NULL, JS_CLASS_ARRAY_BUFFER ), JS_CGETSET_MAGIC_DEF("resizable", js_array_buffer_get_resizable, NULL, JS_CLASS_ARRAY_BUFFER ), JS_CGETSET_DEF("detached", js_array_buffer_get_detached, NULL ), + JS_CGETSET_DEF("immutable", js_array_buffer_get_immutable, NULL ), JS_CFUNC_MAGIC_DEF("resize", 1, js_array_buffer_resize, JS_CLASS_ARRAY_BUFFER ), - JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_ARRAY_BUFFER ), - JS_CFUNC_MAGIC_DEF("transfer", 0, js_array_buffer_transfer, 0 ), - JS_CFUNC_MAGIC_DEF("transferToFixedLength", 0, js_array_buffer_transfer, 1 ), + JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_ARRAY_BUFFER*2 + /*immutable*/0 ), + JS_CFUNC_MAGIC_DEF("sliceToImmutable", 2, js_array_buffer_slice, JS_CLASS_ARRAY_BUFFER*2 + /*immutable*/1 ), + JS_CFUNC_MAGIC_DEF("transfer", 0, js_array_buffer_transfer, JS_ARRAY_BUFFER_TRANSFER ), + JS_CFUNC_MAGIC_DEF("transferToImmutable", 0, js_array_buffer_transfer, JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE ), + JS_CFUNC_MAGIC_DEF("transferToFixedLength", 0, js_array_buffer_transfer, JS_ARRAY_BUFFER_TRANSFER_TO_FIXED_LENGTH ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "ArrayBuffer", JS_PROP_CONFIGURABLE ), }; @@ -54405,7 +58424,7 @@ static const JSCFunctionListEntry js_shared_array_buffer_proto_funcs[] = { JS_CGETSET_MAGIC_DEF("maxByteLength", js_array_buffer_get_maxByteLength, NULL, JS_CLASS_SHARED_ARRAY_BUFFER ), JS_CGETSET_MAGIC_DEF("growable", js_array_buffer_get_resizable, NULL, JS_CLASS_SHARED_ARRAY_BUFFER ), JS_CFUNC_MAGIC_DEF("grow", 1, js_array_buffer_resize, JS_CLASS_SHARED_ARRAY_BUFFER ), - JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_SHARED_ARRAY_BUFFER ), + JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_SHARED_ARRAY_BUFFER*2 + /*immutable*/0 ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "SharedArrayBuffer", JS_PROP_CONFIGURABLE ), }; @@ -54414,6 +58433,18 @@ static bool is_typed_array(JSClassID class_id) return class_id >= JS_CLASS_UINT8C_ARRAY && class_id <= JS_CLASS_FLOAT64_ARRAY; } +// |p| must be a typed array, *not* a DataView +static bool typed_array_is_immutable(JSObject *p) +{ + JSArrayBuffer *abuf; + JSTypedArray *ta; + + assert(is_typed_array(p->class_id)); + ta = p->u.typed_array; + abuf = ta->buffer->u.array_buffer; + return abuf->immutable; +} + // is the typed array detached or out of bounds relative to its RAB? // |p| must be a typed array, *not* a DataView static bool typed_array_is_oob(JSObject *p) @@ -54604,6 +58635,10 @@ static JSValue js_typed_array_set_internal(JSContext *ctx, p = get_typed_array(ctx, dst); if (!p) goto fail; + if (typed_array_is_immutable(p)) { + JS_ThrowTypeErrorImmutableArrayBuffer(ctx); + goto fail; + } if (JS_ToInt64Sat(ctx, &offset, off)) goto fail; if (offset < 0) @@ -54732,39 +58767,79 @@ static JSValue js_typed_array_at(JSContext *ctx, JSValueConst this_val, static JSValue js_typed_array_with(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSValue arr, val; + JSValue arr, val, buffer; JSObject *p; + JSTypedArray *ta; + JSArrayBuffer *src_abuf, *abuf; int64_t idx; - uint32_t len, oldlen, newlen; + uint32_t len, newlen, copy_len; + int size_log2; p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; - oldlen = p->u.array.count; + len = p->u.array.count; if (JS_ToInt64Sat(ctx, &idx, argv[0])) return JS_EXCEPTION; + /* resolve negative index using original length (spec step 5-6) */ + if (idx < 0) + idx = len + idx; val = JS_ToPrimitive(ctx, argv[1], HINT_NUMBER); if (JS_IsException(val)) return JS_EXCEPTION; + /* re-validate after user code (spec step 9: IsValidIntegerIndex) */ + if (typed_array_is_oob(p)) { + JS_FreeValue(ctx, val); + return JS_ThrowTypeErrorArrayBufferOOB(ctx); + } newlen = p->u.array.count; - if (idx < 0) - idx = newlen + idx; if (idx < 0 || idx >= newlen) { JS_FreeValue(ctx, val); - return JS_ThrowRangeError(ctx, "invalid array index"); + return JS_ThrowRangeError(ctx, "invalid typed array index"); } - len = min_uint32(oldlen, newlen); - arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val, - p->class_id, len); + copy_len = min_uint32(len, newlen); + size_log2 = typed_array_size_log2(p->class_id); + + /* create new typed array with original length (zero-initialized) */ + arr = js_create_from_ctor(ctx, JS_UNDEFINED, p->class_id); if (JS_IsException(arr)) { JS_FreeValue(ctx, val); return JS_EXCEPTION; } - if (idx < len && JS_SetPropertyInt64(ctx, arr, idx, val) < 0) { + buffer = js_array_buffer_constructor1(ctx, JS_UNDEFINED, + (uint64_t)len << size_log2, + NULL); + if (JS_IsException(buffer)) { + JS_FreeValue(ctx, val); + JS_FreeValue(ctx, arr); + return JS_EXCEPTION; + } + if (typed_array_is_oob(p)) { + JS_FreeValue(ctx, val); + JS_FreeValue(ctx, buffer); + JS_FreeValue(ctx, arr); + return JS_ThrowTypeErrorArrayBufferOOB(ctx); + } + abuf = JS_GetOpaque(buffer, JS_CLASS_ARRAY_BUFFER); + if (typed_array_init(ctx, arr, buffer, 0, len, /*track_rab*/false)) { + JS_FreeValue(ctx, val); + JS_FreeValue(ctx, arr); + return JS_EXCEPTION; + } + + /* copy min(len, newlen) elements from source; rest stays zero */ + if (copy_len > 0) { + ta = p->u.typed_array; + src_abuf = ta->buffer->u.array_buffer; + memcpy(abuf->data, src_abuf->data + ta->offset, + (size_t)copy_len << size_log2); + } + + if (JS_SetPropertyInt64(ctx, arr, idx, val) < 0) { JS_FreeValue(ctx, arr); return JS_EXCEPTION; } @@ -54966,6 +59041,8 @@ static JSValue js_typed_array_copyWithin(JSContext *ctx, JSValueConst this_val, p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; + if (typed_array_is_immutable(p)) + return JS_ThrowTypeErrorImmutableArrayBuffer(ctx); if (typed_array_is_oob(p)) return JS_ThrowTypeErrorArrayBufferOOB(ctx); len = p->u.array.count; @@ -55008,6 +59085,8 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val, p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; + if (typed_array_is_immutable(p)) + return JS_ThrowTypeErrorImmutableArrayBuffer(ctx); if (typed_array_is_oob(p)) return JS_ThrowTypeErrorArrayBufferOOB(ctx); len = p->u.array.count; @@ -55915,6 +59994,8 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, p = get_typed_array(ctx, this_val); if (!p) return JS_EXCEPTION; + if (typed_array_is_immutable(p)) + return JS_ThrowTypeErrorImmutableArrayBuffer(ctx); if (typed_array_is_oob(p)) return JS_ThrowTypeErrorArrayBufferOOB(ctx); @@ -56011,25 +60092,29 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, case 1: for(i = 0; i < len; i++) { j = array_idx[i]; - p->u.array.u.uint8_ptr[i] = ((uint8_t *)array_tmp)[j]; + if (j < len) + p->u.array.u.uint8_ptr[i] = ((uint8_t *)array_tmp)[j]; } break; case 2: for(i = 0; i < len; i++) { j = array_idx[i]; - p->u.array.u.uint16_ptr[i] = ((uint16_t *)array_tmp)[j]; + if (j < len) + p->u.array.u.uint16_ptr[i] = ((uint16_t *)array_tmp)[j]; } break; case 4: for(i = 0; i < len; i++) { j = array_idx[i]; - p->u.array.u.uint32_ptr[i] = ((uint32_t *)array_tmp)[j]; + if (j < len) + p->u.array.u.uint32_ptr[i] = ((uint32_t *)array_tmp)[j]; } break; case 8: for(i = 0; i < len; i++) { j = array_idx[i]; - p->u.array.u.uint64_ptr[i] = ((uint64_t *)array_tmp)[j]; + if (j < len) + p->u.array.u.uint64_ptr[i] = ((uint64_t *)array_tmp)[j]; } break; default: @@ -56111,6 +60196,13 @@ static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = { //JS_ALIAS_BASE_DEF("toString", "toString", 2 /* Array.prototype. */), @@@ }; +static const JSCFunctionListEntry js_typed_array_funcs[] = { + JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 1, 0), + JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 2, 0), + JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 4, 0), + JS_PROP_INT32_DEF("BYTES_PER_ELEMENT", 8, 0), +}; + static JSValue js_typed_array_base_constructor(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) @@ -56262,6 +60354,10 @@ static JSValue js_typed_array_constructor_ta(JSContext *ctx, JS_ThrowTypeErrorArrayBufferOOB(ctx); goto fail; } + if (len > p->u.array.count) { + JS_ThrowRangeError(ctx, "length out of bounds"); + goto fail; + } ta = p->u.typed_array; src_buffer = ta->buffer; src_abuf = src_buffer->u.array_buffer; @@ -56364,6 +60460,27 @@ static JSValue js_typed_array_constructor(JSContext *ctx, JS_FreeValue(ctx, buffer); return JS_EXCEPTION; } + // Re-validate buffer after js_create_from_ctor which may have run JS code + // that resized or detached the ArrayBuffer + abuf = JS_VALUE_GET_OBJ(buffer)->u.array_buffer; + if (abuf->detached) { + JS_FreeValue(ctx, buffer); + JS_FreeValue(ctx, obj); + return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + } + if (offset > abuf->byte_length) { + JS_FreeValue(ctx, buffer); + JS_FreeValue(ctx, obj); + return JS_ThrowRangeError(ctx, "invalid offset"); + } + if (track_rab) { + // Recalculate length for RAB-backed view + len = (abuf->byte_length - offset) >> size_log2; + } else if ((offset + (len << size_log2)) > abuf->byte_length) { + JS_FreeValue(ctx, buffer); + JS_FreeValue(ctx, obj); + return JS_ThrowRangeError(ctx, "invalid length"); + } if (typed_array_init(ctx, obj, buffer, offset, len, track_rab)) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; @@ -56677,6 +60794,9 @@ static JSValue js_dataview_setValue(JSContext *ctx, ta = JS_GetOpaque2(ctx, this_obj, JS_CLASS_DATAVIEW); if (!ta) return JS_EXCEPTION; + abuf = ta->buffer->u.array_buffer; + if (abuf->immutable) + return JS_ThrowTypeErrorImmutableArrayBuffer(ctx); size = 1 << typed_array_size_log2(class_id); if (JS_ToIndex(ctx, &pos, argv[0])) return JS_EXCEPTION; @@ -56710,7 +60830,6 @@ static JSValue js_dataview_setValue(JSContext *ctx, } littleEndian = argc > 2 && JS_ToBool(ctx, argv[2]); is_swap = littleEndian ^ !is_be(); - abuf = ta->buffer->u.array_buffer; if (abuf->detached) return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); // order matters: this check should come before the next one @@ -56848,19 +60967,16 @@ typedef enum AtomicsOpEnum { ATOMICS_OP_LOAD, } AtomicsOpEnum; -static void *js_atomics_get_ptr(JSContext *ctx, - JSArrayBuffer **pabuf, - int *psize_log2, JSClassID *pclass_id, - JSValueConst obj, JSValueConst idx_val, - int is_waitable) +static JSObject *js_atomics_get_buf(JSContext *ctx, + JSValueConst obj, JSValueConst idx_val, + JSArrayBuffer **pabuf, + uint64_t *pindex, int is_waitable) { JSObject *p; JSTypedArray *ta; JSArrayBuffer *abuf; - void *ptr; uint64_t idx; bool err; - int size_log2; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) goto fail; @@ -56896,15 +61012,10 @@ static void *js_atomics_get_ptr(JSContext *ctx, JS_ThrowRangeError(ctx, "out-of-bound access"); return NULL; } - size_log2 = typed_array_size_log2(p->class_id); - ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); if (pabuf) *pabuf = abuf; - if (psize_log2) - *psize_log2 = size_log2; - if (pclass_id) - *pclass_id = p->class_id; - return ptr; + *pindex = idx; + return p; } static JSValue js_atomics_op(JSContext *ctx, @@ -56912,16 +61023,15 @@ static JSValue js_atomics_op(JSContext *ctx, int argc, JSValueConst *argv, int op) { int size_log2; - uint64_t v, a, rep_val; + uint64_t v, a, rep_val, idx; void *ptr; + JSObject *p; JSValue ret; - JSClassID class_id; - JSArrayBuffer *abuf; - ptr = js_atomics_get_ptr(ctx, &abuf, &size_log2, &class_id, - argv[0], argv[1], 0); - if (!ptr) + p = js_atomics_get_buf(ctx, argv[0], argv[1], NULL, &idx, 0); + if (!p) return JS_EXCEPTION; + size_log2 = typed_array_size_log2(p->class_id); rep_val = 0; if (op == ATOMICS_OP_LOAD) { v = 0; @@ -56947,10 +61057,14 @@ static JSValue js_atomics_op(JSContext *ctx, rep_val = v32; } } - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); } + /* check if an evil .valueOf has resized or detached the array */ + if (idx >= p->u.array.count) + return JS_ThrowRangeError(ctx, "out-of-bound access"); + + ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); + switch(op | (size_log2 << 3)) { #define OP(op_name, func_name) \ @@ -57018,7 +61132,7 @@ static JSValue js_atomics_op(JSContext *ctx, abort(); } - switch(class_id) { + switch(p->class_id) { case JS_CLASS_INT8_ARRAY: a = (int8_t)a; goto done; @@ -57055,14 +61169,15 @@ static JSValue js_atomics_store(JSContext *ctx, int argc, JSValueConst *argv) { int size_log2; + uint64_t idx; void *ptr; + JSObject *p; JSValue ret; - JSArrayBuffer *abuf; - ptr = js_atomics_get_ptr(ctx, &abuf, &size_log2, NULL, - argv[0], argv[1], 0); - if (!ptr) + p = js_atomics_get_buf(ctx, argv[0], argv[1], NULL, &idx, 0); + if (!p) return JS_EXCEPTION; + size_log2 = typed_array_size_log2(p->class_id); if (size_log2 == 3) { int64_t v64; ret = JS_ToBigIntFree(ctx, js_dup(argv[2])); @@ -57072,8 +61187,11 @@ static JSValue js_atomics_store(JSContext *ctx, JS_FreeValue(ctx, ret); return JS_EXCEPTION; } - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + /* check if an evil .valueOf has resized or detached the array */ + if (idx >= p->u.array.count) { + return JS_ThrowRangeError(ctx, "out-of-bound access"); + } + ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); atomic_store((_Atomic uint64_t *)ptr, v64); } else { uint32_t v; @@ -57085,8 +61203,11 @@ static JSValue js_atomics_store(JSContext *ctx, JS_FreeValue(ctx, ret); return JS_EXCEPTION; } - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + /* check if an evil .valueOf has resized or detached the array */ + if (idx >= p->u.array.count) { + return JS_ThrowRangeError(ctx, "out-of-bound access"); + } + ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); switch(size_log2) { case 0: atomic_store((_Atomic uint8_t *)ptr, v); @@ -57161,14 +61282,16 @@ static JSValue js_atomics_wait(JSContext *ctx, int32_t v32; void *ptr; int64_t timeout; + uint64_t idx; + JSObject *p; JSAtomicsWaiter waiter_s, *waiter; int ret, size_log2, res; double d; - ptr = js_atomics_get_ptr(ctx, NULL, &size_log2, NULL, - argv[0], argv[1], 2); - if (!ptr) + p = js_atomics_get_buf(ctx, argv[0], argv[1], NULL, &idx, 2); + if (!p) return JS_EXCEPTION; + size_log2 = typed_array_size_log2(p->class_id); if (size_log2 == 3) { if (JS_ToBigInt64(ctx, &v, argv[2])) return JS_EXCEPTION; @@ -57188,6 +61311,12 @@ static JSValue js_atomics_wait(JSContext *ctx, if (!ctx->rt->can_block) return JS_ThrowTypeError(ctx, "cannot block in this thread"); + /* check if an evil .valueOf has resized or detached the array */ + if (idx >= p->u.array.count) + return JS_ThrowRangeError(ctx, "out-of-bound access"); + + ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); + /* XXX: inefficient if large number of waiters, should hash on 'ptr' value */ js_mutex_lock(&js_atomics_mutex); @@ -57229,14 +61358,18 @@ static JSValue js_atomics_notify(JSContext *ctx, int argc, JSValueConst *argv) { struct list_head *el, *el1, waiter_list; + int size_log2; int32_t count, n; void *ptr; - JSAtomicsWaiter *waiter; + uint64_t idx; + JSObject *p; JSArrayBuffer *abuf; + JSAtomicsWaiter *waiter; - ptr = js_atomics_get_ptr(ctx, &abuf, NULL, NULL, argv[0], argv[1], 1); - if (!ptr) + p = js_atomics_get_buf(ctx, argv[0], argv[1], &abuf, &idx, 1); + if (!p) return JS_EXCEPTION; + size_log2 = typed_array_size_log2(p->class_id); if (JS_IsUndefined(argv[2])) { count = INT32_MAX; @@ -57244,11 +61377,15 @@ static JSValue js_atomics_notify(JSContext *ctx, if (JS_ToInt32Clamp(ctx, &count, argv[2], 0, INT32_MAX, 0)) return JS_EXCEPTION; } - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + + /* check if an evil .valueOf has resized or detached the array */ + if (idx >= p->u.array.count) + return JS_ThrowRangeError(ctx, "out-of-bound access"); n = 0; if (abuf->shared && count > 0) { + ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); + js_mutex_lock(&js_atomics_mutex); init_list_head(&waiter_list); list_for_each_safe(el, el1, &js_atomics_waiter_list) { @@ -57297,103 +61434,113 @@ static void js__atomics_init(void) { } /* TODO(saghul) make this public and not dependent on typed arrays? */ -void JS_AddIntrinsicAtomics(JSContext *ctx) +static int JS_AddIntrinsicAtomics(JSContext *ctx) { js_once(&js_atomics_once, js__atomics_init); /* add Atomics as autoinit object */ - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_atomics_obj, countof(js_atomics_obj)); + return JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_atomics_obj, countof(js_atomics_obj)); } #endif /* CONFIG_ATOMICS */ -void JS_AddIntrinsicTypedArrays(JSContext *ctx) +static int js_uint8array_funcs_init(JSContext *ctx); + +int JS_AddIntrinsicTypedArrays(JSContext *ctx) { - JSValue typed_array_base_proto, typed_array_base_func; - JSValue array_buffer_func, shared_array_buffer_func; - int i; + JSValue typed_array_base_func, typed_array_base_proto, obj; + int i, ret; - ctx->class_proto[JS_CLASS_ARRAY_BUFFER] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY_BUFFER], - js_array_buffer_proto_funcs, - countof(js_array_buffer_proto_funcs)); - - array_buffer_func = JS_NewGlobalCConstructorOnly(ctx, "ArrayBuffer", - js_array_buffer_constructor, 1, - ctx->class_proto[JS_CLASS_ARRAY_BUFFER]); - JS_SetPropertyFunctionList(ctx, array_buffer_func, - js_array_buffer_funcs, - countof(js_array_buffer_funcs)); - - ctx->class_proto[JS_CLASS_SHARED_ARRAY_BUFFER] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_SHARED_ARRAY_BUFFER], - js_shared_array_buffer_proto_funcs, - countof(js_shared_array_buffer_proto_funcs)); - - shared_array_buffer_func = JS_NewGlobalCConstructorOnly(ctx, "SharedArrayBuffer", - js_shared_array_buffer_constructor, 1, - ctx->class_proto[JS_CLASS_SHARED_ARRAY_BUFFER]); - JS_SetPropertyFunctionList(ctx, shared_array_buffer_func, - js_shared_array_buffer_funcs, - countof(js_shared_array_buffer_funcs)); - - typed_array_base_proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, typed_array_base_proto, - js_typed_array_base_proto_funcs, - countof(js_typed_array_base_proto_funcs)); + obj = JS_NewCConstructor(ctx, JS_CLASS_ARRAY_BUFFER, "ArrayBuffer", + js_array_buffer_constructor, 1, JS_CFUNC_constructor, 0, + JS_UNDEFINED, + js_array_buffer_funcs, countof(js_array_buffer_funcs), + js_array_buffer_proto_funcs, countof(js_array_buffer_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); + + obj = JS_NewCConstructor(ctx, JS_CLASS_SHARED_ARRAY_BUFFER, "SharedArrayBuffer", + js_shared_array_buffer_constructor, 1, JS_CFUNC_constructor, 0, + JS_UNDEFINED, + js_shared_array_buffer_funcs, countof(js_shared_array_buffer_funcs), + js_shared_array_buffer_proto_funcs, countof(js_shared_array_buffer_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); + + typed_array_base_func = + JS_NewCConstructor(ctx, -1, "TypedArray", + js_typed_array_base_constructor, 0, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + js_typed_array_base_funcs, countof(js_typed_array_base_funcs), + js_typed_array_base_proto_funcs, countof(js_typed_array_base_proto_funcs), + JS_NEW_CTOR_NO_GLOBAL); + if (JS_IsException(typed_array_base_func)) + return -1; /* TypedArray.prototype.toString must be the same object as Array.prototype.toString */ - JSValue obj = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_toString); + obj = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_toString); + if (JS_IsException(obj)) + goto fail; /* XXX: should use alias method in JSCFunctionListEntry */ //@@@ - JS_DefinePropertyValue(ctx, typed_array_base_proto, JS_ATOM_toString, obj, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - - typed_array_base_func = JS_NewCFunction(ctx, js_typed_array_base_constructor, - "TypedArray", 0); - JS_SetPropertyFunctionList(ctx, typed_array_base_func, - js_typed_array_base_funcs, - countof(js_typed_array_base_funcs)); - JS_SetConstructor(ctx, typed_array_base_func, typed_array_base_proto); - JS_SetConstructorBit(ctx, typed_array_base_func, true); + typed_array_base_proto = JS_GetProperty(ctx, typed_array_base_func, JS_ATOM_prototype); + if (JS_IsException(typed_array_base_proto)) + goto fail; + ret = JS_DefinePropertyValue(ctx, typed_array_base_proto, JS_ATOM_toString, obj, + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_FreeValue(ctx, typed_array_base_proto); + if (ret < 0) + goto fail; /* Used to squelch a -Wcast-function-type warning. */ JSCFunctionType ft = { .generic_magic = js_typed_array_constructor }; for(i = JS_CLASS_UINT8C_ARRAY; i < JS_CLASS_UINT8C_ARRAY + JS_TYPED_ARRAY_COUNT; i++) { - JSValue func_obj; char buf[ATOM_GET_STR_BUF_SIZE]; const char *name; + const JSCFunctionListEntry *bpe; - ctx->class_proto[i] = JS_NewObjectProto(ctx, typed_array_base_proto); - JS_DefinePropertyValueStr(ctx, ctx->class_proto[i], - "BYTES_PER_ELEMENT", - js_int32(1 << typed_array_size_log2(i)), - 0); name = JS_AtomGetStr(ctx, buf, sizeof(buf), JS_ATOM_Uint8ClampedArray + i - JS_CLASS_UINT8C_ARRAY); - func_obj = JS_NewCFunction3(ctx, ft.generic, - name, 3, JS_CFUNC_constructor_magic, i, - typed_array_base_func); - JS_NewGlobalCConstructor2(ctx, func_obj, name, ctx->class_proto[i]); - JS_DefinePropertyValueStr(ctx, func_obj, - "BYTES_PER_ELEMENT", - js_int32(1 << typed_array_size_log2(i)), - 0); + bpe = js_typed_array_funcs + typed_array_size_log2(i); + obj = JS_NewCConstructor(ctx, i, name, + ft.generic, 3, JS_CFUNC_constructor_magic, i, + typed_array_base_func, + bpe, 1, + bpe, 1, + 0); + if (JS_IsException(obj)) { + fail: + JS_FreeValue(ctx, typed_array_base_func); + return -1; + } + JS_FreeValue(ctx, obj); } - JS_FreeValue(ctx, typed_array_base_proto); JS_FreeValue(ctx, typed_array_base_func); + /* Uint8Array base64/hex methods */ + if (js_uint8array_funcs_init(ctx)) + return -1; + /* DataView */ - ctx->class_proto[JS_CLASS_DATAVIEW] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_DATAVIEW], - js_dataview_proto_funcs, - countof(js_dataview_proto_funcs)); - JS_NewGlobalCConstructorOnly(ctx, "DataView", - js_dataview_constructor, 1, - ctx->class_proto[JS_CLASS_DATAVIEW]); + obj = JS_NewCConstructor(ctx, JS_CLASS_DATAVIEW, "DataView", + js_dataview_constructor, 1, JS_CFUNC_constructor, 0, + JS_UNDEFINED, + NULL, 0, + js_dataview_proto_funcs, countof(js_dataview_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); + /* Atomics */ #ifdef CONFIG_ATOMICS - JS_AddIntrinsicAtomics(ctx); + if (JS_AddIntrinsicAtomics(ctx)) + return -1; #endif + return 0; } /* Performance */ @@ -57412,7 +61559,7 @@ static const JSCFunctionListEntry js_perf_proto_funcs[] = { JS_CFUNC_DEF2("now", 0, js_perf_now, JS_PROP_ENUMERABLE), }; -void JS_AddPerformance(JSContext *ctx) +int JS_AddPerformance(JSContext *ctx) { ctx->time_origin = js__now_ms(); @@ -57425,6 +61572,7 @@ void JS_AddPerformance(JSContext *ctx) js_dup(performance), JS_PROP_WRITABLE | JS_PROP_ENUMERABLE | JS_PROP_CONFIGURABLE); JS_FreeValue(ctx, performance); + return 0; } /* Equality comparisons and sameness */ @@ -57438,7 +61586,7 @@ int JS_IsEqual(JSContext *ctx, JSValueConst op1, JSValueConst op2) bool JS_IsStrictEqual(JSContext *ctx, JSValueConst op1, JSValueConst op2) { - return js_strict_eq2(ctx, js_dup(op1), js_dup(op2), JS_EQ_STRICT); + return js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT); } bool JS_IsSameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2) @@ -57536,10 +61684,11 @@ static const JSClassShortDef js_weakref_class_def[] = { typedef struct JSFinRecEntry { struct list_head link; - JSValueConst obj; JSValueConst target; JSValue held_val; JSValue token; + JSValue cb; + JSContext *ctx; } JSFinRecEntry; typedef struct JSFinalizationRegistryData { @@ -57564,6 +61713,15 @@ static void delete_finrec_weakref(JSRuntime *rt, JSFinRecEntry *fre) js_free_rt(rt, wr); } +static void js_finrec_free(JSRuntime *rt, JSFinRecEntry *fre) +{ + JS_FreeValueRT(rt, fre->held_val); + JS_FreeValueRT(rt, fre->token); + JS_FreeValueRT(rt, fre->cb); + JS_FreeContext(fre->ctx); + js_free_rt(rt, fre); +} + static void js_finrec_finalizer(JSRuntime *rt, JSValueConst val) { JSFinalizationRegistryData *frd = JS_GetOpaque(val, JS_CLASS_FINALIZATION_REGISTRY); @@ -57579,9 +61737,7 @@ static void js_finrec_finalizer(JSRuntime *rt, JSValueConst val) list_for_each_safe(el, el1, &frd->entries) { JSFinRecEntry *fre = list_entry(el, JSFinRecEntry, link); list_del(&fre->link); - JS_FreeValueRT(rt, fre->held_val); - JS_FreeValueRT(rt, fre->token); - js_free_rt(rt, fre); + js_finrec_free(rt, fre); } JS_FreeValueRT(rt, frd->cb); js_free_rt(rt, frd); @@ -57599,6 +61755,8 @@ static void js_finrec_mark(JSRuntime *rt, JSValueConst val, JSFinRecEntry *fre = list_entry(el, JSFinRecEntry, link); JS_MarkValue(rt, fre->held_val, mark_func); JS_MarkValue(rt, fre->token, mark_func); + JS_MarkValue(rt, fre->cb, mark_func); + mark_func(rt, &fre->ctx->header); } } } @@ -57655,7 +61813,8 @@ static JSValue js_finrec_register(JSContext *ctx, JSValueConst this_val, js_free(ctx, fre); return JS_EXCEPTION; } - fre->obj = this_val; + fre->cb = js_dup(frd->cb); + fre->ctx = JS_DupContext(frd->ctx); fre->target = target; fre->held_val = js_dup(held_val); fre->token = js_dup(token); @@ -57684,9 +61843,7 @@ static JSValue js_finrec_unregister(JSContext *ctx, JSValueConst this_val, int a if (js_same_value(ctx, fre->token, token)) { list_del(&fre->link); delete_finrec_weakref(ctx->rt, fre); - JS_FreeValue(ctx, fre->held_val); - JS_FreeValue(ctx, fre->token); - js_free(ctx, fre); + js_finrec_free(ctx->rt, fre); removed = true; } } @@ -57709,31 +61866,43 @@ static JSValue js_finrec_job(JSContext *ctx, int argc, JSValueConst *argv) return JS_Call(ctx, argv[0], JS_UNDEFINED, 1, &argv[1]); } -void JS_AddIntrinsicWeakRef(JSContext *ctx) +int JS_AddIntrinsicWeakRef(JSContext *ctx) { JSRuntime *rt = ctx->rt; + JSValue obj; /* WeakRef */ if (!JS_IsRegisteredClass(rt, JS_CLASS_WEAK_REF)) { - init_class_range(rt, js_weakref_class_def, JS_CLASS_WEAK_REF, - countof(js_weakref_class_def)); + if (init_class_range(rt, js_weakref_class_def, JS_CLASS_WEAK_REF, + countof(js_weakref_class_def))) + return -1; } - ctx->class_proto[JS_CLASS_WEAK_REF] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_WEAK_REF], - js_weakref_proto_funcs, - countof(js_weakref_proto_funcs)); - JS_NewGlobalCConstructor(ctx, "WeakRef", js_weakref_constructor, 1, ctx->class_proto[JS_CLASS_WEAK_REF]); + obj = JS_NewCConstructor(ctx, JS_CLASS_WEAK_REF, "WeakRef", + js_weakref_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + NULL, 0, + js_weakref_proto_funcs, countof(js_weakref_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); /* FinalizationRegistry */ if (!JS_IsRegisteredClass(rt, JS_CLASS_FINALIZATION_REGISTRY)) { - init_class_range(rt, js_finrec_class_def, JS_CLASS_FINALIZATION_REGISTRY, - countof(js_finrec_class_def)); + if (init_class_range(rt, js_finrec_class_def, JS_CLASS_FINALIZATION_REGISTRY, + countof(js_finrec_class_def))) + return -1; } - ctx->class_proto[JS_CLASS_FINALIZATION_REGISTRY] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_FINALIZATION_REGISTRY], - js_finrec_proto_funcs, - countof(js_finrec_proto_funcs)); - JS_NewGlobalCConstructor(ctx, "FinalizationRegistry", js_finrec_constructor, 1, ctx->class_proto[JS_CLASS_FINALIZATION_REGISTRY]); + obj = JS_NewCConstructor(ctx, JS_CLASS_FINALIZATION_REGISTRY, "FinalizationRegistry", + js_finrec_constructor, 1, JS_CFUNC_constructor_or_func, 0, + JS_UNDEFINED, + NULL, 0, + js_finrec_proto_funcs, countof(js_finrec_proto_funcs), + 0); + if (JS_IsException(obj)) + return -1; + JS_FreeValue(ctx, obj); + return 0; } static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref) @@ -57787,20 +61956,31 @@ static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref) break; case JS_WEAK_REF_KIND_FINALIZATION_REGISTRY_ENTRY: { fre = wr->u.fin_rec_entry; - JSFinalizationRegistryData *frd = JS_GetOpaque(fre->obj, JS_CLASS_FINALIZATION_REGISTRY); - assert(frd != NULL); /** - * During the GC sweep phase the held object might be collected first. + * During the GC sweep phase the held object might be + * collected first (free_mark set). Also skip if the + * callback or held value are part of a cycle being + * collected (header.mark is set for objects on + * tmp_obj_list during gc_free_cycles). */ - if (!rt->in_free && (!JS_IsObject(fre->held_val) || JS_IsLiveObject(rt, fre->held_val))) { + bool enqueue = !rt->in_free; + if (enqueue && JS_IsObject(fre->held_val)) { + JSObject *p = JS_VALUE_GET_OBJ(fre->held_val); + if (p->free_mark || p->header.mark) + enqueue = false; + } + if (enqueue && JS_IsObject(fre->cb)) { + JSObject *p = JS_VALUE_GET_OBJ(fre->cb); + if (p->free_mark || p->header.mark) + enqueue = false; + } + if (enqueue) { JSValueConst args[2]; - args[0] = frd->cb; + args[0] = fre->cb; args[1] = fre->held_val; - JS_EnqueueJob(frd->ctx, js_finrec_job, 2, args); + JS_EnqueueJob(fre->ctx, js_finrec_job, 2, args); } - JS_FreeValueRT(rt, fre->held_val); - JS_FreeValueRT(rt, fre->token); - js_free_rt(rt, fre); + js_finrec_free(rt, fre); break; } default: @@ -57976,18 +62156,19 @@ static const JSClassShortDef js_callsite_class_def[] = { { JS_ATOM_CallSite, js_callsite_finalizer, js_callsite_mark }, /* JS_CLASS_CALL_SITE */ }; -static void _JS_AddIntrinsicCallSite(JSContext *ctx) +static int _JS_AddIntrinsicCallSite(JSContext *ctx) { JSRuntime *rt = ctx->rt; if (!JS_IsRegisteredClass(rt, JS_CLASS_CALL_SITE)) { - init_class_range(rt, js_callsite_class_def, JS_CLASS_CALL_SITE, - countof(js_callsite_class_def)); + if (init_class_range(rt, js_callsite_class_def, JS_CLASS_CALL_SITE, + countof(js_callsite_class_def))) + return -1; } ctx->class_proto[JS_CLASS_CALL_SITE] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_CALL_SITE], - js_callsite_proto_funcs, - countof(js_callsite_proto_funcs)); + return JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_CALL_SITE], + js_callsite_proto_funcs, + countof(js_callsite_proto_funcs)); } /* DOMException */ @@ -58181,7 +62362,7 @@ JSValue JS_PRINTF_FORMAT_ATTR(3, 4) JS_ThrowDOMException(JSContext *ctx, const c return JS_Throw(ctx, obj); } -void JS_AddIntrinsicDOMException(JSContext *ctx) +int JS_AddIntrinsicDOMException(JSContext *ctx) { JSRuntime *rt = ctx->rt; int i; @@ -58189,8 +62370,9 @@ void JS_AddIntrinsicDOMException(JSContext *ctx) JSValue ctor, proto; if (!JS_IsRegisteredClass(rt, JS_CLASS_DOM_EXCEPTION)) { - init_class_range(rt, js_domexception_class_def, JS_CLASS_DOM_EXCEPTION, - countof(js_domexception_class_def)); + if (init_class_range(rt, js_domexception_class_def, JS_CLASS_DOM_EXCEPTION, + countof(js_domexception_class_def))) + return -1; } proto = JS_NewObjectClass(ctx, JS_CLASS_ERROR); JS_SetPropertyFunctionList(ctx, proto, @@ -58210,6 +62392,994 @@ void JS_AddIntrinsicDOMException(JSContext *ctx) JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_DOMException, ctor, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); ctx->class_proto[JS_CLASS_DOM_EXCEPTION] = proto; + return 0; +} +/* base64 */ + +static const unsigned char b64_enc[64] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X','Y','Z', + 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p', + 'q','r','s','t','u','v','w','x','y','z', + '0','1','2','3','4','5','6','7','8','9', + '+','/' +}; + +static const unsigned char b64url_enc[64] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X','Y','Z', + 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p', + 'q','r','s','t','u','v','w','x','y','z', + '0','1','2','3','4','5','6','7','8','9', + '-','_' +}; + +enum { K_VAL = 1u, K_WS = 2u }; + +static const uint8_t b64_val[256] = { + ['A']=0, ['B']=1, ['C']=2, ['D']=3, ['E']=4, ['F']=5, ['G']=6, ['H']=7, + ['I']=8, ['J']=9, ['K']=10,['L']=11,['M']=12,['N']=13,['O']=14,['P']=15, + ['Q']=16,['R']=17,['S']=18,['T']=19,['U']=20,['V']=21,['W']=22,['X']=23,['Y']=24,['Z']=25, + ['a']=26,['b']=27,['c']=28,['d']=29,['e']=30,['f']=31,['g']=32,['h']=33, + ['i']=34,['j']=35,['k']=36,['l']=37,['m']=38,['n']=39,['o']=40,['p']=41, + ['q']=42,['r']=43,['s']=44,['t']=45,['u']=46,['v']=47,['w']=48,['x']=49,['y']=50,['z']=51, + ['0']=52,['1']=53,['2']=54,['3']=55,['4']=56,['5']=57,['6']=58,['7']=59,['8']=60,['9']=61, + ['+']=62, ['/']=63, + ['-']=62, ['_']=63, +}; + +static const char b64_flags[256] = { + [' ']=K_WS, ['\t']=K_WS, ['\n']=K_WS, ['\f']=K_WS, ['\r']=K_WS, + ['A']=K_VAL,['B']=K_VAL,['C']=K_VAL,['D']=K_VAL,['E']=K_VAL,['F']=K_VAL,['G']=K_VAL,['H']=K_VAL, + ['I']=K_VAL,['J']=K_VAL,['K']=K_VAL,['L']=K_VAL,['M']=K_VAL,['N']=K_VAL,['O']=K_VAL,['P']=K_VAL, + ['Q']=K_VAL,['R']=K_VAL,['S']=K_VAL,['T']=K_VAL,['U']=K_VAL,['V']=K_VAL,['W']=K_VAL,['X']=K_VAL, + ['Y']=K_VAL,['Z']=K_VAL, + ['a']=K_VAL,['b']=K_VAL,['c']=K_VAL,['d']=K_VAL,['e']=K_VAL,['f']=K_VAL,['g']=K_VAL,['h']=K_VAL, + ['i']=K_VAL,['j']=K_VAL,['k']=K_VAL,['l']=K_VAL,['m']=K_VAL,['n']=K_VAL,['o']=K_VAL,['p']=K_VAL, + ['q']=K_VAL,['r']=K_VAL,['s']=K_VAL,['t']=K_VAL,['u']=K_VAL,['v']=K_VAL,['w']=K_VAL,['x']=K_VAL, + ['y']=K_VAL,['z']=K_VAL, + ['0']=K_VAL,['1']=K_VAL,['2']=K_VAL,['3']=K_VAL,['4']=K_VAL,['5']=K_VAL,['6']=K_VAL,['7']=K_VAL, + ['8']=K_VAL,['9']=K_VAL, + ['+']=K_VAL,['/']=K_VAL, +}; + +static const char b64_flags_url[256] = { + [' ']=K_WS, ['\t']=K_WS, ['\n']=K_WS, ['\f']=K_WS, ['\r']=K_WS, + ['A']=K_VAL,['B']=K_VAL,['C']=K_VAL,['D']=K_VAL,['E']=K_VAL,['F']=K_VAL,['G']=K_VAL,['H']=K_VAL, + ['I']=K_VAL,['J']=K_VAL,['K']=K_VAL,['L']=K_VAL,['M']=K_VAL,['N']=K_VAL,['O']=K_VAL,['P']=K_VAL, + ['Q']=K_VAL,['R']=K_VAL,['S']=K_VAL,['T']=K_VAL,['U']=K_VAL,['V']=K_VAL,['W']=K_VAL,['X']=K_VAL, + ['Y']=K_VAL,['Z']=K_VAL, + ['a']=K_VAL,['b']=K_VAL,['c']=K_VAL,['d']=K_VAL,['e']=K_VAL,['f']=K_VAL,['g']=K_VAL,['h']=K_VAL, + ['i']=K_VAL,['j']=K_VAL,['k']=K_VAL,['l']=K_VAL,['m']=K_VAL,['n']=K_VAL,['o']=K_VAL,['p']=K_VAL, + ['q']=K_VAL,['r']=K_VAL,['s']=K_VAL,['t']=K_VAL,['u']=K_VAL,['v']=K_VAL,['w']=K_VAL,['x']=K_VAL, + ['y']=K_VAL,['z']=K_VAL, + ['0']=K_VAL,['1']=K_VAL,['2']=K_VAL,['3']=K_VAL,['4']=K_VAL,['5']=K_VAL,['6']=K_VAL,['7']=K_VAL, + ['8']=K_VAL,['9']=K_VAL, + ['-']=K_VAL,['_']=K_VAL, +}; + +static size_t b64_encode(const uint8_t *src, size_t len, char *dst, + const unsigned char *alpha) +{ + size_t i = 0, j = 0; + size_t main_len = (len / 3) * 3; + + for (; i < main_len; i += 3, j += 4) { + uint32_t v = 65536*src[i] + 256*src[i + 1] + src[i + 2]; + dst[j + 0] = alpha[(v >> 18) & 63]; + dst[j + 1] = alpha[(v >> 12) & 63]; + dst[j + 2] = alpha[(v >> 6) & 63]; + dst[j + 3] = alpha[v & 63]; + } + + size_t rem = len - i; + if (rem == 1) { + uint32_t v = 65536*src[i]; + dst[j++] = alpha[(v >> 18) & 63]; + dst[j++] = alpha[(v >> 12) & 63]; + dst[j++] = '='; + dst[j++] = '='; + } else if (rem == 2) { + uint32_t v = 65536*src[i] + 256*src[i + 1]; + dst[j++] = alpha[(v >> 18) & 63]; + dst[j++] = alpha[(v >> 12) & 63]; + dst[j++] = alpha[(v >> 6) & 63]; + dst[j++] = '='; + } + return j; +} + +/* Implements https://infra.spec.whatwg.org/#forgiving-base64-decode */ +static size_t +b64_decode(const char *src, size_t len, uint8_t *dst, int *err) +{ + size_t i, j; + uint32_t acc; + int seen, pad; + unsigned ch; + + acc = 0; + seen = 0; + for (i = 0, j = 0; i < len; i++) { + ch = (unsigned char)src[i]; + if ((b64_flags[ch] & K_WS)) + continue; + if (!(b64_flags[ch] & K_VAL)) + break; + acc = (acc << 6) | b64_val[ch]; + seen++; + if (seen == 4) { + dst[j++] = (acc >> 16) & 0xFF; + dst[j++] = (acc >> 8) & 0xFF; + dst[j++] = acc & 0xFF; + seen = 0; + acc = 0; + } + } + + if (seen != 0) { + if (seen == 3) { + dst[j++] = (acc >> 10) & 0xFF; + dst[j++] = (acc >> 2) & 0xFF; + } else if (seen == 2) { + dst[j++] = (acc >> 4) & 0xFF; + } else { + *err = 1; + return 0; + } + for (pad = 0; i < len; i++) { + ch = (unsigned char)src[i]; + if (pad < 2 && ch == '=') + pad++; + else if (!(b64_flags[ch] & K_WS)) + break; + } + if (pad != 0 && seen + pad != 4) { + *err = 1; + return 0; + } + } + + *err = i < len; + return j; +} + +static JSValue js_btoa(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + const uint8_t *in8; + uint8_t *tmp = NULL; + uint8_t *outp; + JSValue val, ret = JS_EXCEPTION; + JSString *s, *ostr; + size_t len, out_len, written; + + val = JS_ToString(ctx, argv[0]); + if (unlikely(JS_IsException(val))) + return JS_EXCEPTION; + + s = JS_VALUE_GET_STRING(val); + len = (size_t)s->len; + + if (likely(!s->is_wide_char)) { + in8 = (const uint8_t *)str8(s); + } else { + const uint16_t *src = str16(s); + tmp = js_malloc(ctx, likely(len) ? len : 1); + if (unlikely(!tmp)) + goto fail; + for (size_t i = 0; i < len; i++) { + uint32_t c = src[i]; + if (unlikely(c > 0xFF)) { + JS_ThrowDOMException(ctx, "InvalidCharacterError", + "String contains an invalid character"); + goto fail; + } + tmp[i] = (uint8_t)c; + } + in8 = tmp; + } + + if (unlikely(len > (SIZE_MAX - 2) / 3)) { + JS_ThrowRangeError(ctx, "input too large"); + goto fail; + } + out_len = 4 * ((len + 2) / 3); + if (unlikely(out_len > JS_STRING_LEN_MAX)) { + JS_ThrowRangeError(ctx, "output too large"); + goto fail; + } + + ostr = js_alloc_string(ctx, out_len, 0); + if (unlikely(!ostr)) + goto fail; + + outp = str8(ostr); + written = b64_encode(in8, len, (char *)outp, b64_enc); + outp[written] = '\0'; + ostr->len = out_len; + ret = JS_MKPTR(JS_TAG_STRING, ostr); +fail: + if (tmp) + js_free(ctx, tmp); + JS_FreeValue(ctx, val); + return ret; +} + +static JSValue js_atob(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + const uint8_t *in; + uint8_t *tmp = NULL, *outp; + JSValue val, ret = JS_EXCEPTION; + JSString *s, *ostr; + size_t slen, out_cap, out_len; + int err; + + val = JS_ToString(ctx, argv[0]); + if (unlikely(JS_IsException(val))) + return JS_EXCEPTION; + + s = JS_VALUE_GET_STRING(val); + slen = (size_t)s->len; + + if (likely(!s->is_wide_char)) { + const uint8_t *p = (const uint8_t *)str8(s); + for (size_t i = 0; i < slen; i++) { + if (unlikely(p[i] & 0x80)) { + JS_ThrowDOMException(ctx, "InvalidCharacterError", + "The string to be decoded is not correctly encoded"); + goto fail; + } + } + in = p; + } else { + const uint16_t *src = str16(s); + tmp = js_malloc(ctx, likely(slen) ? slen : 1); + if (unlikely(!tmp)) + goto fail; + for (size_t i = 0; i < slen; i++) { + if (unlikely(src[i] > 0x7F)) { + JS_ThrowDOMException(ctx, "InvalidCharacterError", + "The string to be decoded is not correctly encoded"); + goto fail; + } + tmp[i] = (uint8_t)src[i]; + } + in = tmp; + } + + if (unlikely(slen > (SIZE_MAX / 3) * 4)) { + JS_ThrowRangeError(ctx, "input too large"); + goto fail; + } + out_cap = (slen / 4) * 3 + 3; + if (unlikely(out_cap > JS_STRING_LEN_MAX)) { + JS_ThrowRangeError(ctx, "output too large"); + goto fail; + } + + ostr = js_alloc_string(ctx, out_cap, 0); + if (unlikely(!ostr)) + goto fail; + + outp = str8(ostr); + err = 0; + out_len = b64_decode((const char *)in, slen, outp, &err); + + if (unlikely(err)) { + js_free_string(ctx->rt, ostr); + JS_ThrowDOMException(ctx, "InvalidCharacterError", + "The string to be decoded is not correctly encoded"); + goto fail; + } + outp[out_len] = '\0'; + ostr->len = out_len; + ret = JS_MKPTR(JS_TAG_STRING, ostr); +fail: + if (tmp) + js_free(ctx, tmp); + JS_FreeValue(ctx, val); + return ret; +} + +static const JSCFunctionListEntry js_base64_funcs[] = { + JS_CFUNC_DEF("btoa", 1, js_btoa), + JS_CFUNC_DEF("atob", 1, js_atob), +}; + + +/* Uint8Array base64/hex (tc39 proposal-arraybuffer-base64) */ + +enum { + B64_ALPHABET_BASE64 = 0, + B64_ALPHABET_BASE64URL = 1, +}; + +enum { + B64_LAST_LOOSE = 0, + B64_LAST_STRICT = 1, + B64_LAST_STOP_BEFORE_PARTIAL = 2, +}; + + +static size_t b64_skip_ws(const char *src, size_t len, size_t index, + const char *flags) +{ + while (index < len && (flags[(unsigned char)src[index]] & K_WS)) + index++; + return index; +} + +/* Implements the FromBase64 abstract operation. + src/src_len: the input string (must be ASCII/latin1) + dst/max_len: output buffer + flags: b64_flags or b64_flags_url (selects valid characters) + last_chunk: B64_LAST_LOOSE, B64_LAST_STRICT, or B64_LAST_STOP_BEFORE_PARTIAL + *p_read: set to number of input characters consumed + *p_err: set to 1 on error, 0 on success + Returns: number of bytes written to dst */ +static size_t from_base64(const char *src, size_t src_len, + uint8_t *dst, size_t max_len, + const char *flags, int last_chunk, + size_t *p_read, int *p_err) +{ + size_t read = 0, written = 0; + uint32_t acc = 0; + int seen = 0; + size_t index = 0; + + *p_err = 0; + + if (max_len == 0) { + *p_read = 0; + return 0; + } + + /* Fast path: decode complete groups of 4 valid characters. + Breaks out on whitespace, padding, invalid chars, or capacity. */ + while (index + 4 <= src_len && written + 3 <= max_len) { + uint8_t f = flags[(unsigned char)src[index]] + & flags[(unsigned char)src[index + 1]] + & flags[(unsigned char)src[index + 2]] + & flags[(unsigned char)src[index + 3]]; + if (!(f & K_VAL)) + break; + uint32_t v = ((uint32_t)b64_val[(unsigned char)src[index]] << 18) + | ((uint32_t)b64_val[(unsigned char)src[index + 1]] << 12) + | ((uint32_t)b64_val[(unsigned char)src[index + 2]] << 6) + | (uint32_t)b64_val[(unsigned char)src[index + 3]]; + dst[written] = (uint8_t)(v >> 16); + dst[written + 1] = (uint8_t)(v >> 8); + dst[written + 2] = (uint8_t)(v); + written += 3; + index += 4; + } + read = index; + + if (written >= max_len) { + *p_read = read; + return written; + } + + /* Slow path: handle whitespace, padding, partial groups, capacity. */ + for (;;) { + index = b64_skip_ws(src, src_len, index, flags); + + if (index == src_len) { + if (seen > 0) { + if (last_chunk == B64_LAST_STOP_BEFORE_PARTIAL) { + *p_read = read; + return written; + } + if (last_chunk == B64_LAST_STRICT) { + *p_err = 1; + return 0; + } + /* loose */ + if (seen == 1) { + *p_err = 1; + return 0; + } + goto decode_partial; + } + *p_read = src_len; + return written; + } + + unsigned char ch = src[index++]; + + if (ch == '=') { + if (seen < 2) { + *p_err = 1; + return 0; + } + index = b64_skip_ws(src, src_len, index, flags); + if (seen == 2) { + if (index == src_len) { + if (last_chunk == B64_LAST_STOP_BEFORE_PARTIAL) { + *p_read = read; + return written; + } + *p_err = 1; + return 0; + } + if (src[index] == '=') { + index++; + index = b64_skip_ws(src, src_len, index, flags); + } else { + *p_err = 1; + return 0; + } + } + /* After padding, only whitespace is allowed */ + if (index != src_len) { + *p_err = 1; + return 0; + } + if (last_chunk == B64_LAST_STRICT) { + uint32_t mask = (seen == 2) ? 0xF : 0x3; + if (acc & mask) { + *p_err = 1; + return 0; + } + } + goto decode_partial; + } + + if (!(flags[ch] & K_VAL)) { + *p_err = 1; + return 0; + } + + /* Check remaining capacity before committing to this group */ + { + size_t remaining = max_len - written; + if ((remaining == 1 && seen == 2) || + (remaining == 2 && seen == 3)) { + *p_read = read; + return written; + } + } + + acc = (acc << 6) | b64_val[ch]; + seen++; + + if (seen == 4) { + dst[written] = (uint8_t)(acc >> 16); + dst[written + 1] = (uint8_t)(acc >> 8); + dst[written + 2] = (uint8_t)(acc); + written += 3; + acc = 0; + seen = 0; + read = index; + if (written >= max_len) { + *p_read = read; + return written; + } + } + } + +decode_partial: + if (seen == 2) { + dst[written++] = (uint8_t)(acc >> 4); + } else if (seen == 3) { + dst[written] = (uint8_t)(acc >> 10); + dst[written + 1] = (uint8_t)(acc >> 2); + written += 2; + } + *p_read = src_len; + return written; +} + +/* Hex helpers */ +static const char u8a_hex_digits[] = "0123456789abcdef"; + +static int u8a_hex_nibble(unsigned char ch) +{ + if (ch >= '0' && ch <= '9') return ch - '0'; + if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10; + if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10; + return -1; +} + +static size_t u8a_hex_encode(const uint8_t *src, size_t len, char *dst) +{ + for (size_t i = 0; i < len; i++) { + dst[i * 2] = u8a_hex_digits[src[i] >> 4]; + dst[i * 2 + 1] = u8a_hex_digits[src[i] & 0xF]; + } + return len * 2; +} + +/* Decode hex string to bytes. + Returns bytes written. Sets *p_read to chars consumed, *p_err on error. */ +static size_t u8a_hex_decode(const char *src, size_t src_len, + uint8_t *dst, size_t max_len, + size_t *p_read, int *p_err) +{ + size_t written = 0, i = 0; + *p_err = 0; + + if (src_len & 1) { + *p_err = 1; + return 0; + } + + while (i < src_len && written < max_len) { + int hi = u8a_hex_nibble(src[i]); + int lo = u8a_hex_nibble(src[i + 1]); + if (hi < 0 || lo < 0) { + *p_err = 1; + return 0; + } + dst[written++] = (uint8_t)((hi << 4) | lo); + i += 2; + } + + *p_read = i; + return written; +} + +/* Validate that this_val is a Uint8Array (type check only, no detach check). + Returns the JSObject pointer or NULL on error (throws). */ +static JSObject *check_uint8array(JSContext *ctx, JSValueConst this_val) +{ + JSObject *p; + + if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT) + goto fail; + p = JS_VALUE_GET_OBJ(this_val); + if (p->class_id != JS_CLASS_UINT8_ARRAY) + goto fail; + return p; +fail: + JS_ThrowTypeError(ctx, "not a Uint8Array"); + return NULL; +} + +/* Get the data pointer and length of a Uint8Array, checking for detached + buffers. Must be called after options are read (per spec ordering). + Returns 0 on success, -1 on error (throws). */ +static int get_uint8array_bytes(JSContext *ctx, JSObject *p, + uint8_t **pdata, size_t *plen) +{ + if (typed_array_is_oob(p)) { + JS_ThrowTypeErrorArrayBufferOOB(ctx); + return -1; + } + *pdata = p->u.array.u.uint8_ptr; + *plen = p->u.array.count; + return 0; +} + +/* Validate options is undefined or an object (GetOptionsObject). + Returns 0 on success, -1 on error (throws). */ +static int check_options_object(JSContext *ctx, JSValueConst options) +{ + if (JS_IsUndefined(options)) + return 0; + if (!JS_IsObject(options)) { + JS_ThrowTypeError(ctx, "options must be an object"); + return -1; + } + return 0; +} + +/* Parse the 'alphabet' option from an options object. + Returns B64_ALPHABET_BASE64 or B64_ALPHABET_BASE64URL, or -1 on error. */ +static int parse_alphabet_option(JSContext *ctx, JSValueConst options) +{ + JSValue val; + const char *str; + int ret; + + if (JS_IsUndefined(options)) + return B64_ALPHABET_BASE64; + + val = JS_GetPropertyStr(ctx, options, "alphabet"); + if (JS_IsException(val)) + return -1; + if (JS_IsUndefined(val)) + return B64_ALPHABET_BASE64; + if (!JS_IsString(val)) { + JS_FreeValue(ctx, val); + JS_ThrowTypeError(ctx, "expected string for alphabet"); + return -1; + } + + str = JS_ToCString(ctx, val); + JS_FreeValue(ctx, val); + if (!str) + return -1; + + if (!strcmp(str, "base64")) + ret = B64_ALPHABET_BASE64; + else if (!strcmp(str, "base64url")) + ret = B64_ALPHABET_BASE64URL; + else { + JS_ThrowTypeError(ctx, "invalid alphabet"); + ret = -1; + } + JS_FreeCString(ctx, str); + return ret; +} + +/* Parse the 'lastChunkHandling' option. Returns mode or -1 on error. */ +static int parse_last_chunk_option(JSContext *ctx, JSValueConst options) +{ + JSValue val; + const char *str; + int ret; + + if (JS_IsUndefined(options)) + return B64_LAST_LOOSE; + + val = JS_GetPropertyStr(ctx, options, "lastChunkHandling"); + if (JS_IsException(val)) + return -1; + if (JS_IsUndefined(val)) + return B64_LAST_LOOSE; + if (!JS_IsString(val)) { + JS_FreeValue(ctx, val); + JS_ThrowTypeError(ctx, "expected string for lastChunkHandling"); + return -1; + } + + str = JS_ToCString(ctx, val); + JS_FreeValue(ctx, val); + if (!str) + return -1; + + if (!strcmp(str, "loose")) + ret = B64_LAST_LOOSE; + else if (!strcmp(str, "strict")) + ret = B64_LAST_STRICT; + else if (!strcmp(str, "stop-before-partial")) + ret = B64_LAST_STOP_BEFORE_PARTIAL; + else { + JS_ThrowTypeError(ctx, "invalid lastChunkHandling option"); + ret = -1; + } + JS_FreeCString(ctx, str); + return ret; +} + +/* Uint8Array.prototype.toBase64([options]) */ +static JSValue js_uint8array_to_base64(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + uint8_t *data; + size_t len; + JSValue options; + JSObject *p; + int alphabet, omit_padding; + size_t out_len, written; + JSString *ostr; + char *dst; + + p = check_uint8array(ctx, this_val); + if (!p) + return JS_EXCEPTION; + + options = argc > 0 ? unsafe_unconst(argv[0]) : JS_UNDEFINED; + if (check_options_object(ctx, options)) + return JS_EXCEPTION; + alphabet = parse_alphabet_option(ctx, options); + if (alphabet < 0) + return JS_EXCEPTION; + + omit_padding = 0; + if (!JS_IsUndefined(options)) { + JSValue op_val = JS_GetPropertyStr(ctx, options, "omitPadding"); + if (JS_IsException(op_val)) + return JS_EXCEPTION; + omit_padding = JS_ToBool(ctx, op_val); + JS_FreeValue(ctx, op_val); + } + + if (get_uint8array_bytes(ctx, p, &data, &len)) + return JS_EXCEPTION; + + out_len = 4 * ((len + 2) / 3); + + if (unlikely(out_len > JS_STRING_LEN_MAX)) + return JS_ThrowRangeError(ctx, "output too large"); + + ostr = js_alloc_string(ctx, out_len, 0); + if (!ostr) + return JS_EXCEPTION; + + dst = (char *)str8(ostr); + written = b64_encode(data, len, dst, + alphabet == B64_ALPHABET_BASE64URL ? b64url_enc : b64_enc); + if (omit_padding) { + while (written > 0 && dst[written - 1] == '=') + written--; + } + dst[written] = '\0'; + + ostr->len = written; + return JS_MKPTR(JS_TAG_STRING, ostr); +} + +/* Uint8Array.prototype.toHex() */ +static JSValue js_uint8array_to_hex(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + uint8_t *data; + size_t len, out_len; + JSObject *p; + JSString *ostr; + + p = check_uint8array(ctx, this_val); + if (!p) + return JS_EXCEPTION; + if (get_uint8array_bytes(ctx, p, &data, &len)) + return JS_EXCEPTION; + + out_len = len * 2; + if (unlikely(out_len > JS_STRING_LEN_MAX)) + return JS_ThrowRangeError(ctx, "output too large"); + + ostr = js_alloc_string(ctx, out_len, 0); + if (!ostr) + return JS_EXCEPTION; + + u8a_hex_encode(data, len, (char *)str8(ostr)); + str8(ostr)[out_len] = '\0'; + return JS_MKPTR(JS_TAG_STRING, ostr); +} + +/* Uint8Array.fromBase64(string[, options]) */ +static JSValue js_uint8array_from_base64(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + const char *str; + size_t str_len, read_pos, decoded_len, out_cap; + int alphabet, last_chunk, err; + uint8_t *buf; + JSValue result, options; + + if (!JS_IsString(argv[0])) + return JS_ThrowTypeError(ctx, "expected string"); + + str = JS_ToCStringLen(ctx, &str_len, argv[0]); + if (!str) + return JS_EXCEPTION; + + options = argc > 1 ? unsafe_unconst(argv[1]) : JS_UNDEFINED; + if (check_options_object(ctx, options)) { + JS_FreeCString(ctx, str); + return JS_EXCEPTION; + } + alphabet = parse_alphabet_option(ctx, options); + if (alphabet < 0) { + JS_FreeCString(ctx, str); + return JS_EXCEPTION; + } + last_chunk = parse_last_chunk_option(ctx, options); + if (last_chunk < 0) { + JS_FreeCString(ctx, str); + return JS_EXCEPTION; + } + + out_cap = (str_len / 4) * 3 + 3; + buf = js_malloc(ctx, out_cap ? out_cap : 1); + if (!buf) { + JS_FreeCString(ctx, str); + return JS_EXCEPTION; + } + + decoded_len = from_base64(str, str_len, buf, out_cap, + alphabet == B64_ALPHABET_BASE64URL + ? b64_flags_url : b64_flags, + last_chunk, &read_pos, &err); + JS_FreeCString(ctx, str); + + if (err) { + js_free(ctx, buf); + return JS_ThrowSyntaxError(ctx, "invalid base64 string"); + } + + result = JS_NewUint8ArrayCopy(ctx, buf, decoded_len); + js_free(ctx, buf); + return result; +} + +/* Uint8Array.fromHex(string) */ +static JSValue js_uint8array_from_hex(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + const char *str; + size_t str_len, read_pos, decoded_len, out_cap; + int err; + uint8_t *buf; + JSValue result; + + if (!JS_IsString(argv[0])) + return JS_ThrowTypeError(ctx, "expected string"); + + str = JS_ToCStringLen(ctx, &str_len, argv[0]); + if (!str) + return JS_EXCEPTION; + + out_cap = str_len / 2 + 1; + buf = js_malloc(ctx, out_cap ? out_cap : 1); + if (!buf) { + JS_FreeCString(ctx, str); + return JS_EXCEPTION; + } + + decoded_len = u8a_hex_decode(str, str_len, buf, out_cap, &read_pos, &err); + JS_FreeCString(ctx, str); + + if (err) { + js_free(ctx, buf); + return JS_ThrowSyntaxError(ctx, "invalid hex string"); + } + + result = JS_NewUint8ArrayCopy(ctx, buf, decoded_len); + js_free(ctx, buf); + return result; +} + +/* Return a { read, written } result object */ +static JSValue js_make_read_written(JSContext *ctx, size_t read, size_t written) +{ + JSValue obj = JS_NewObject(ctx); + if (JS_IsException(obj)) + return JS_EXCEPTION; + if (JS_DefinePropertyValueStr(ctx, obj, "read", + js_uint32(read), JS_PROP_C_W_E) < 0) + goto fail; + if (JS_DefinePropertyValueStr(ctx, obj, "written", + js_uint32(written), JS_PROP_C_W_E) < 0) + goto fail; + return obj; +fail: + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; +} + +/* Uint8Array.prototype.setFromBase64(string[, options]) */ +static JSValue js_uint8array_set_from_base64(JSContext *ctx, + JSValueConst this_val, + int argc, JSValueConst *argv) +{ + uint8_t *data; + size_t len; + const char *str; + size_t str_len, read_pos, decoded_len; + JSObject *p; + int alphabet, last_chunk, err; + JSValue options; + + p = check_uint8array(ctx, this_val); + if (!p) + return JS_EXCEPTION; + + if (!JS_IsString(argv[0])) + return JS_ThrowTypeError(ctx, "expected string"); + + str = JS_ToCStringLen(ctx, &str_len, argv[0]); + if (!str) + return JS_EXCEPTION; + + options = argc > 1 ? unsafe_unconst(argv[1]) : JS_UNDEFINED; + if (check_options_object(ctx, options)) { + JS_FreeCString(ctx, str); + return JS_EXCEPTION; + } + alphabet = parse_alphabet_option(ctx, options); + if (alphabet < 0) { + JS_FreeCString(ctx, str); + return JS_EXCEPTION; + } + last_chunk = parse_last_chunk_option(ctx, options); + if (last_chunk < 0) { + JS_FreeCString(ctx, str); + return JS_EXCEPTION; + } + + if (get_uint8array_bytes(ctx, p, &data, &len)) { + JS_FreeCString(ctx, str); + return JS_EXCEPTION; + } + + decoded_len = from_base64(str, str_len, data, len, + alphabet == B64_ALPHABET_BASE64URL + ? b64_flags_url : b64_flags, + last_chunk, &read_pos, &err); + JS_FreeCString(ctx, str); + + if (err) + return JS_ThrowSyntaxError(ctx, "invalid base64 string"); + + return js_make_read_written(ctx, read_pos, decoded_len); +} + +/* Uint8Array.prototype.setFromHex(string) */ +static JSValue js_uint8array_set_from_hex(JSContext *ctx, + JSValueConst this_val, + int argc, JSValueConst *argv) +{ + uint8_t *data; + size_t len; + const char *str; + size_t str_len, read_pos, decoded_len; + JSObject *p; + int err; + + p = check_uint8array(ctx, this_val); + if (!p) + return JS_EXCEPTION; + + if (!JS_IsString(argv[0])) + return JS_ThrowTypeError(ctx, "expected string"); + + str = JS_ToCStringLen(ctx, &str_len, argv[0]); + if (!str) + return JS_EXCEPTION; + + if (get_uint8array_bytes(ctx, p, &data, &len)) { + JS_FreeCString(ctx, str); + return JS_EXCEPTION; + } + + decoded_len = u8a_hex_decode(str, str_len, data, len, &read_pos, &err); + JS_FreeCString(ctx, str); + + if (err) + return JS_ThrowSyntaxError(ctx, "invalid hex string"); + + return js_make_read_written(ctx, read_pos, decoded_len); +} + +static const JSCFunctionListEntry js_uint8array_proto_funcs[] = { + JS_CFUNC_DEF("toBase64", 0, js_uint8array_to_base64), + JS_CFUNC_DEF("toHex", 0, js_uint8array_to_hex), + JS_CFUNC_DEF("setFromBase64", 1, js_uint8array_set_from_base64), + JS_CFUNC_DEF("setFromHex", 1, js_uint8array_set_from_hex), +}; + +static const JSCFunctionListEntry js_uint8array_funcs[] = { + JS_CFUNC_DEF("fromBase64", 1, js_uint8array_from_base64), + JS_CFUNC_DEF("fromHex", 1, js_uint8array_from_hex), +}; + +static int js_uint8array_funcs_init(JSContext *ctx) +{ + JSValue ctor, proto; + + ctor = JS_GetProperty(ctx, ctx->global_obj, JS_ATOM_Uint8Array); + if (JS_IsException(ctor)) + return -1; + proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype); + if (JS_IsException(proto)) { + JS_FreeValue(ctx, ctor); + return -1; + } + JS_SetPropertyFunctionList(ctx, proto, + js_uint8array_proto_funcs, + countof(js_uint8array_proto_funcs)); + JS_FreeValue(ctx, proto); + JS_SetPropertyFunctionList(ctx, ctor, + js_uint8array_funcs, + countof(js_uint8array_funcs)); + JS_FreeValue(ctx, ctor); + return 0; +} + +int JS_AddIntrinsicAToB(JSContext *ctx) +{ + if (!JS_IsRegisteredClass(ctx->rt, JS_CLASS_DOM_EXCEPTION)) { + if (JS_AddIntrinsicDOMException(ctx)) + return -1; + } + JS_SetPropertyFunctionList(ctx, ctx->global_obj, + js_base64_funcs, countof(js_base64_funcs)); + return 0; } bool JS_DetectModule(const char *input, size_t input_len) @@ -58286,6 +63456,7 @@ uintptr_t js_std_cmd(int cmd, ...) { return rv; } + /* CUSTOM */ int JS_IsArrayBuffer2(JSContext *ctx, JSValueConst val) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs.h b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs.h index c8c97c33..87d9a587 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs.h +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/quickjs.h @@ -1,10 +1,10 @@ /* * QuickJS Javascript Engine * - * Copyright (c) 2017-2024 Fabrice Bellard + * Copyright (c) 2017-2026 Fabrice Bellard * Copyright (c) 2017-2024 Charlie Gordon - * Copyright (c) 2023-2025 Ben Noordhuis - * Copyright (c) 2023-2025 Saúl Ibarra Corretgé + * Copyright (c) 2023-2026 Ben Noordhuis + * Copyright (c) 2023-2026 Saúl Ibarra Corretgé * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,17 +39,87 @@ extern "C" { #define QUICKJS_NG 1 +/* Helpers. */ +#if defined(_WIN32) || defined(__CYGWIN__) +# define QUICKJS_NG_PLAT_WIN32 1 +#endif /* defined(_WIN32) || defined(__CYGWIN__) */ + #if defined(__GNUC__) || defined(__clang__) -#define js_force_inline inline __attribute__((always_inline)) -#define JS_EXTERN __attribute__((visibility("default"))) +# define QUICKJS_NG_CC_GNULIKE 1 +#endif /* defined(__GNUC__) || defined(__clang__) */ + +/* + * `JS_EXTERN` -- helper macro that must be used to mark the external + * interfaces of libqjs. + * + * Define BUILDING_QJS_SHARED when building and USING_QJS_SHARED when using + * shared libqjs. + * + * Windows note: The `__declspec` syntax is supported by both Clang and GCC. + * If building qjs, the BUILDING_QJS_SHARED macro must be defined for libqjs + * (and only for it) to properly export symbols. + */ +#ifdef QUICKJS_NG_PLAT_WIN32 +# if defined(BUILDING_QJS_SHARED) +# define JS_EXTERN __declspec(dllexport) +# elif defined(USING_QJS_SHARED) +# define JS_EXTERN __declspec(dllimport) +# else +# define JS_EXTERN /* nothing */ +# endif +#else +# if defined(BUILDING_QJS_SHARED) && defined(QUICKJS_NG_CC_GNULIKE) +# define JS_EXTERN __attribute__((visibility("default"))) +# else +# define JS_EXTERN /* nothing */ +# endif +#endif /* QUICKJS_NG_PLAT_WIN32 */ + +/* + * `JS_LIBC_EXTERN` -- helper macro that must be used to mark the extern + * interfaces of quickjs-libc specifically. + */ +#if defined(QUICKJS_NG_BUILD) && !defined(QJS_BUILD_LIBC) && defined(QUICKJS_NG_PLAT_WIN32) +/* + * We are building QuickJS-NG, quickjs-libc is a static library and we are on + * Windows. Then, make sure to not export any interfaces. + */ +# define JS_LIBC_EXTERN /* nothing */ #else -#define js_force_inline inline -#define JS_EXTERN /* nothing */ +/* + * Otherwise, if we are either (1) not building QuickJS-NG, (2) libc is built as + * a part of libqjs, or (3) we are not on Windows, define JS_LIBC_EXTERN to + * JS_EXTERN. + */ +# define JS_LIBC_EXTERN JS_EXTERN #endif +/* + * `JS_MODULE_EXTERN` -- helper macro that must be used to mark `js_init_module` + * and other public functions of the binary modules. See examples/ for examples + * of the usage. + * + * Windows note: -DQUICKJS_NG_MODULE_BUILD must be set when building a binary + * module to properly set __declspec. + */ +#ifdef QUICKJS_NG_PLAT_WIN32 +# ifdef QUICKJS_NG_MODULE_BUILD +# define JS_MODULE_EXTERN __declspec(dllexport) +# else +# define JS_MODULE_EXTERN __declspec(dllimport) +# endif +#else +# if defined(QUICKJS_NG_MODULE_BUILD) && defined(QUICKJS_NG_CC_GNULIKE) +# define JS_MODULE_EXTERN __attribute__((visibility("default"))) +# else +# define JS_MODULE_EXTERN /* nothing */ +# endif +#endif /* QUICKJS_NG_PLAT_WIN32 */ + /* Borrowed from Folly */ #ifndef JS_PRINTF_FORMAT -#ifdef _MSC_VER +/* Clang on Windows doesn't seem to support _Printf_format_string_ */ +#if defined(_MSC_VER) && !defined(__clang__) #include #define JS_PRINTF_FORMAT _Printf_format_string_ #define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) @@ -65,6 +135,9 @@ extern "C" { #endif #endif +#undef QUICKJS_NG_CC_GNULIKE +#undef QUICKJS_NG_PLAT_WIN32 + typedef struct JSRuntime JSRuntime; typedef struct JSContext JSContext; typedef struct JSObject JSObject; @@ -91,6 +164,7 @@ enum { JS_TAG_BIG_INT = -9, JS_TAG_SYMBOL = -8, JS_TAG_STRING = -7, + JS_TAG_STRING_ROPE = -6, JS_TAG_MODULE = -3, /* used internally */ JS_TAG_FUNCTION_BYTECODE = -2, /* used internally */ JS_TAG_OBJECT = -1, @@ -150,12 +224,6 @@ static inline JSValue __JS_NewFloat64(double d) return JS_MKVAL(JS_TAG_FLOAT64, (int)d); } -static inline JSValue __JS_NewShortBigInt(JSContext *ctx, int32_t d) -{ - (void)&ctx; - return JS_MKVAL(JS_TAG_SHORT_BIG_INT, d); -} - static inline bool JS_VALUE_IS_NAN(JSValue v) { (void)&v; @@ -206,12 +274,6 @@ static inline JSValue __JS_NewFloat64(double d) return v; } -static inline JSValue __JS_NewShortBigInt(JSContext *ctx, int32_t d) -{ - (void)&ctx; - return JS_MKVAL(JS_TAG_SHORT_BIG_INT, d); -} - #define JS_TAG_IS_FLOAT64(tag) ((unsigned)((tag) - JS_TAG_FIRST) >= (JS_TAG_FLOAT64 - JS_TAG_FIRST)) /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ @@ -298,15 +360,6 @@ static inline JSValue __JS_NewFloat64(double d) return v; } -static inline JSValue __JS_NewShortBigInt(JSContext *ctx, int64_t d) -{ - (void)&ctx; - JSValue v; - v.tag = JS_TAG_SHORT_BIG_INT; - v.u.short_big_int = d; - return v; -} - static inline bool JS_VALUE_IS_NAN(JSValue v) { union { @@ -324,7 +377,6 @@ static inline bool JS_VALUE_IS_NAN(JSValue v) #define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0) #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))) -#define JS_VALUE_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v)) #define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST) /* special values */ @@ -394,6 +446,7 @@ static inline bool JS_VALUE_IS_NAN(JSValue v) typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); typedef JSValue JSCFunctionData(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValueConst *func_data); +typedef JSValue JSCClosure(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, void *opaque); typedef struct JSMallocFunctions { void *(*js_calloc)(void *opaque, size_t count, size_t size); @@ -425,6 +478,7 @@ typedef struct JSMallocFunctions { #define JS_DUMP_OBJECTS 0x20000 /* dump objects in JS_FreeRuntime */ #define JS_DUMP_ATOMS 0x40000 /* dump atoms in JS_FreeRuntime */ #define JS_DUMP_SHAPES 0x80000 /* dump shapes in JS_FreeRuntime */ +#define JS_ABORT_ON_LEAKS 0x10C000 /* abort on atom/object/string leaks; for testing */ // Finalizers run in LIFO order at the very end of JS_FreeRuntime. // Intended for cleanup of associated resources; the runtime itself @@ -472,20 +526,21 @@ JS_EXTERN JSValue JS_GetFunctionProto(JSContext *ctx); /* the following functions are used to select the intrinsic object to save memory */ JS_EXTERN JSContext *JS_NewContextRaw(JSRuntime *rt); -JS_EXTERN void JS_AddIntrinsicBaseObjects(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicDate(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicEval(JSContext *ctx); +JS_EXTERN int JS_AddIntrinsicBaseObjects(JSContext *ctx); +JS_EXTERN int JS_AddIntrinsicDate(JSContext *ctx); +JS_EXTERN int JS_AddIntrinsicEval(JSContext *ctx); JS_EXTERN void JS_AddIntrinsicRegExpCompiler(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicRegExp(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicJSON(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicProxy(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicMapSet(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicTypedArrays(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicPromise(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicBigInt(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicWeakRef(JSContext *ctx); -JS_EXTERN void JS_AddPerformance(JSContext *ctx); -JS_EXTERN void JS_AddIntrinsicDOMException(JSContext *ctx); +JS_EXTERN int JS_AddIntrinsicRegExp(JSContext *ctx); +JS_EXTERN int JS_AddIntrinsicJSON(JSContext *ctx); +JS_EXTERN int JS_AddIntrinsicProxy(JSContext *ctx); +JS_EXTERN int JS_AddIntrinsicMapSet(JSContext *ctx); +JS_EXTERN int JS_AddIntrinsicTypedArrays(JSContext *ctx); +JS_EXTERN int JS_AddIntrinsicPromise(JSContext *ctx); +JS_EXTERN int JS_AddIntrinsicBigInt(JSContext *ctx); +JS_EXTERN int JS_AddIntrinsicWeakRef(JSContext *ctx); +JS_EXTERN int JS_AddPerformance(JSContext *ctx); +JS_EXTERN int JS_AddIntrinsicDOMException(JSContext *ctx); +JS_EXTERN int JS_AddIntrinsicAToB(JSContext *ctx); /* for equality comparisons and sameness */ JS_EXTERN int JS_IsEqual(JSContext *ctx, JSValueConst op1, JSValueConst op2); @@ -541,12 +596,13 @@ JS_EXTERN JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len); JS_EXTERN JSAtom JS_NewAtom(JSContext *ctx, const char *str); JS_EXTERN JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n); JS_EXTERN JSAtom JS_DupAtom(JSContext *ctx, JSAtom v); +JS_EXTERN JSAtom JS_DupAtomRT(JSRuntime *rt, JSAtom v); JS_EXTERN void JS_FreeAtom(JSContext *ctx, JSAtom v); JS_EXTERN void JS_FreeAtomRT(JSRuntime *rt, JSAtom v); JS_EXTERN JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom); JS_EXTERN JSValue JS_AtomToString(JSContext *ctx, JSAtom atom); JS_EXTERN const char *JS_AtomToCStringLen(JSContext *ctx, size_t *plen, JSAtom atom); -static inline const char *JS_AtomToCString(JSContext *ctx, JSAtom atom) +static inline const char *JS_AtomToCString(JSContext *ctx, JSAtom atom) { return JS_AtomToCStringLen(ctx, NULL, atom); } @@ -639,31 +695,31 @@ JS_EXTERN JSAtom JS_GetClassName(JSRuntime *rt, JSClassID class_id); /* value handling */ -static js_force_inline JSValue JS_NewBool(JSContext *ctx, bool val) +static inline JSValue JS_NewBool(JSContext *ctx, bool val) { (void)&ctx; return JS_MKVAL(JS_TAG_BOOL, (val != 0)); } -static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val) +static inline JSValue JS_NewInt32(JSContext *ctx, int32_t val) { (void)&ctx; return JS_MKVAL(JS_TAG_INT, val); } -static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double val) +static inline JSValue JS_NewFloat64(JSContext *ctx, double val) { (void)&ctx; return __JS_NewFloat64(val); } -static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val) +static inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val) { (void)&ctx; return JS_MKVAL(JS_TAG_CATCH_OFFSET, val); } -static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val) +static inline JSValue JS_NewInt64(JSContext *ctx, int64_t val) { JSValue v; if (val >= INT32_MIN && val <= INT32_MAX) { @@ -674,7 +730,18 @@ static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val) return v; } -static js_force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val) +static inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val) +{ + JSValue v; + if (val <= INT32_MAX) { + v = JS_NewInt32(ctx, (int32_t)val); + } else { + v = JS_NewFloat64(ctx, (double)val); + } + return v; +} + +static inline JSValue JS_NewUint64(JSContext *ctx, uint64_t val) { JSValue v; if (val <= INT32_MAX) { @@ -728,7 +795,8 @@ static inline bool JS_IsUninitialized(JSValueConst v) static inline bool JS_IsString(JSValueConst v) { - return JS_VALUE_GET_TAG(v) == JS_TAG_STRING; + int tag = JS_VALUE_GET_TAG(v); + return tag == JS_TAG_STRING || tag == JS_TAG_STRING_ROPE; } static inline bool JS_IsSymbol(JSValueConst v) @@ -803,8 +871,8 @@ static inline JSValue JS_NewString(JSContext *ctx, const char *str) { } // makes a copy of the input; does not check if the input is valid UTF-16, // that is the responsibility of the caller -JS_EXTERN JSValue JS_NewTwoByteString(JSContext *ctx, const uint16_t *buf, - size_t len); +JS_EXTERN JSValue JS_NewStringUTF16(JSContext *ctx, const uint16_t *buf, + size_t len); JS_EXTERN JSValue JS_NewAtomString(JSContext *ctx, const char *str); JS_EXTERN JSValue JS_ToString(JSContext *ctx, JSValueConst val); JS_EXTERN JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val); @@ -817,7 +885,21 @@ static inline const char *JS_ToCString(JSContext *ctx, JSValueConst val1) { return JS_ToCStringLen2(ctx, NULL, val1, 0); } +// returns a utf-16 version of the string in native endianness; the +// string is not nul terminated and can contain unmatched surrogates +// |*plen| is in uint16s, not code points; a surrogate pair such as +// U+D834 U+DF06 has len=2; an unmatched surrogate has len=1 +JS_EXTERN const uint16_t *JS_ToCStringLenUTF16(JSContext *ctx, size_t *plen, + JSValueConst val1); +static inline const uint16_t *JS_ToCStringUTF16(JSContext *ctx, + JSValueConst val1) +{ + return JS_ToCStringLenUTF16(ctx, NULL, val1); +} JS_EXTERN void JS_FreeCString(JSContext *ctx, const char *ptr); +JS_EXTERN void JS_FreeCStringRT(JSRuntime *rt, const char *ptr); +JS_EXTERN void JS_FreeCStringUTF16(JSContext *ctx, const uint16_t *ptr); +JS_EXTERN void JS_FreeCStringRT_UTF16(JSRuntime *rt, const uint16_t *ptr); JS_EXTERN JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto, JSClassID class_id); @@ -836,6 +918,7 @@ JS_EXTERN JSValue JS_ToObject(JSContext *ctx, JSValueConst val); JS_EXTERN JSValue JS_ToObjectString(JSContext *ctx, JSValueConst val); JS_EXTERN bool JS_IsFunction(JSContext* ctx, JSValueConst val); +JS_EXTERN bool JS_IsAsyncFunction(JSValueConst val); JS_EXTERN bool JS_IsConstructor(JSContext* ctx, JSValueConst val); JS_EXTERN bool JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, bool val); @@ -860,6 +943,8 @@ JS_EXTERN bool JS_IsArray(JSValueConst val); JS_EXTERN bool JS_IsProxy(JSValueConst val); JS_EXTERN JSValue JS_GetProxyTarget(JSContext *ctx, JSValueConst proxy); JS_EXTERN JSValue JS_GetProxyHandler(JSContext *ctx, JSValueConst proxy); +JS_EXTERN JSValue JS_NewProxy(JSContext *ctx, JSValueConst target, + JSValueConst handler); JS_EXTERN JSValue JS_NewDate(JSContext *ctx, double epoch_ms); JS_EXTERN bool JS_IsDate(JSValueConst v); @@ -970,6 +1055,10 @@ JS_EXTERN JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size JS_EXTERN void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj); JS_EXTERN uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj); JS_EXTERN bool JS_IsArrayBuffer(JSValueConst obj); +// returns true or false if obj is an ArrayBuffer, -1 otherwise +JS_EXTERN int JS_IsImmutableArrayBuffer(JSValueConst obj); +// returns 0 if obj is an ArrayBuffer, -1 otherwise +JS_EXTERN int JS_SetImmutableArrayBuffer(JSValueConst obj, bool immutable); JS_EXTERN uint8_t *JS_GetUint8Array(JSContext *ctx, size_t *psize, JSValueConst obj); typedef enum JSTypedArrayEnum { @@ -1008,7 +1097,9 @@ typedef struct { JS_EXTERN void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, const JSSharedArrayBufferFunctions *sf); typedef enum JSPromiseStateEnum { - JS_PROMISE_PENDING, + // argument to JS_PromiseState() was not in fact a promise + JS_PROMISE_NOT_A_PROMISE = -1, + JS_PROMISE_PENDING = 0, JS_PROMISE_FULFILLED, JS_PROMISE_REJECTED, } JSPromiseStateEnum; @@ -1018,6 +1109,7 @@ JS_EXTERN JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValueConst promise); JS_EXTERN JSValue JS_PromiseResult(JSContext *ctx, JSValueConst promise); JS_EXTERN bool JS_IsPromise(JSValueConst val); +JS_EXTERN JSValue JS_NewSettledPromise(JSContext *ctx, bool is_reject, JSValueConst value); JS_EXTERN JSValue JS_NewSymbol(JSContext *ctx, const char *description, bool is_global); @@ -1059,19 +1151,49 @@ typedef struct JSModuleDef JSModuleDef; typedef char *JSModuleNormalizeFunc(JSContext *ctx, const char *module_base_name, const char *module_name, void *opaque); +typedef char *JSModuleNormalizeFunc2(JSContext *ctx, + const char *module_base_name, + const char *module_name, + JSValueConst attributes, + void *opaque); typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx, const char *module_name, void *opaque); +/* module loader with import attributes support */ +typedef JSModuleDef *JSModuleLoaderFunc2(JSContext *ctx, + const char *module_name, void *opaque, + JSValueConst attributes); + +/* return -1 if exception, 0 if OK */ +typedef int JSModuleCheckSupportedImportAttributes(JSContext *ctx, void *opaque, + JSValueConst attributes); + /* module_normalize = NULL is allowed and invokes the default module filename normalizer */ JS_EXTERN void JS_SetModuleLoaderFunc(JSRuntime *rt, JSModuleNormalizeFunc *module_normalize, JSModuleLoaderFunc *module_loader, void *opaque); + +/* same as JS_SetModuleLoaderFunc but with import attributes support */ +JS_EXTERN void JS_SetModuleLoaderFunc2(JSRuntime *rt, + JSModuleNormalizeFunc *module_normalize, + JSModuleLoaderFunc2 *module_loader, + JSModuleCheckSupportedImportAttributes *module_check_attrs, + void *opaque); + +/* Set an attributes-aware module normalizer. Call after JS_SetModuleLoaderFunc2. */ +JS_EXTERN void JS_SetModuleNormalizeFunc2(JSRuntime *rt, + JSModuleNormalizeFunc2 *module_normalize); + /* return the import.meta object of a module */ JS_EXTERN JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m); JS_EXTERN JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m); JS_EXTERN JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m); +/* associate a JSValue to a C module */ +JS_EXTERN int JS_SetModulePrivateValue(JSContext *ctx, JSModuleDef *m, JSValue val); +JS_EXTERN JSValue JS_GetModulePrivateValue(JSContext *ctx, JSModuleDef *m); + /* JS Job support */ typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSValueConst *argv); @@ -1079,6 +1201,7 @@ JS_EXTERN int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValueConst *argv); JS_EXTERN bool JS_IsJobPending(JSRuntime *rt); +JS_EXTERN JSContext *JS_GetPendingJobContext(JSRuntime *rt); JS_EXTERN int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx); /* Structure to retrieve (de)serialized SharedArrayBuffer objects. */ @@ -1098,8 +1221,14 @@ JS_EXTERN uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst ob JS_EXTERN uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, int flags, JSSABTab *psab_tab); +/* WARNING: only enable JS_READ_OBJ_BYTECODE on input from a trusted + writer. The bytecode format is not designed to resist a hostile + producer; loading adversarial bytecode can lead to memory corruption. */ #define JS_READ_OBJ_BYTECODE (1 << 0) /* allow function/module */ #define JS_READ_OBJ_ROM_DATA (0) /* avoid duplicating 'buf' data (obsolete, broken by ICs) */ +/* WARNING: serialized SharedArrayBuffers carry a literal host pointer in + the blob; only enable JS_READ_OBJ_SAB on input produced by a trusted + writer in the same process (e.g. another Worker on the same runtime). */ #define JS_READ_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */ #define JS_READ_OBJ_REFERENCE (1 << 3) /* allow object references */ JS_EXTERN JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, int flags); @@ -1157,7 +1286,7 @@ JS_EXTERN JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func, JS_EXTERN JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func, const char *name, int length, JSCFunctionEnum cproto, int magic, - JSValueConst proto_val); + JSValueConst proto_val, int n_fields); JS_EXTERN JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, int length, int magic, int data_len, JSValueConst *data); @@ -1165,6 +1294,11 @@ JS_EXTERN JSValue JS_NewCFunctionData2(JSContext *ctx, JSCFunctionData *func, const char *name, int length, int magic, int data_len, JSValueConst *data); +typedef void JSCClosureFinalizerFunc(void*); +JS_EXTERN JSValue JS_NewCClosure(JSContext *ctx, JSCClosure *func, + const char *name, + JSCClosureFinalizerFunc *opaque_finalize, + int length, int magic, void *opaque); static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name, int length) @@ -1181,8 +1315,8 @@ static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *fun ft.generic_magic = func; return JS_NewCFunction2(ctx, ft.generic, name, length, cproto, magic); } -JS_EXTERN void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, - JSValueConst proto); +JS_EXTERN int JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, + JSValueConst proto); /* C property definition */ @@ -1227,6 +1361,8 @@ typedef struct JSCFunctionListEntry { #define JS_DEF_PROP_UNDEFINED 7 #define JS_DEF_OBJECT 8 #define JS_DEF_ALIAS 9 +#define JS_DEF_PROP_SYMBOL 10 +#define JS_DEF_PROP_BOOL 11 /* Note: c++ does not like nested designators */ #define JS_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } @@ -1243,6 +1379,8 @@ typedef struct JSCFunctionListEntry { #define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, { .f64 = val } } #define JS_PROP_U2D_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, { .u64 = val } } #define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, { .i32 = 0 } } +#define JS_PROP_SYMBOL_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_SYMBOL, 0, { .i32 = val } } +#define JS_PROP_BOOL_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_BOOL, 0, { .i32 = val } } #define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, { .prop_list = { tab, len } } } #define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, { .alias = { from, -1 } } } #define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, { .alias = { from, base } } } @@ -1278,8 +1416,8 @@ JSValue JS_WeakRef_Deref(JSContext *ctx, JSValueConst this_val); /* Version */ #define QJS_VERSION_MAJOR 0 -#define QJS_VERSION_MINOR 11 -#define QJS_VERSION_PATCH 0 +#define QJS_VERSION_MINOR 15 +#define QJS_VERSION_PATCH 1 #define QJS_VERSION_SUFFIX "" JS_EXTERN const char* JS_GetVersion(void); @@ -1287,9 +1425,6 @@ JS_EXTERN const char* JS_GetVersion(void); /* Integration point for quickjs-libc.c, not for public use. */ JS_EXTERN uintptr_t js_std_cmd(int cmd, ...); -#undef JS_EXTERN -#undef js_force_inline - #ifdef __cplusplus } /* extern "C" { */ #endif diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/repl.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/repl.js index 43fc5a04..6cc9f16b 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/repl.js +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/repl.js @@ -51,6 +51,14 @@ import * as bjson from "qjs:bjson"; var Infinity = g.Infinity; var console = g.console; + // auto-completion keywords + var keywords = [ + "await ", "catch (", "class ", "const ", "else ", "export ", "for ", + "function ", "if (", "import ", "instanceof ", "let ", "new ", + "return", "super ", "this", "try {", "typeof ", "var ", "while (", + "yield ", + ]; + var colors = { none: "\x1b[0m", black: "\x1b[30m", @@ -221,6 +229,10 @@ import * as bjson from "qjs:bjson"; (is_alpha(c) || is_digit(c) || c == '_' || c == '$'); } + function is_blank(c) { + return typeof c === "string" && "\t\r\n\f\v".includes(c[0]) + } + function ucs_length(str) { var len, c, i, str_len = str.length; len = 0; @@ -602,12 +614,23 @@ import * as bjson from "qjs:bjson"; cursor_pos = 0; } + // returns true if |line| looks something like "object.prop" + function is_named_property(line, end) { + var pos = end; + while (pos > 0 && is_word(line[pos - 1])) + pos--; + while (pos > 0 && is_blank(line[pos - 1])) + pos--; + return pos > 0 && line[pos - 1] === "."; + } + function get_context_word(line, end) { var pos = end; while (pos > 0 && is_word(line[pos - 1])) pos--; return line.slice(pos, end); } + function get_context_object(line, pos) { if (pos <= 0) return g; @@ -664,6 +687,12 @@ import * as bjson from "qjs:bjson"; s = get_context_word(line, pos); ctx_obj = get_context_object(line, pos - s.length); r = []; + if (!is_named_property(line, pos)) { + for (const kw of keywords) { + if (kw.startsWith(s)) + r.push(kw); + } + } /* enumerate properties from object and its prototype chain, add non-numeric regular properties with s as e prefix */ @@ -727,12 +756,14 @@ import * as bjson from "qjs:bjson"; } if (last_fun === completion && tab.length == 1) { /* append parentheses to function names */ - var m = res.ctx[tab[0]]; + s = tab[0]; + var m = res.ctx[s]; if (typeof m == "function") { insert('('); if (m.length == 0) insert(')'); - } else if (typeof m == "object") { + } else if (typeof m == "object" || + typeof m == "undefined" && s == "this") { insert('.'); } } diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/run-test262.c b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/run-test262.c index 56e233c4..4c996fb0 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/run-test262.c +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/run-test262.c @@ -38,6 +38,7 @@ #else #include #include +#include #endif #include "cutils.h" @@ -226,9 +227,7 @@ char *skip_prefix(const char *str, const char *prefix) char *get_basename(const char *filename) { - char *p; - - p = strrchr(filename, '/'); + const char *p = strrchr(filename, '/'); if (!p) return NULL; return strdup_len(filename, p - filename); @@ -418,6 +417,11 @@ static void consider_test_file(const char *path, const char *name, int is_dir) while (pathlen > 0 && ispathsep(path[pathlen-1])) pathlen--; snprintf(s, sizeof(s), "%.*s/%s", (int)pathlen, path, name); +#if !defined(_WIN32) && !defined(DT_DIR) + struct stat st; + if (is_dir < 0) + is_dir = !stat(s, &st) && S_ISDIR(st.st_mode); +#endif if (is_dir) find_test_files(s); else @@ -448,7 +452,11 @@ static void find_test_files(const char *path) n = scandir(path, &ds, NULL, alphasort); for (i = 0; i < n; i++) { d = ds[i]; +#ifdef DT_DIR consider_test_file(path, d->d_name, d->d_type == DT_DIR); +#else + consider_test_file(path, d->d_name, -1); +#endif free(d); } free(ds); @@ -498,6 +506,15 @@ static JSValue js_print_262(JSContext *ctx, JSValueConst this_val, if (verbose > 1) printf("%s%s", &" "[i < 1], s); JS_FreeCString(ctx, s); + if (verbose > 2 && JS_IsError(v)) { + JSValue stack = JS_GetPropertyStr(ctx, v, "stack"); + s = JS_ToCString(ctx, stack); + JS_FreeValue(ctx, stack); + if (s) { + printf("\n%s", s); + JS_FreeCString(ctx, s); + } + } } if (outfile) fputc('\n', outfile); @@ -890,6 +907,13 @@ static JSValue js_IsHTMLDDA(JSContext *ctx, JSValueConst this_val, return JS_NULL; } +static JSValue js_gc(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JS_RunGC(JS_GetRuntime(ctx)); + return JS_UNDEFINED; +} + static JSValue add_helpers1(JSContext *ctx) { JSValue global_obj; @@ -899,6 +923,8 @@ static JSValue add_helpers1(JSContext *ctx) JS_SetPropertyStr(ctx, global_obj, "print", JS_NewCFunction(ctx, js_print_262, "print", 1)); + JS_SetPropertyStr(ctx, global_obj, "gc", + JS_NewCFunction(ctx, js_gc, "gc", 0)); is_html_dda = JS_NewCFunction(ctx, js_IsHTMLDDA, "IsHTMLDDA", 0); JS_SetIsHTMLDDA(ctx, is_html_dda); @@ -943,12 +969,9 @@ static char *load_file(const char *filename, size_t *lenp) } static JSModuleDef *js_module_loader_test(JSContext *ctx, - const char *module_name, void *opaque) + const char *module_name, void *opaque, + JSValueConst attributes) { - size_t buf_len; - uint8_t *buf; - JSModuleDef *m; - JSValue func_val; char *filename, *slash, path[1024]; // interpret import("bar.js") from path/to/foo.js as @@ -962,24 +985,7 @@ static JSModuleDef *js_module_loader_test(JSContext *ctx, module_name = path; } } - - buf = js_load_file(ctx, &buf_len, module_name); - if (!buf) { - JS_ThrowReferenceError(ctx, "could not load module filename '%s'", - module_name); - return NULL; - } - - /* compile the module */ - func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name, - JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); - js_free(ctx, buf); - if (JS_IsException(func_val)) - return NULL; - /* the module is already referenced, so we must free it */ - m = JS_VALUE_GET_PTR(func_val); - JS_FreeValue(ctx, func_val); - return m; + return js_module_load(ctx, module_name, opaque, attributes, js_load_file); } int is_line_sep(char c) @@ -1757,7 +1763,7 @@ int run_test_buf(ThreadLocalStorage *tls, const char *filename, char *harness, JS_SetCanBlock(rt, can_block); /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, (void *) filename); + JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader_test, NULL, (void *) filename); if (track_promise_rejections) JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker, NULL); @@ -1820,10 +1826,10 @@ int run_test(ThreadLocalStorage *tls, const char *filename, int *msec) harness = harness_dir; if (!harness) { - p = strstr(filename, "test/"); - if (p) { + const char *p1 = strstr(filename, "test/"); + if (p1) { snprintf(harnessbuf, sizeof(harnessbuf), "%.*s%s", - (int)(p - filename), filename, "harness"); + (int)(p1 - filename), filename, "harness"); } harness = harnessbuf; } @@ -1982,7 +1988,7 @@ int run_test(ThreadLocalStorage *tls, const char *filename, int *msec) /* run a test when called by test262-harness+eshost */ int run_test262_harness_test(ThreadLocalStorage *tls, const char *filename, - bool is_module) + bool is_module, bool can_block) { JSRuntime *rt; JSContext *ctx; @@ -1990,7 +1996,6 @@ int run_test262_harness_test(ThreadLocalStorage *tls, const char *filename, size_t buf_len; int eval_flags, ret_code, ret; JSValue res_val; - bool can_block; outfile = stdout; /* for js_print_262 */ @@ -2007,11 +2012,10 @@ int run_test262_harness_test(ThreadLocalStorage *tls, const char *filename, } JS_SetRuntimeInfo(rt, filename); - can_block = true; JS_SetCanBlock(rt, can_block); /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, (void *) filename); + JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader_test, NULL, (void *) filename); add_helpers(ctx); @@ -2130,7 +2134,8 @@ void help(void) "-d dir run all test files in directory tree 'dir'\n" "-e file load the known errors from 'file'\n" "-f file execute single test from 'file'\n" - "-x file exclude tests listed in 'file'\n", + "-x file exclude tests listed in 'file'\n" + "--no-can-block set [[CanBlock]] to false (Atomics.wait will throw)\n", JS_GetVersion()); exit(1); } @@ -2153,6 +2158,7 @@ int main(int argc, char **argv) const char *ignore = ""; bool is_test262_harness = false; bool is_module = false; + bool can_block = true; bool enable_progress = true; js_std_set_worker_new_context_func(JS_NewCustomContext); @@ -2221,6 +2227,8 @@ int main(int argc, char **argv) is_test262_harness = true; } else if (str_equal(arg, "--module")) { is_module = true; + } else if (str_equal(arg, "--no-can-block")) { + can_block = false; } else { fatal(1, "unknown option: %s", arg); break; @@ -2231,7 +2239,7 @@ int main(int argc, char **argv) help(); if (is_test262_harness) { - return run_test262_harness_test(tls, argv[optind], is_module); + return run_test262_harness_test(tls, argv[optind], is_module, can_block); } nthreads = max_int(nthreads, 1); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/standalone.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/standalone.js index 59dac958..3d62fa5b 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/standalone.js +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/standalone.js @@ -13,8 +13,8 @@ const JS_WRITE_OBJ_STRIP_SOURCE = 1 << 4; * Trailer for standalone binaries. When some code gets bundled with the qjs * executable we add a 12 byte trailer. The first 8 bytes are the magic * string that helps us understand this is a standalone binary, and the - * remaining 4 are the offset (from the beginning of the binary) where the - * bundled data is located. + * remaining 4 are the offset (before the trailer) where the bundled data + * is located. * * The offset is stored as a 32bit little-endian number. */ @@ -64,7 +64,7 @@ export function compileStandalone(inFile, outFile, targetExe) { const dw = new DataView(newBuffer, exeSize + bytecode.length + Trailer.MagicSize, Trailer.DataSize); - dw.setUint32(0, exeSize, true /* little-endian */); + dw.setUint32(0, bytecode.length, true /* little-endian */); // We use os.open() so we can set the permissions mask. const newFd = os.open(outFile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o755); @@ -105,10 +105,10 @@ export function runStandalone() { } const dw = new DataView(trailer.buffer, Trailer.MagicSize, Trailer.DataSize); - const offset = dw.getUint32(0, true /* little-endian */); - const bytecode = new Uint8Array(offset - Trailer.Size); + const bytecodelen = dw.getUint32(0, true /* little-endian */); + const bytecode = new Uint8Array(bytecodelen); - r = exe.seek(offset, std.SEEK_SET); + r = exe.seek(-(bytecodelen + Trailer.Size), std.SEEK_END); if (r < 0) { exe.close(); throw new Error(`seek error: ${-r}`); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/test262.conf b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/test262.conf index 130355a9..467e31b9 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/test262.conf +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/test262.conf @@ -12,7 +12,7 @@ mode=default # handle tests flagged as [async]: yes, no, skip # for these, load 'harness/doneprintHandle.js' prior to test -# and expect `print('Test262:AsyncTestComplete')` to be called for +# and expect `print('Test262:AsyncTestComplete')` to be called for # successful termination async=yes @@ -62,10 +62,10 @@ arraybuffer-transfer arrow-function async-functions async-iteration -# atomics are broken in recent versions of tcc -Atomics=!tcc Atomics.pause=!tcc Atomics.waitAsync=skip +Atomics=!tcc # atomics are broken in recent versions of tcc +await-dictionary=skip BigInt caller canonical-tz=skip @@ -99,7 +99,7 @@ destructuring-binding dynamic-import error-cause Error.isError -explicit-resource-management=skip +explicit-resource-management exponentiation export-star-as-namespace-from-module FinalizationRegistry @@ -112,10 +112,11 @@ generators globalThis hashbang host-gc-required=skip -immutable-arraybuffer=skip -import-assertions=skip -import-attributes=skip +immutable-arraybuffer +import-attributes +import-bytes import-defer=skip +import-text import.meta Int16Array Int32Array @@ -130,6 +131,7 @@ Intl.DateTimeFormat-fractionalSecondDigits=skip Intl.DisplayNames-v2=skip Intl.DisplayNames=skip Intl.DurationFormat=skip +Intl.Era-monthcode=skip Intl.ListFormat=skip Intl.Locale-info=skip Intl.Locale=skip @@ -140,8 +142,9 @@ Intl.Segmenter=skip IsHTMLDDA iterator-helpers iterator-sequencing -json-modules=skip -json-parse-with-source=skip +joint-iteration +json-modules +json-parse-with-source json-superset legacy-regexp=skip let @@ -149,6 +152,7 @@ logical-assignment-operators Map Math.sumPrecise new.target +nonextensible-applies-to-private=skip numeric-separator-literal object-rest object-spread @@ -186,6 +190,8 @@ ShadowRealm=skip SharedArrayBuffer source-phase-imports-module-source=skip source-phase-imports=skip +stable-array-sort +stable-typedarray-sort string-trimming String.fromCodePoint String.prototype.at @@ -224,7 +230,7 @@ u180e Uint16Array Uint32Array Uint8Array -uint8array-base64=skip +uint8array-base64 Uint8ClampedArray upsert WeakMap @@ -247,6 +253,24 @@ test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js #test262/test/built-ins/RegExp/CharacterClassEscapes/ #test262/test/built-ins/RegExp/property-escapes/ +# global variable assignment performance improvement (V8, SpiderMonkey and JavaScriptCore have the same non-compliance) +test262/test/language/identifier-resolution/assign-to-global-undefined.js + +# destructuring performance improvements (V8 has the same spec non-compliance) +test262/test/language/expressions/assignment/S11.13.1_A6_T1.js +test262/test/language/expressions/assignment/S11.13.1_A6_T2.js +test262/test/language/expressions/compound-assignment/S11.13.2_A6.1_T1.js +test262/test/language/expressions/compound-assignment/S11.13.2_A6.2_T1.js +test262/test/language/expressions/compound-assignment/S11.13.2_A6.3_T1.js +test262/test/language/expressions/compound-assignment/S11.13.2_A6.4_T1.js +test262/test/language/expressions/compound-assignment/S11.13.2_A6.5_T1.js +test262/test/language/expressions/compound-assignment/S11.13.2_A6.6_T1.js +test262/test/language/expressions/compound-assignment/S11.13.2_A6.7_T1.js +test262/test/language/expressions/compound-assignment/S11.13.2_A6.8_T1.js +test262/test/language/expressions/compound-assignment/S11.13.2_A6.9_T1.js +test262/test/language/expressions/compound-assignment/S11.13.2_A6.10_T1.js +test262/test/language/expressions/compound-assignment/S11.13.2_A6.11_T1.js + # in progress regexp-v-flag support, see https://github.com/quickjs-ng/quickjs/issues/228 test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-CharacterClass.js test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-P.js @@ -391,6 +415,7 @@ test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-string- # frequently broken, sometimes contain engine-dependent tests test262/test/staging/ +!test262/test/staging/explicit-resource-management/ [tests] # list test files or use config.testdir diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/test262_errors.txt b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/test262_errors.txt new file mode 100755 index 00000000..e014e0cb --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/test262_errors.txt @@ -0,0 +1,96 @@ +test262/test/annexB/language/expressions/assignmenttargettype/callexpression-as-for-in-lhs.js:27: SyntaxError: invalid for in/of left hand-side +test262/test/annexB/language/expressions/assignmenttargettype/callexpression-as-for-of-lhs.js:27: SyntaxError: invalid for in/of left hand-side +test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-compound-assignment.js:33: SyntaxError: invalid assignment left-hand side +test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-postfix-update.js:27: SyntaxError: invalid increment/decrement operand +test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-prefix-update.js:27: SyntaxError: invalid increment/decrement operand +test262/test/annexB/language/expressions/assignmenttargettype/callexpression.js:33: SyntaxError: invalid assignment left-hand side +test262/test/annexB/language/expressions/assignmenttargettype/cover-callexpression-and-asyncarrowhead.js:20: SyntaxError: invalid assignment left-hand side +test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/iterator-result-poisoned-wrapper.js:64: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/iterator-result-poisoned-wrapper.js:64: strict mode: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/next-result-poisoned-wrapper.js:69: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/next-result-poisoned-wrapper.js:69: strict mode: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-iterator-next-rejected-promise-close.js:59: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-iterator-next-rejected-promise-close.js:59: strict mode: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-next-rejected-promise-close.js:64: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-next-rejected-promise-close.js:64: strict mode: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/iterator-result-rejected-promise-close.js:74: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/iterator-result-rejected-promise-close.js:74: strict mode: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-result-poisoned-wrapper.js:81: TypeError: $DONE() not called +test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-result-poisoned-wrapper.js:81: strict mode: TypeError: $DONE() not called +test262/test/built-ins/RegExp/property-escapes/generated/Script_-_Unknown.js:16: SyntaxError: unknown unicode script +test262/test/built-ins/RegExp/property-escapes/generated/Script_-_Unknown.js:16: strict mode: SyntaxError: unknown unicode script +test262/test/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Unknown.js:16: SyntaxError: unknown unicode script +test262/test/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Unknown.js:16: strict mode: SyntaxError: unknown unicode script +test262/test/built-ins/RegExp/property-escapes/special-property-value-Script_Extensions-Unknown.js:14: SyntaxError: unknown unicode script +test262/test/built-ins/RegExp/property-escapes/special-property-value-Script_Extensions-Unknown.js:14: strict mode: SyntaxError: unknown unicode script +test262/test/built-ins/RegExp/prototype/exec/regexp-builtin-exec-v-u-flag.js:45: Test262Error: Actual argument [null] shouldn't be primitive. Unicode property escapes with v flag +test262/test/built-ins/RegExp/prototype/exec/regexp-builtin-exec-v-u-flag.js:45: strict mode: Test262Error: Actual argument [null] shouldn't be primitive. Unicode property escapes with v flag +test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-16.0.js:16: Test262Error: `\p{RGI_Emoji}` should match 🇨🇶 (U+01F1E8 U+01F1F6) +test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-16.0.js:16: strict mode: Test262Error: `\p{RGI_Emoji}` should match 🇨🇶 (U+01F1E8 U+01F1F6) +test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-17.0.js:16: Test262Error: `\p{RGI_Emoji}` should match 👨🏻‍🐰‍👨🏼 (U+01F468 U+01F3FB U+00200D U+01F430 U+00200D U+01F468 U+01F3FC) +test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-17.0.js:16: strict mode: Test262Error: `\p{RGI_Emoji}` should match 👨🏻‍🐰‍👨🏼 (U+01F468 U+01F3FB U+00200D U+01F430 U+00200D U+01F468 U+01F3FC) +test262/test/built-ins/String/prototype/match/regexp-prototype-match-v-u-flag.js:10: Test262Error: Actual argument [null] shouldn't be primitive. Unicode property escapes with v flag +test262/test/built-ins/String/prototype/match/regexp-prototype-match-v-u-flag.js:10: strict mode: Test262Error: Actual argument [null] shouldn't be primitive. Unicode property escapes with v flag +test262/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-v-u-flag.js:73: Test262Error: Actual [] and expected [𠮷, 𠮷, 𠮷, 0, 3, 6] should have the same contents. +test262/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-v-u-flag.js:73: strict mode: Test262Error: Actual [] and expected [𠮷, 𠮷, 𠮷, 0, 3, 6] should have the same contents. +test262/test/built-ins/String/prototype/replace/regexp-prototype-replace-v-u-flag.js:9: Test262Error: Unicode property escapes with v flag Expected SameValue(«"𠮷a𠮷b𠮷"», «"XaXbX"») to be true +test262/test/built-ins/String/prototype/replace/regexp-prototype-replace-v-u-flag.js:9: strict mode: Test262Error: Unicode property escapes with v flag Expected SameValue(«"𠮷a𠮷b𠮷"», «"XaXbX"») to be true +test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-flag.js:9: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true +test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-flag.js:9: strict mode: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true +test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-u-flag.js:9: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true +test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-u-flag.js:9: strict mode: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true +test262/test/built-ins/TypedArray/prototype/lastIndexOf/negative-index-and-resize-to-smaller.js:23: Test262Error: For index -1 Expected SameValue(«-1», «2») to be true (Testing with Float64Array and makePassthrough.) +test262/test/built-ins/TypedArray/prototype/lastIndexOf/negative-index-and-resize-to-smaller.js:23: strict mode: Test262Error: For index -1 Expected SameValue(«-1», «2») to be true (Testing with Float64Array and makePassthrough.) +test262/test/built-ins/TypedArray/prototype/slice/speciesctor-return-same-buffer-with-offset.js:24: Test262Error: Actual [20, 30, 40, 60] and expected [20, 20, 20, 60] should have the same contents. (Testing with Float64Array and makePassthrough.) +test262/test/built-ins/TypedArray/prototype/slice/speciesctor-return-same-buffer-with-offset.js:24: strict mode: Test262Error: Actual [20, 30, 40, 60] and expected [20, 20, 20, 60] should have the same contents. (Testing with Float64Array and makePassthrough.) +test262/test/built-ins/TypedArray/prototype/subarray/BigInt/speciesctor-get-species-custom-ctor-invocation.js:43: Test262Error: Actual [[object ArrayBuffer], 8, undefined] and expected [[object ArrayBuffer], 8] should have the same contents. Constructor called with arguments (Testing with BigInt64Array and makeResizableArrayBuffer.) +test262/test/built-ins/TypedArray/prototype/subarray/BigInt/speciesctor-get-species-custom-ctor-invocation.js:43: strict mode: Test262Error: Actual [[object ArrayBuffer], 8, undefined] and expected [[object ArrayBuffer], 8] should have the same contents. Constructor called with arguments (Testing with BigInt64Array and makeResizableArrayBuffer.) +test262/test/built-ins/TypedArray/prototype/subarray/byteoffset-with-detached-buffer.js:44: RangeError: invalid offset (Testing with Float64Array and makePassthrough.) +test262/test/built-ins/TypedArray/prototype/subarray/byteoffset-with-detached-buffer.js:44: strict mode: RangeError: invalid offset (Testing with Float64Array and makePassthrough.) +test262/test/built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor-invocation.js:43: Test262Error: Actual [[object ArrayBuffer], 8, undefined] and expected [[object ArrayBuffer], 8] should have the same contents. Constructor called with arguments (Testing with Float64Array and makeResizableArrayBuffer.) +test262/test/built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor-invocation.js:43: strict mode: Test262Error: Actual [[object ArrayBuffer], 8, undefined] and expected [[object ArrayBuffer], 8] should have the same contents. Constructor called with arguments (Testing with Float64Array and makeResizableArrayBuffer.) +test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-prototype-chain-set.js:35: Test262Error: value should not be coerced Expected SameValue(«22», «0») to be true +test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-prototype-chain-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«22», «0») to be true +test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-reflect-set.js:35: Test262Error: value should not be coerced Expected SameValue(«32», «0») to be true +test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-reflect-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«32», «0») to be true +test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-prototype-chain-set.js:35: Test262Error: value should not be coerced Expected SameValue(«110», «0») to be true +test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-prototype-chain-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«110», «0») to be true +test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-reflect-set.js:35: Test262Error: value should not be coerced Expected SameValue(«160», «0») to be true +test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-reflect-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«160», «0») to be true +test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-object.js:19: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true +test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-object.js:19: strict mode: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true +test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-typed-array.js:19: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true +test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-typed-array.js:19: strict mode: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true +test262/test/language/destructuring/binding/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js:73: Test262Error: Actual [binding::source, binding::sourceKey, sourceKey, get source, binding::defaultValue, binding::varTarget] and expected [binding::source, binding::sourceKey, sourceKey, binding::varTarget, get source, binding::defaultValue] should have the same contents. +test262/test/language/expressions/assignment/destructuring/iterator-destructuring-property-reference-target-evaluation-order.js:42: Test262Error: Actual [source, iterator, target, target-key, target-key-tostring, iterator-step, iterator-done, set] and expected [source, iterator, target, target-key, iterator-step, iterator-done, target-key-tostring, set] should have the same contents. +test262/test/language/expressions/assignment/destructuring/iterator-destructuring-property-reference-target-evaluation-order.js:42: strict mode: Test262Error: Actual [source, iterator, target, target-key, target-key-tostring, iterator-step, iterator-done, set] and expected [source, iterator, target, target-key, iterator-step, iterator-done, target-key-tostring, set] should have the same contents. +test262/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js:37: Test262Error: Actual [binding::source, binding::sourceKey, sourceKey, binding::target, binding::targetKey, targetKey, get source, binding::defaultValue, set target] and expected [binding::source, binding::sourceKey, sourceKey, binding::target, binding::targetKey, get source, binding::defaultValue, targetKey, set target] should have the same contents. +test262/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order.js:32: Test262Error: Actual [source, source-key, source-key-tostring, target, target-key, target-key-tostring, get, set] and expected [source, source-key, source-key-tostring, target, target-key, get, target-key-tostring, set] should have the same contents. +test262/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order.js:32: strict mode: Test262Error: Actual [source, source-key, source-key-tostring, target, target-key, target-key-tostring, get, set] and expected [source, source-key, source-key-tostring, target, target-key, get, target-key-tostring, set] should have the same contents. +test262/test/language/expressions/assignment/target-member-computed-reference.js:22: Test262Error: Expected a DummyError but got a Test262Error +test262/test/language/expressions/assignment/target-member-computed-reference.js:22: strict mode: Test262Error: Expected a DummyError but got a Test262Error +test262/test/language/expressions/assignment/target-super-computed-reference.js:20: Test262Error: Expected a DummyError but got a Test262Error +test262/test/language/expressions/assignment/target-super-computed-reference.js:20: strict mode: Test262Error: Expected a DummyError but got a Test262Error +test262/test/language/expressions/dynamic-import/import-attributes/2nd-param-with-type-text.js:10: TypeError: $DONE() not called +test262/test/language/expressions/dynamic-import/import-attributes/2nd-param-with-type-text.js:10: strict mode: TypeError: $DONE() not called +test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: unexpected error type: Test262: This statement should not be evaluated. +test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: strict mode: unexpected error type: Test262: This statement should not be evaluated. +test262/test/language/expressions/object/computed-property-name-topropertykey-before-value-evaluation.js:31: Test262Error: Expected SameValue(«"bad"», «"ok"») to be true +test262/test/language/expressions/object/computed-property-name-topropertykey-before-value-evaluation.js:31: strict mode: Test262Error: Expected SameValue(«"bad"», «"ok"») to be true +test262/test/language/import/import-attributes/text-self.js:10: SyntaxError: Could not find export 'default' in module 'test262/test/language/import/import-attributes/text-self.js' +test262/test/language/module-code/ambiguous-export-bindings/import-and-export-propagates-binding.js:75: SyntaxError: export 'foo' in module 'test262/test/language/module-code/ambiguous-export-bindings/imp' is ambiguous +test262/test/language/module-code/ambiguous-export-bindings/namespace-unambiguous-if-export-star-as-from-and-import-star-as-and-export.js:74: SyntaxError: export 'foo' in module 'test262/test/language/module-code/ambiguous-export-bindings/nam' is ambiguous +test262/test/language/module-code/ambiguous-export-bindings/namespace-unambiguous-if-export-star-as-from.js:75: SyntaxError: export 'foo' in module 'test262/test/language/module-code/ambiguous-export-bindings/nam' is ambiguous +test262/test/language/module-code/ambiguous-export-bindings/namespace-unambiguous-if-import-star-as-and-export.js:74: SyntaxError: export 'foo' in module 'test262/test/language/module-code/ambiguous-export-bindings/nam' is ambiguous +test262/test/language/module-code/top-level-await/module-graphs-does-not-hang.js:10: TypeError: $DONE() not called +test262/test/language/module-code/top-level-await/rejection-order.js:20: TypeError: $DONE() not called +test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-get-followed-by-generator-asi.js:40: SyntaxError: invalid property name +test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-get-followed-by-generator-asi.js:40: strict mode: SyntaxError: invalid property name +test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-set-followed-by-generator-asi.js:40: SyntaxError: invalid property name +test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-set-followed-by-generator-asi.js:40: strict mode: SyntaxError: invalid property name +test262/test/language/statements/with/get-binding-value-call-with-proxy-env.js:39: Test262Error: Actual [has:Object, get:Symbol(Symbol.unscopables), get:Object] and expected [has:Object, get:Symbol(Symbol.unscopables), has:Object, get:Object] should have the same contents. +test262/test/language/statements/with/get-binding-value-idref-with-proxy-env.js:39: Test262Error: Actual [has:Object, get:Symbol(Symbol.unscopables), get:Object] and expected [has:Object, get:Symbol(Symbol.unscopables), has:Object, get:Object] should have the same contents. +test262/test/language/statements/with/get-mutable-binding-binding-deleted-in-get-unscopables-strict-mode.js:21: Test262Error: Expected a ReferenceError to be thrown but no exception was thrown at all +test262/test/language/statements/with/set-mutable-binding-binding-deleted-with-typed-array-in-proto-chain.js:20: Test262Error: Expected SameValue(«[object Object]», «undefined») to be true +test262/test/language/statements/with/set-mutable-binding-idref-compound-assign-with-proxy-env.js:58: Test262Error: Actual [has:p, get:Symbol(Symbol.unscopables), get:p, set:p, getOwnPropertyDescriptor:p, defineProperty:p] and expected [has:p, get:Symbol(Symbol.unscopables), has:p, get:p, has:p, set:p, getOwnPropertyDescriptor:p, defineProperty:p] should have the same contents. +test262/test/language/statements/with/set-mutable-binding-idref-with-proxy-env.js:50: Test262Error: Actual [has:p, get:Symbol(Symbol.unscopables), set:p, getOwnPropertyDescriptor:p, defineProperty:p] and expected [has:p, get:Symbol(Symbol.unscopables), has:p, set:p, getOwnPropertyDescriptor:p, defineProperty:p] should have the same contents. diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests.conf b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests.conf index 7a2afc6f..f94778cb 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests.conf +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests.conf @@ -3,6 +3,9 @@ local=yes verbose=yes testdir=tests +[features] +skip-if-tcc=!tcc + [exclude] tests/empty.js tests/fixture_cyclic_import.js diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/assert.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/assert.js new file mode 100755 index 00000000..c8240c88 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/assert.js @@ -0,0 +1,49 @@ +export function assert(actual, expected, message) { + if (arguments.length === 1) + expected = true; + + if (typeof actual === typeof expected) { + if (actual === expected) { + if (actual !== 0 || (1 / actual) === (1 / expected)) + return; + } + if (typeof actual === 'number') { + if (isNaN(actual) && isNaN(expected)) + return; + } + if (typeof actual === 'object') { + if (actual !== null && expected !== null + && actual.constructor === expected.constructor + && actual.toString() === expected.toString()) + return; + } + } + throw Error("assertion failed: got |" + actual + "|" + + ", expected |" + expected + "|" + + (message ? " (" + message + ")" : "")); +} + +export function assertThrows(err, func) +{ + var ex; + ex = false; + try { + func(); + } catch(e) { + ex = true; + assert(e instanceof err); + } + assert(ex, true, "exception expected"); +} + +export function assertArrayEquals(a, b) +{ + if (!Array.isArray(a) || !Array.isArray(b)) + return assert(false); + + assert(a.length, b.length); + + a.forEach((value, idx) => { + assert(b[idx], value); + }); +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1221.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1221.js new file mode 100755 index 00000000..a3ed10ec --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1221.js @@ -0,0 +1,16 @@ +import {assert} from "./assert.js" + +let caught = 0 +for (let i = 1; i <= 32; i++) { + const prefix = "(:?".repeat(i) + const suffix = "|)+".repeat(i) + const between = "(?:a|)+" + try { + new RegExp(prefix + between + suffix) + } catch (e) { + assert(e instanceof SyntaxError) + assert(e.message, "out of memory") + caught++ + } +} +assert(caught, 12) // subject to change diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1296.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1296.js new file mode 100755 index 00000000..80a1305d --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1296.js @@ -0,0 +1,12 @@ +const ab = new ArrayBuffer(10, { maxByteLength: 10 }); +function f() { + return 1337; +} +const evil = f.bind(); + +Object.defineProperty(evil, "prototype", { get: () => { + print("resizing"); + return ab.resize(); +} }); +let u8 = Reflect.construct(Uint8Array, [ab], evil); +print(u8); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1297.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1297.js new file mode 100755 index 00000000..106d2961 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1297.js @@ -0,0 +1,22 @@ +// Test for issue #1297: Heap buffer overflow in js_typed_array_sort +// The bug occurs when a comparator function resizes the ArrayBuffer during sort + +const sz = 256; +const newSz = 10; +const ab = new ArrayBuffer(sz, { maxByteLength: sz * 10 }); +const u8 = new Uint8Array(ab); + +for (let i = 0; i < sz; i++) u8[i] = i; +u8[sz - 1] = 0; + +let cnt = 0; +u8.sort((a, b) => { + for (let i = 0; i < 3000; i++) { + try { ab.resize(newSz); } catch(e){} + } + + return a - b; +}); + +// If we get here without crashing, the fix works +print("PASS: bug1297 - typed array sort with resize did not crash"); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1301.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1301.js new file mode 100755 index 00000000..c1dfa528 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1301.js @@ -0,0 +1,21 @@ +/*--- +features: [skip-if-tcc] +---*/ + +import {assert} from "./assert.js" + +const rab = new ArrayBuffer(1024, { maxByteLength: 1024 * 1024 }); +const i32 = new Int32Array(rab); +const evil = { + valueOf: () => { + print("resize buffer"); + rab.resize(0); + return 123; + } +}; + +try { + Atomics.store(i32, 0, evil); +} catch (e) { + assert(e instanceof RangeError); +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1302.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1302.js new file mode 100755 index 00000000..0535ca9c --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1302.js @@ -0,0 +1,24 @@ +/*--- +features: [skip-if-tcc] +---*/ + +import {assert} from "./assert.js" + +const rab = new ArrayBuffer(1024, { maxByteLength: 1024 * 1024 }); +const i32 = new Int32Array(rab); +const evil = { + valueOf: () => { + print("resize buffer"); + rab.resize(0); + return 123; + } +}; +try { + Atomics.add(i32, 0, evil); + // Atomics.sub(i32, 0, evil); + // Atomics.and(i32, 0, evil); + // Atomics.or(i32, 0, evil); + // Atomics.xor(i32, 0, evil); +} catch (e) { + assert(e instanceof RangeError); +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1305.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1305.js new file mode 100755 index 00000000..52a76808 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1305.js @@ -0,0 +1,26 @@ +import {assert} from "./assert.js" + +const rab = new ArrayBuffer(10, { maxByteLength: 10 }); +const src = new Uint8Array(rab, 0); + +function f() { + return 1337; +} + +const EvilConstructor = new Proxy(function(){}, { + get: function(target, prop, receiver) { + if (prop === 'prototype') { + print("resizing"); + rab.resize(0); + return Uint8Array.prototype; + } + return Reflect.get(target, prop, receiver); + } +}); + +try { + let u8 = Reflect.construct(Uint8Array, [src], EvilConstructor); + print(u8); +} catch (e) { + assert(e instanceof RangeError); +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1318.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1318.js new file mode 100755 index 00000000..af9f9cd1 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1318.js @@ -0,0 +1,54 @@ +import * as std from "qjs:std"; +// https://github.com/quickjs-ng/quickjs/issues/1318 +// Heap use-after-free when FinalizationRegistry is part of a reference cycle. +// Run under ASAN. + +// Test 1: held value is the FR itself (original PoC pattern) +{ + let target = {}; + let fr = new FinalizationRegistry(function() {}); + fr.register(target, fr); + fr.ref = target; + target.ref = fr; + target = null; + fr = null; + std.gc(); +} + +// Test 2: callback is part of the cycle +{ + let target = {}; + let cb = function() {}; + let fr = new FinalizationRegistry(cb); + fr.register(target, 42); + fr.ref = target; + target.ref = fr; + target.cb = cb; + target = null; + fr = null; + cb = null; + std.gc(); +} + +// Test 3: simplified real-world pattern (from issue comment) +{ + class Registry { + #fr = new FinalizationRegistry(v => {}); + set(key) { + const ref = new WeakRef(key); + this.#fr.register(key, {}, ref); + } + } + function Observer() { + this.targets = new Registry; + } + Observer.prototype.observe = function(target) { + this.targets.set(target); + target.subset = new Set; + target.subset.add(this); + } + let sample = {}; + new Observer().observe(sample); + sample = null; + std.gc(); +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1352.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1352.js new file mode 100755 index 00000000..1a9099c3 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1352.js @@ -0,0 +1,8 @@ +// run under ASAN +let key = Symbol("fortytwo") +let wm = new WeakMap() +let fr = new FinalizationRegistry(() => {}) +fr.register(key, 42) +wm.set(key, fr) +fr = null +key = null diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1354.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1354.js new file mode 100755 index 00000000..d331c804 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1354.js @@ -0,0 +1,6 @@ +/*--- +negative: + phase: runtime + type: SyntaxError +---*/ +new RegExp("[", "v") // run under ASAN diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1355.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1355.js new file mode 100755 index 00000000..b1358b52 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1355.js @@ -0,0 +1,58 @@ +function deferred() { + let resolve + const promise = new Promise(f => { + resolve = f + }) + return { promise, resolve } +} + +let it, a, b, c +let getterHit = 0 +let inGetter = false + +Object.defineProperty(Object.prototype, "then", { + configurable: true, + get() { + if (inGetter || !it) return undefined + inGetter = true + try { + if (getterHit === 0) { + it.return(0) + } else if (getterHit === 1) { + it.next(1) + it.return(1) + } + getterHit++ + } catch (_) { + } + inGetter = false + return undefined + }, +}) + +async function* g() { + try { + await a.promise + yield 1 + await b.promise + yield 2 + await c.promise + } finally { + await c.promise + } +} + +(async () => { + a = deferred() + b = deferred() + c = deferred() + it = g() + + it.next() + a.resolve({}) + await Promise.resolve() + await Promise.resolve() + b.resolve({}) + c.resolve({}) + await Promise.resolve() +})() diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1368.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1368.js new file mode 100755 index 00000000..a9a7c32e --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1368.js @@ -0,0 +1,72 @@ +import { assert, assertThrows } from "./assert.js"; + +function test_symbol_iterator_reentry() { + let it; + let calls = 0; + const evil = { + [Symbol.iterator]() { + calls++; + assertThrows(TypeError, () => it.return()); + return [][Symbol.iterator](); + }, + }; + + it = Iterator.concat(evil); + const result = it.next(); + assert(calls, 1); + assert(result.done, true); + assert(result.value, undefined); +} + +function test_next_getter_reentry() { + let it; + let calls = 0; + const evil = { + [Symbol.iterator]() { + return { + get next() { + calls++; + assertThrows(TypeError, () => it.return()); + return () => ({ done: true, value: 1 }); + }, + }; + }, + }; + + it = Iterator.concat(evil); + const result = it.next(); + assert(calls, 1); + assert(result.done, true); + assert(result.value, undefined); +} + +function test_value_getter_reentry() { + let it; + let calls = 0; + const evil = { + [Symbol.iterator]() { + return { + next() { + return { + done: false, + get value() { + calls++; + assertThrows(TypeError, () => it.return()); + return 1; + }, + }; + }, + }; + }, + }; + + it = Iterator.concat(evil); + const result = it.next(); + assert(calls, 1); + assert(result.done, false); + assert(result.value, 1); +} + +test_symbol_iterator_reentry(); +test_next_getter_reentry(); +test_value_getter_reentry(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1430.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1430.js new file mode 100755 index 00000000..0b255fb6 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1430.js @@ -0,0 +1,17 @@ +import { assert } from "./assert.js"; + +const arr = [{ x: 0 }, { x: 1 }]; + +delete arr[1]; + +assert(arr.length, 2); +assert(1 in arr, false); +assert(arr[1], undefined); + +arr.push({ y: 2 }); + +assert(arr.length, 3); +assert(1 in arr, false); +assert(2 in arr, true); +assert(arr[1], undefined); +assert(arr[2].y, 2); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1468.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1468.js new file mode 100755 index 00000000..904f2ca9 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1468.js @@ -0,0 +1,25 @@ +// Bug: expand_fast_array calls max_int(new_len, new_size) where new_len is uint32_t. +// When new_len >= 0x80000000, cast to int makes it negative. +// max_int returns the small grow-by-50% size. Buffer is underallocated. +// add_fast_array_element then writes to values[new_len-1] — OOB write. +// +// Pre-fix behavior: process crashes with SIGBUS (OOB write to unmapped memory) +// Post-fix behavior: InternalError or RangeError thrown and caught cleanly +// +// Run: qjs poc_test_fixed.js +// Expected output: PASS: got graceful error: ... +const arr = [1, 2, 3]; +arr.length = 0x7FFFFFFF; + +try { + const result = arr.push(4); + // Succeeded via slow array path — no crash, no heap corruption + print("PASS: push completed without crash, result:", result); + +} catch(e) { + if (e instanceof InternalError || e instanceof RangeError || e instanceof TypeError) { + print("PASS: got graceful error:", e.message); + } else { + throw e; // unexpected — re-throw + } +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1498.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1498.js new file mode 100755 index 00000000..f618c794 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug1498.js @@ -0,0 +1,30 @@ +import { assert } from "./assert.js"; + +function test_invalid_number_literal_location() +{ + let error; + const source = + "function fun() {\n" + + " let a = 123bcd;\n" + + "}\n"; + + try { + eval(source); + } catch (e) { + error = e; + } + + assert(error instanceof SyntaxError); + assert(error.message, "invalid number literal"); + assert(error.stack.length >= 1); + assert(error.stack[0].getFileName(), ""); + assert(error.stack[0].getLineNumber(), 2); + assert(error.stack[0].getColumnNumber(), 13); +} + +Error.prepareStackTrace = (_, frames) => frames; +try { + test_invalid_number_literal_location(); +} finally { + Error.prepareStackTrace = undefined; +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug39/1.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug39/1.js new file mode 100755 index 00000000..9084ea2e --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug39/1.js @@ -0,0 +1,6 @@ +/*--- +flags: [qjs:track-promise-rejections] +---*/ + +Promise.reject().catch(() => print('oops')) +Promise.resolve().then(() => print('ok')) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug39/2.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug39/2.js new file mode 100755 index 00000000..a786a774 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug39/2.js @@ -0,0 +1,6 @@ +/*--- +flags: [qjs:track-promise-rejections] +---*/ + +const error = await Promise.resolve().then(() => Promise.reject('reject')).catch(e => e) +print('Got this error:', error) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug39/3.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug39/3.js new file mode 100755 index 00000000..aa13106f --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug39/3.js @@ -0,0 +1,7 @@ +/*--- +flags: [qjs:track-promise-rejections] +---*/ + +const promise = Promise.reject('reject') +const error = await Promise.resolve().then(() => promise).catch(e => e) +print('Got this error:', error) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug488-upstream.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug488-upstream.js new file mode 100755 index 00000000..a16de20a --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug488-upstream.js @@ -0,0 +1,7 @@ +// for-of with yield in iterable expression should not cause stack underflow +function* x() { + for (var e of yield []); +} +var g = x(); +g.next(); +g.return("test"); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug492.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug492.js new file mode 100755 index 00000000..128a3b29 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug492.js @@ -0,0 +1,113 @@ +import { assert } from "./assert.js"; + +// TypedArray.prototype.with must re-validate after user code in valueOf +// https://github.com/bellard/quickjs/issues/492 + +// Test 1: resize (shrink) during valueOf — no heap over-read +function test_resize_shrink() { + var ab = new ArrayBuffer(4096, { maxByteLength: 4096 }); + var ta = new Int32Array(ab); + for (var i = 0; i < ta.length; i++) ta[i] = 0x42424242; + + var result = ta.with(0, { + valueOf() { + ab.resize(4); + return 999; + } + }); + + assert(result[0] === 999); + // result should have original length with remaining elements zero-filled + assert(result.length === 1024); + assert(result[1] === 0); + assert(result[1023] === 0); +} + +// Test 2: detach during valueOf — must throw TypeError +function test_detach() { + var ab = new ArrayBuffer(16); + var ta = new Int32Array(ab); + ta[0] = 1; ta[1] = 2; + var caught = false; + try { + ta.with(0, { + valueOf() { + ab.transfer(); + return 999; + } + }); + } catch(e) { + caught = true; + assert(e instanceof TypeError); + } + assert(caught); +} + +// Test 3: resize to 0 during valueOf — must throw RangeError +// (RAB-tracking typed array is not OOB, but index is out of bounds) +function test_resize_zero() { + var ab = new ArrayBuffer(16, { maxByteLength: 16 }); + var ta = new Int32Array(ab); + ta[0] = 1; + var caught = false; + try { + ta.with(0, { + valueOf() { + ab.resize(0); + return 999; + } + }); + } catch(e) { + caught = true; + assert(e instanceof RangeError); + } + assert(caught); +} + +// Test 4: grow during valueOf — result should use original length +function test_resize_grow() { + var ab = new ArrayBuffer(16, { maxByteLength: 1024 }); + var ta = new Int32Array(ab); + ta[0] = 1; ta[1] = 2; ta[2] = 3; ta[3] = 4; + + var result = ta.with(0, { + valueOf() { + ab.resize(1024); + return 999; + } + }); + + assert(result.length === 4); + assert(result[0] === 999); + assert(result[1] === 2); + assert(result[2] === 3); + assert(result[3] === 4); +} + +// Test 5: normal case (no resize) still works +function test_normal() { + var ta = new Int32Array([10, 20, 30, 40]); + var result = ta.with(2, 99); + assert(result.length === 4); + assert(result[0] === 10); + assert(result[1] === 20); + assert(result[2] === 99); + assert(result[3] === 40); +} + +// Test 6: negative index uses original length +function test_negative_index() { + var ta = new Float64Array([1.5, 2.5, 3.5]); + var result = ta.with(-1, 9.9); + assert(result.length === 3); + assert(result[0] === 1.5); + assert(result[1] === 2.5); + assert(result[2] === 9.9); +} + +test_resize_shrink(); +test_detach(); +test_resize_zero(); +test_resize_grow(); +test_normal(); +test_negative_index(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug493.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug493.js new file mode 100755 index 00000000..06118cd6 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug493.js @@ -0,0 +1,10 @@ +// Iterator.prototype.map must not leak the original item +function* gen() { + for (let i = 0; i < 5; i++) { + yield { index: i }; + } +} + +const mapped = gen().map(x => x.index * 2); + +for (const val of mapped) {} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug633/0.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug633/0.js new file mode 100755 index 00000000..155d3a44 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug633/0.js @@ -0,0 +1,7 @@ +/*--- +flags: [qjs:no-detect-module] +negative: + phase: parse + type: SyntaxError +---*/ +const undefined = 42 // SyntaxError at global scope diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug633/1.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug633/1.js new file mode 100755 index 00000000..1aa83ba1 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug633/1.js @@ -0,0 +1,4 @@ +/*--- +flags: [qjs:no-detect-module, module] +---*/ +const undefined = 42 // not a SyntaxError at toplevel module scope diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug633/2.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug633/2.js new file mode 100755 index 00000000..70a3301d --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug633/2.js @@ -0,0 +1,4 @@ +/*--- +flags: [qjs:no-detect-module] +---*/ +{ const undefined = 42 } // not a SyntaxError, not at global scope diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug633/3.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug633/3.js new file mode 100755 index 00000000..2bfa1ce0 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug633/3.js @@ -0,0 +1,4 @@ +/*--- +flags: [qjs:no-detect-module] +---*/ +;(function() { const undefined = 42 })() // not a SyntaxError, not at global scope diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug645/0.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug645/0.js new file mode 100755 index 00000000..00bdac8d --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug645/0.js @@ -0,0 +1,4 @@ +"use strict"; + +const u8 = new Uint8Array(1); +u8[100] = 123; // Should not throw. diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug645/1.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug645/1.js new file mode 100755 index 00000000..8031be21 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug645/1.js @@ -0,0 +1,9 @@ +import { assert, assertThrows } from "../assert.js"; +const ab = new ArrayBuffer(1); +const u8 = new Uint8Array(ab); +assert(!ab.detached); +// Detach the ArrayBuffer. +ab.transfer(); +assert(ab.detached); +u8[100] = 123; // Doesn't throw. +assertThrows(TypeError, () => Object.defineProperty(u8, "100", { value: 123 })); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug645/2.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug645/2.js new file mode 100755 index 00000000..3076efa8 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug645/2.js @@ -0,0 +1,7 @@ +import { assert, assertThrows } from "../assert.js"; +const ab = new ArrayBuffer(16, { maxByteLength: 32 }); +const u8 = new Uint8Array(ab, 16); +ab.resize(8); +assert(ab.byteLength, 8); +u8[1] = 123; // Doesn't throw. +assertThrows(TypeError, () => Object.defineProperty(u8, "1", { value: 123 })); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug648.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug648.js new file mode 100755 index 00000000..cb0a7d38 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug648.js @@ -0,0 +1,13 @@ +/*--- +negative: + phase: runtime + type: Error +---*/ +let finrec = new FinalizationRegistry(v => {}) +let object = {object:"object"} +finrec.register(object, {held:"held"}, {token:"token"}) +object = undefined +// abrupt termination should not leak |held| +// unfortunately only shows up in qjs, not run-test262, +// but still good to have a regression test +throw Error("ok") diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug652.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug652.js new file mode 100755 index 00000000..27dea3bd --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug652.js @@ -0,0 +1,4 @@ +import { assert } from "./assert.js" +const ref = new WeakRef({}) +const val = ref.deref() // should not throw +assert(val, undefined) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug741.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug741.js new file mode 100755 index 00000000..3947f719 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug741.js @@ -0,0 +1,19 @@ +import {assert} from "./assert.js" + +while (1) label: break + +var i = 0 +while (i < 3) label: { + if (i > 0) + break + i++ +} +assert(i, 1) + +for (;;) label: break + +for (i = 0; i < 3; i++) label: { + if (i > 0) + break +} +assert(i, 1) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug775.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug775.js new file mode 100755 index 00000000..4cb9387e --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug775.js @@ -0,0 +1,7 @@ +/*--- +negative: + phase: runtime + type: RangeError +---*/ +function f() { f() } // was problematic under ASan +f() diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug776.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug776.js new file mode 100755 index 00000000..4b092c2b --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug776.js @@ -0,0 +1,7 @@ +/*--- +negative: + phase: runtime + type: RangeError +---*/ +function f() { f.apply(null) } // was problematic under ASan +f() diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug832.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug832.js new file mode 100755 index 00000000..7d7b8459 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug832.js @@ -0,0 +1,2 @@ +const m = await import("./empty.js") +print(m) // should not throw diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug858.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug858.js new file mode 100755 index 00000000..2b0ef2c4 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug858.js @@ -0,0 +1,26 @@ +import {assert} from "./assert.js"; + +Error.stackTraceLimit = Infinity; +assert(Error.stackTraceLimit === Infinity); +assert(new Error("error").stack.includes("bug858.js")); // stack should not be empty + +Error.stackTraceLimit = -Infinity; +assert(Error.stackTraceLimit === -Infinity); +assert(!new Error("error").stack.includes("bug858.js")); // stack should be empty + +Error.stackTraceLimit = NaN; +assert(Number.isNaN(Error.stackTraceLimit)); +assert(!new Error("error").stack.includes("bug858.js")); // stack should be empty + +Error.stackTraceLimit = -0; +assert(Object.is(Error.stackTraceLimit, -0)); +assert(!new Error("error").stack.includes("bug858.js")); // stack should be empty + +const obj = { valueOf() { throw "evil" } }; +Error.stackTraceLimit = obj; +assert(Error.stackTraceLimit === obj); +try { + throw new Error("fail") +} catch (e) { + assert(e.message.includes("fail")); +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug904.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug904.js new file mode 100755 index 00000000..baecafeb --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug904.js @@ -0,0 +1,6 @@ +import {assert, assertThrows} from "./assert.js" +let calls = 0 +Error.prepareStackTrace = function() { calls++ } +function f() { f() } +assertThrows(RangeError, f) +assert(calls, 0) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug988.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug988.js new file mode 100755 index 00000000..5f1027c2 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug988.js @@ -0,0 +1,7 @@ +import {assert} from "./assert.js" +const expected = [97,98,99] +const ab = new ArrayBuffer(0, {maxByteLength:3}) +const dv = new DataView(ab) +ab.resize(3) +for (const [i,v] of Object.entries(expected)) dv.setUint8(i, v) +for (const [i,v] of Object.entries(expected)) assert(v, dv.getUint8(i)) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug999.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug999.js new file mode 100755 index 00000000..28a3a6f0 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/bug999.js @@ -0,0 +1,3 @@ +function* f(r){ return r } // must return r +[...f({})] + diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/destructured-export.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/destructured-export.js new file mode 100755 index 00000000..a038c6ff --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/destructured-export.js @@ -0,0 +1,8 @@ +import { assert, assertArrayEquals } from "./assert.js"; +import * as mod from "./destructured-export.js"; + +export const { a, b, c } = { a: 1, b: 2, c: 3 }; +export const d = 4; + +assert(typeof mod === 'object'); +assertArrayEquals(Object.keys(mod), ["a", "b", "c", "d"]); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/0.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/0.js new file mode 100755 index 00000000..18a9109a --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/0.js @@ -0,0 +1 @@ +await undefined diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/1.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/1.js new file mode 100755 index 00000000..02122827 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/1.js @@ -0,0 +1,2 @@ +const p = Promise.resolve(42) +await p diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/2.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/2.js new file mode 100755 index 00000000..0b1d1f7b --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/2.js @@ -0,0 +1 @@ +await = 42 // parsed as classic script diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/3.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/3.js new file mode 100755 index 00000000..5b175e93 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/3.js @@ -0,0 +1,8 @@ +/*--- +negative: + phase: parse + type: SyntaxError +---*/ +// the import statement makes it a module but `await = 42` is a SyntaxError +import * as _ from "dummy" +await = 42 diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/4.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/4.js new file mode 100755 index 00000000..5713f31b --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/detect_module/4.js @@ -0,0 +1,3 @@ +// imports should classify it as a module, even when not at the top +os.now() +import * as os from "qjs:os" diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/empty.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/empty.js new file mode 100755 index 00000000..e69de29b diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/fix_set_array_length-uaf.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/fix_set_array_length-uaf.js new file mode 100755 index 00000000..5f4224d1 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/fix_set_array_length-uaf.js @@ -0,0 +1,6 @@ +// Crash — heap-use-after-free (confirmed with ASan) +const arr = [{a:1}, {b:2}, {c:3}, {d:4}, {e:5}]; +arr.length = 2; // frees elements 2-4 +arr.length = 5; // grows length back; count stays at 2 +arr.push({f:6}); // count jumps to 6; elements 2-4 are freed but readable +print(JSON.stringify(arr[3])); // reads freed memory diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/fixture_cyclic_import.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/fixture_cyclic_import.js new file mode 100755 index 00000000..bac80d8b --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/fixture_cyclic_import.js @@ -0,0 +1,2 @@ +import * as a from "./test_cyclic_import.js" +export function f(x) { return 2 * a.g(x) } diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/fixture_string_exports.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/fixture_string_exports.js new file mode 100755 index 00000000..f6439064 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/fixture_string_exports.js @@ -0,0 +1,12 @@ +// ES2020 string export names test fixture +export const regularExport = "regular"; +const value1 = "value-1"; +const value2 = "value-2"; + +// String export names (ES2020) +export { value1 as "string-export-1" }; +export { value2 as "string-export-2" }; + +// Mixed: regular and string exports +const mixed = "mixed-value"; +export { mixed as normalName, mixed as "string-name" }; diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/function_source.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/function_source.js new file mode 100755 index 00000000..640420af --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/function_source.js @@ -0,0 +1,14 @@ +"use strict" +const expect = "function f() { return 42 }" +function f() { return 42 } + +{ + const actual = f.toString() + if (actual !== expect) throw Error(actual) +} + +{ + const f = eval(expect + "f") + const actual = f.toString() + if (actual !== expect) throw Error(actual) +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/microbench.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/microbench.js new file mode 100755 index 00000000..c62b6320 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/microbench.js @@ -0,0 +1,1267 @@ +/* + * Javascript Micro benchmark + * + * Copyright (c) 2017-2019 Fabrice Bellard + * Copyright (c) 2017-2019 Charlie Gordon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +import * as std from "qjs:std"; +import * as os from "qjs:os"; + +function pad(str, n) { + str += ""; + while (str.length < n) + str += " "; + return str; +} + +function pad_left(str, n) { + str += ""; + while (str.length < n) + str = " " + str; + return str; +} + +function pad_center(str, n) { + str += ""; + while (str.length < n) { + if ((n - str.length) & 1) + str = str + " "; + else + str = " " + str; + } + return str; +} + +function toPrec(n, prec) { + var i, s; + for (i = 0; i < prec; i++) + n *= 10; + s = "" + Math.round(n); + for (i = s.length - prec; i <= 0; i++) + s = "0" + s; + if (prec > 0) + s = s.substring(0, i) + "." + s.substring(i); + return s; +} + +var ref_data; +var log_data; + +var heads = [ "TEST", "N", "TIME (ns)", "REF (ns)", "SCORE (%)" ]; +var widths = [ 22, 10, 9, 9, 9 ]; +var precs = [ 0, 0, 2, 2, 2 ]; +var total = [ 0, 0, 0, 0, 0 ]; +var total_score = 0; +var total_scale = 0; + +if (typeof console == "undefined") { + var console = { log: print }; +} + +function log_line() { + var i, n, s, a; + s = ""; + for (i = 0, n = arguments.length; i < n; i++) { + if (i > 0) + s += " "; + a = arguments[i]; + if (typeof a == "number") { + total[i] += a; + a = toPrec(a, precs[i]); + s += pad_left(a, widths[i]); + } else { + s += pad_left(a, widths[i]); + } + } + console.log(s); +} + +var clocks_per_sec = 1000000; +var max_iterations = 100; +var clock_threshold = 2000; /* favoring short measuring spans */ +var min_n_argument = 1; +var get_clock = os.cputime ?? os.now; + +function log_one(text, n, ti) { + var ref; + + if (ref_data) + ref = ref_data[text]; + else + ref = null; + + ti = Math.round(ti * 100) / 100; + log_data[text] = ti; + if (typeof ref === "number") { + log_line(text, n, ti, ref, ti * 100 / ref); + total_score += ti * 100 / ref; + total_scale += 100; + } else { + log_line(text, n, ti); + total_score += 100; + total_scale += 100; + } +} + +function bench(f, text) +{ + var i, j, n, t, t1, ti, nb_its, ref, ti_n, ti_n1, min_ti; + + nb_its = n = 1; + if (f.bench) { + ti_n = f(text); + } else { + ti_n = 1000000000; + min_ti = clock_threshold / 10; + for(i = 0; i < 30; i++) { + ti = 1000000000; + for (j = 0; j < max_iterations; j++) { + t = get_clock(); + while ((t1 = get_clock()) == t) + continue; + nb_its = f(n); + if (nb_its < 0) + return; // test failure + t1 = get_clock() - t1; + if (ti > t1) + ti = t1; + } + if (ti >= min_ti) { + ti_n1 = ti / nb_its; + if (ti_n > ti_n1) + ti_n = ti_n1; + } + if (ti >= clock_threshold && n >= min_n_argument) + break; + + n = n * [ 2, 2.5, 2 ][i % 3]; + } + // to use only the best timing from the last loop, uncomment below + //ti_n = ti / nb_its; + } + /* nano seconds per iteration */ + log_one(text, n, ti_n * 1e9 / clocks_per_sec); +} + +var global_res; /* to be sure the code is not optimized */ + +function empty_loop(n) { + var j; + for(j = 0; j < n; j++) { + } + return n; +} + +function date_now(n) { + var j; + for(j = 0; j < n; j++) { + Date.now(); + } + return n; +} + +function prop_read(n) +{ + var obj, sum, j; + obj = {a: 1, b: 2, c:3, d:4 }; + sum = 0; + for(j = 0; j < n; j++) { + sum += obj.a; + sum += obj.b; + sum += obj.c; + sum += obj.d; + } + global_res = sum; + return n * 4; +} + +function prop_write(n) +{ + var obj, j; + obj = {a: 1, b: 2, c:3, d:4 }; + for(j = 0; j < n; j++) { + obj.a = j; + obj.b = j; + obj.c = j; + obj.d = j; + } + return n * 4; +} + +function prop_create(n) +{ + var obj, j; + for(j = 0; j < n; j++) { + obj = new Object(); + obj.a = 1; + obj.b = 2; + obj.c = 3; + obj.d = 4; + } + return n * 4; +} + +function prop_delete(n) +{ + var obj, j; + obj = {}; + for(j = 0; j < n; j++) { + obj[j] = 1; + } + for(j = 0; j < n; j++) { + delete obj[j]; + } + return n; +} + +function array_read(n) +{ + var tab, len, sum, i, j; + tab = []; + len = 10; + for(i = 0; i < len; i++) + tab[i] = i; + sum = 0; + for(j = 0; j < n; j++) { + sum += tab[0]; + sum += tab[1]; + sum += tab[2]; + sum += tab[3]; + sum += tab[4]; + sum += tab[5]; + sum += tab[6]; + sum += tab[7]; + sum += tab[8]; + sum += tab[9]; + } + global_res = sum; + return len * n; +} + +function array_write(n) +{ + var tab, len, i, j; + tab = []; + len = 10; + for(i = 0; i < len; i++) + tab[i] = i; + for(j = 0; j < n; j++) { + tab[0] = j; + tab[1] = j; + tab[2] = j; + tab[3] = j; + tab[4] = j; + tab[5] = j; + tab[6] = j; + tab[7] = j; + tab[8] = j; + tab[9] = j; + } + return len * n; +} + +function array_prop_create(n) +{ + var tab, i, j, len; + len = 1000; + for(j = 0; j < n; j++) { + tab = []; + for(i = 0; i < len; i++) + tab[i] = i; + } + return len * n; +} + +function array_length_decr(n) +{ + var tab, i, j, len; + len = 1000; + tab = []; + for(i = 0; i < len; i++) + tab[i] = i; + for(j = 0; j < n; j++) { + for(i = len - 1; i >= 0; i--) + tab.length = i; + } + return len * n; +} + +function array_hole_length_decr(n) +{ + var tab, i, j, len; + len = 1000; + tab = []; + for(i = 0; i < len; i++) { + if (i != 3) + tab[i] = i; + } + for(j = 0; j < n; j++) { + for(i = len - 1; i >= 0; i--) + tab.length = i; + } + return len * n; +} + +function array_push(n) +{ + var tab, i, j, len; + len = 500; + for(j = 0; j < n; j++) { + tab = []; + for(i = 0; i < len; i++) + tab.push(i); + } + return len * n; +} + +function array_pop(n) +{ + var tab, i, j, len, sum; + len = 500; + for(j = 0; j < n; j++) { + tab = []; + for(i = 0; i < len; i++) + tab[i] = i; + sum = 0; + for(i = 0; i < len; i++) + sum += tab.pop(); + global_res = sum; + } + return len * n; +} + +function typed_array_read(n) +{ + var tab, len, sum, i, j; + len = 10; + tab = new Int32Array(len); + for(i = 0; i < len; i++) + tab[i] = i; + sum = 0; + for(j = 0; j < n; j++) { + sum += tab[0]; + sum += tab[1]; + sum += tab[2]; + sum += tab[3]; + sum += tab[4]; + sum += tab[5]; + sum += tab[6]; + sum += tab[7]; + sum += tab[8]; + sum += tab[9]; + } + global_res = sum; + return len * n; +} + +function typed_array_write(n) +{ + var tab, len, i, j; + len = 10; + tab = new Int32Array(len); + for(i = 0; i < len; i++) + tab[i] = i; + for(j = 0; j < n; j++) { + tab[0] = j; + tab[1] = j; + tab[2] = j; + tab[3] = j; + tab[4] = j; + tab[5] = j; + tab[6] = j; + tab[7] = j; + tab[8] = j; + tab[9] = j; + } + return len * n; +} + +var global_var0; + +function global_read(n) +{ + var sum, j; + global_var0 = 0; + sum = 0; + for(j = 0; j < n; j++) { + sum += global_var0; + sum += global_var0; + sum += global_var0; + sum += global_var0; + } + global_res = sum; + return n * 4; +} + +function global_write(n) +{ + var j; + for(j = 0; j < n; j++) { + global_var0 = j; + global_var0 = j; + global_var0 = j; + global_var0 = j; + } + return n * 4; +} + +function global_write_strict(n) +{ + "use strict"; + var j; + for(j = 0; j < n; j++) { + global_var0 = j; + global_var0 = j; + global_var0 = j; + global_var0 = j; + } + return n * 4; +} + +function local_destruct(n) +{ + var j, v1, v2, v3, v4; + var array = [ 1, 2, 3, 4, 5]; + var o = { a:1, b:2, c:3, d:4 }; + var a, b, c, d; + for(j = 0; j < n; j++) { + [ v1, v2,, v3, ...v4] = array; + ({ a, b, c, d } = o); + ({ a: a, b: b, c: c, d: d } = o); + } + return n * 12; +} + +var global_v1, global_v2, global_v3, global_v4; +var global_a, global_b, global_c, global_d; + +function global_destruct(n) +{ + var j, v1, v2, v3, v4; + var array = [ 1, 2, 3, 4, 5 ]; + var o = { a:1, b:2, c:3, d:4 }; + var a, b, c, d; + for(j = 0; j < n; j++) { + [ global_v1, global_v2,, global_v3, ...global_v4] = array; + ({ a: global_a, b: global_b, c: global_c, d: global_d } = o); + } + return n * 8; +} + +function global_destruct_strict(n) +{ + "use strict"; + var j, v1, v2, v3, v4; + var array = [ 1, 2, 3, 4, 5 ]; + var o = { a:1, b:2, c:3, d:4 }; + var a, b, c, d; + for(j = 0; j < n; j++) { + [ global_v1, global_v2,, global_v3, ...global_v4] = array; + ({ a: global_a, b: global_b, c: global_c, d: global_d } = o); + } + return n * 8; +} + +function func_call(n) +{ + function f(a) + { + return 1; + } + + var j, sum; + sum = 0; + for(j = 0; j < n; j++) { + sum += f(j); + sum += f(j); + sum += f(j); + sum += f(j); + } + global_res = sum; + return n * 4; +} + +function closure_var(n) +{ + function f(a) + { + sum++; + } + + var j, sum; + sum = 0; + for(j = 0; j < n; j++) { + f(j); + f(j); + f(j); + f(j); + } + global_res = sum; + return n * 4; +} + +function int_arith(n) +{ + var i, j, sum; + global_res = 0; + for(j = 0; j < n; j++) { + sum = 0; + for(i = 0; i < 1000; i++) { + sum += i * i; + } + global_res += sum; + } + return n * 1000; +} + +function float_arith(n) +{ + var i, j, sum, a, incr, a0; + global_res = 0; + a0 = 0.1; + incr = 1.1; + for(j = 0; j < n; j++) { + sum = 0; + a = a0; + for(i = 0; i < 1000; i++) { + sum += a * a; + a += incr; + } + global_res += sum; + } + return n * 1000; +} + +function bigint_arith(n, bits) +{ + var i, j, sum, a, incr, a0, sum0; + sum0 = global_res = BigInt(0); + a0 = BigInt(1) << BigInt(Math.floor((bits - 10) * 0.5)); + incr = BigInt(1); + for(j = 0; j < n; j++) { + sum = sum0; + a = a0; + for(i = 0; i < 1000; i++) { + sum += a * a; + a += incr; + } + global_res += sum; + } + return n * 1000; +} + +function bigint64_arith(n) +{ + return bigint_arith(n, 64); +} + +function bigint256_arith(n) +{ + return bigint_arith(n, 256); +} + +function map_set(n) +{ + var s, i, j, len = 100; + for(j = 0; j < n; j++) { + s = new Map(); + for(i = 0; i < len; i++) { + s.set(String(i), i); + } + for(i = 0; i < len; i++) { + if (!s.has(String(i))) + throw Error("bug in Map"); + } + } + return n * len; +} + +function map_delete(n) +{ + var a, i, j, len; + + len = 1000; + for(j = 0; j < n; j++) { + a = new Map(); + for(i = 0; i < len; i++) { + a.set(String(i), i); + } + for(i = 0; i < len; i++) { + a.delete(String(i)); + } + } + return len * n; +} + +function weak_map_set(n) +{ + var a, i, j, len, tab; + + len = 1000; + tab = []; + for(i = 0; i < len; i++) { + tab.push({ key: i }); + } + for(j = 0; j < n; j++) { + a = new WeakMap(); + for(i = 0; i < len; i++) { + a.set(tab[i], i); + } + } + return len * n; +} + +function weak_map_delete(n) +{ + var a, i, j, len, tab; + + len = 1000; + for(j = 0; j < n; j++) { + tab = []; + for(i = 0; i < len; i++) { + tab.push({ key: i }); + } + a = new WeakMap(); + for(i = 0; i < len; i++) { + a.set(tab[i], i); + } + for(i = 0; i < len; i++) { + tab[i] = null; + } + } + return len * n; +} + +function array_for(n) +{ + var r, i, j, sum; + r = []; + for(i = 0; i < 100; i++) + r[i] = i; + for(j = 0; j < n; j++) { + sum = 0; + for(i = 0; i < 100; i++) { + sum += r[i]; + } + global_res = sum; + } + return n * 100; +} + +function array_for_in(n) +{ + var r, i, j, sum; + r = []; + for(i = 0; i < 100; i++) + r[i] = i; + for(j = 0; j < n; j++) { + sum = 0; + for(i in r) { + sum += r[i]; + } + global_res = sum; + } + return n * 100; +} + +function array_for_of(n) +{ + var r, i, j, sum; + r = []; + for(i = 0; i < 100; i++) + r[i] = i; + for(j = 0; j < n; j++) { + sum = 0; + for(i of r) { + sum += i; + } + global_res = sum; + } + return n * 100; +} + +function math_min(n) +{ + var i, j, r; + r = 0; + for(j = 0; j < n; j++) { + for(i = 0; i < 1000; i++) + r = Math.min(i, 500); + global_res = r; + } + return n * 1000; +} + +function object_null(n) +{ + var j; + for(j = 0; j < n; j++) { + global_res = {__proto__: null}; + } + return n; +} + +function regexp_ascii(n) +{ + var i, j, r, s; + s = "the quick brown fox jumped over the lazy dog" + for(j = 0; j < n; j++) { + for(i = 0; i < 10000; i++) + r = /the quick brown fox/.exec(s) + global_res = r; + } + return n * 10000; +} + +function regexp_utf16(n) +{ + var i, j, r, s; + s = "the quick brown ᶠᵒˣ jumped over the lazy ᵈᵒᵍ" + for(j = 0; j < n; j++) { + for(i = 0; i < 10000; i++) + r = /the quick brown ᶠᵒˣ/.exec(s) + global_res = r; + } + return n * 10000; +} + +/* incremental string contruction as local var */ +function string_build1(n) +{ + var i, j, r; + r = ""; + for(j = 0; j < n; j++) { + for(i = 0; i < 100; i++) + r += "x"; + global_res = r; + } + return n * 100; +} + +/* incremental string contruction as arg */ +function string_build2(n, r) +{ + var i, j; + r = ""; + for(j = 0; j < n; j++) { + for(i = 0; i < 100; i++) + r += "x"; + global_res = r; + } + return n * 100; +} + +/* incremental string contruction by prepending */ +function string_build3(n, r) +{ + var i, j; + r = ""; + for(j = 0; j < n; j++) { + for(i = 0; i < 100; i++) + r = "x" + r; + global_res = r; + } + return n * 100; +} + +/* incremental string contruction with multiple reference */ +function string_build4(n) +{ + var i, j, r, s; + r = ""; + for(j = 0; j < n; j++) { + for(i = 0; i < 100; i++) { + s = r; + r += "x"; + } + global_res = r; + } + return n * 100; +} + +function string_slice1(n) +{ + var i, j, s; + s = "x".repeat(1<<16); + for (i = 0; i < n; i++) { + for (j = 0; j < 1000; j++) + s.slice(-1); // too short for JSStringSlice + } + return n * 1000; +} + +function string_slice2(n) +{ + var i, j, s; + s = "x".repeat(1<<16); + for (i = 0; i < n; i++) { + for (j = 0; j < 1000; j++) + s.slice(-1024); + } + return n * 1000; +} + +function string_slice3(n) +{ + var i, j, s; + s = "x".repeat(1<<16); + for (i = 0; i < n; i++) { + for (j = 0; j < 1000; j++) + s.slice(1); + } + return n * 1000; +} + +function string_concat(n, r) +{ + var i, f, xs; + // generate a function on the fly; splatting the arguments with + // "x".concat(...xs) spends too much time inside the splat itself + xs = "x".repeat(r).split("").map(_ => "'x'"); + f = new Function("", `'x'.concat(${ xs.join(",") })`); + for (i = 0; i < n; i++) + f(); + return n; +} + +function string_concat0(n) { + return string_concat(n, 0); +} + +function string_concat1(n) +{ + return string_concat(n, 1); +} + +function string_concat2(n) +{ + return string_concat(n, 32); +} + +function string_concat3(n) +{ + return string_concat(n, 256); +} + +/* sort bench */ + +function sort_bench(text) { + function random(arr, n, def) { + for (var i = 0; i < n; i++) + arr[i] = def[(Math.random() * n) >> 0]; + } + function random8(arr, n, def) { + for (var i = 0; i < n; i++) + arr[i] = def[(Math.random() * 256) >> 0]; + } + function random1(arr, n, def) { + for (var i = 0; i < n; i++) + arr[i] = def[(Math.random() * 2) >> 0]; + } + function hill(arr, n, def) { + var mid = n >> 1; + for (var i = 0; i < mid; i++) + arr[i] = def[i]; + for (var i = mid; i < n; i++) + arr[i] = def[n - i]; + } + function comb(arr, n, def) { + for (var i = 0; i < n; i++) + arr[i] = def[(i & 1) * i]; + } + function crisscross(arr, n, def) { + for (var i = 0; i < n; i++) + arr[i] = def[(i & 1) ? n - i : i]; + } + function zero(arr, n, def) { + for (var i = 0; i < n; i++) + arr[i] = def[0]; + } + function increasing(arr, n, def) { + for (var i = 0; i < n; i++) + arr[i] = def[i]; + } + function decreasing(arr, n, def) { + for (var i = 0; i < n; i++) + arr[i] = def[n - 1 - i]; + } + function alternate(arr, n, def) { + for (var i = 0; i < n; i++) + arr[i] = def[i ^ 1]; + } + function jigsaw(arr, n, def) { + for (var i = 0; i < n; i++) + arr[i] = def[i % (n >> 4)]; + } + function incbutone(arr, n, def) { + for (var i = 0; i < n; i++) + arr[i] = def[i]; + if (n > 0) + arr[n >> 2] = def[n]; + } + function incbutfirst(arr, n, def) { + if (n > 0) + arr[0] = def[n]; + for (var i = 1; i < n; i++) + arr[i] = def[i]; + } + function incbutlast(arr, n, def) { + for (var i = 0; i < n - 1; i++) + arr[i] = def[i + 1]; + if (n > 0) + arr[n - 1] = def[0]; + } + + var sort_cases = [ random, random8, random1, jigsaw, hill, comb, + crisscross, zero, increasing, decreasing, alternate, + incbutone, incbutlast, incbutfirst ]; + + var n = sort_bench.array_size || 10000; + var array_type = sort_bench.array_type || Array; + var def, arr; + var i, j, x, y; + var total = 0; + + var save_total_score = total_score; + var save_total_scale = total_scale; + + // initialize default sorted array (n + 1 elements) + def = new array_type(n + 1); + if (array_type == Array) { + for (i = 0; i <= n; i++) { + def[i] = i + ""; + } + } else { + for (i = 0; i <= n; i++) { + def[i] = i; + } + } + def.sort(); + for (var f of sort_cases) { + var ti = 0, tx = 0; + for (j = 0; j < 100; j++) { + arr = new array_type(n); + f(arr, n, def); + var t1 = get_clock(); + arr.sort(); + t1 = get_clock() - t1; + tx += t1; + if (!ti || ti > t1) + ti = t1; + if (tx >= clocks_per_sec) + break; + } + total += ti; + + i = 0; + x = arr[0]; + if (x !== void 0) { + for (i = 1; i < n; i++) { + y = arr[i]; + if (y === void 0) + break; + if (x > y) + break; + x = y; + } + } + while (i < n && arr[i] === void 0) + i++; + if (i < n) { + console.log("sort_bench: out of order error for " + f.name + + " at offset " + (i - 1) + + ": " + arr[i - 1] + " > " + arr[i]); + } + if (sort_bench.verbose) + log_one("sort_" + f.name, n, ti, n * 100); + } + total_score = save_total_score; + total_scale = save_total_scale; + return total / n / 1000; +} +sort_bench.bench = true; +sort_bench.verbose = false; + +function int_to_string(n) +{ + var s, r, j; + r = 0; + for(j = 0; j < n; j++) { + s = (j % 10) + ''; + s = (j % 100) + ''; + s = (j) + ''; + } + return n * 3; +} + +function int_toString(n) +{ + var s, r, j; + r = 0; + for(j = 0; j < n; j++) { + s = (j % 10).toString(); + s = (j % 100).toString(); + s = (j).toString(); + } + return n * 3; +} + +function float_to_string(n) +{ + var s, r, j; + r = 0; + for(j = 0; j < n; j++) { + s = (j % 10 + 0.1) + ''; + s = (j + 0.1) + ''; + s = (j * 12345678 + 0.1) + ''; + } + return n * 3; +} + +function float_toString(n) +{ + var s, r, j; + r = 0; + for(j = 0; j < n; j++) { + s = (j % 10 + 0.1).toString(); + s = (j + 0.1).toString(); + s = (j * 12345678 + 0.1).toString(); + } + return n * 3; +} + +function float_toFixed(n) +{ + var s, r, j; + r = 0; + for(j = 0; j < n; j++) { + s = (j % 10 + 0.1).toFixed(j % 16); + s = (j + 0.1).toFixed(j % 16); + s = (j * 12345678 + 0.1).toFixed(j % 16); + } + return n * 3; +} + +function float_toPrecision(n) +{ + var s, r, j; + r = 0; + for(j = 0; j < n; j++) { + s = (j % 10 + 0.1).toPrecision(j % 16 + 1); + s = (j + 0.1).toPrecision(j % 16 + 1); + s = (j * 12345678 + 0.1).toPrecision(j % 16 + 1); + } + return n * 3; +} + +function float_toExponential(n) +{ + var s, r, j; + r = 0; + for(j = 0; j < n; j++) { + s = (j % 10 + 0.1).toExponential(j % 16); + s = (j + 0.1).toExponential(j % 16); + s = (j * 12345678 + 0.1).toExponential(j % 16); + } + return n * 3; +} + +function string_to_int(n) +{ + var s, r, j; + r = 0; + s = "12345"; + r = 0; + for(j = 0; j < n; j++) { + r += (s | 0); + } + global_res = r; + return n; +} + +function string_to_float(n) +{ + var s, r, j; + r = 0; + s = "12345.6"; + r = 0; + for(j = 0; j < n; j++) { + r -= s; + } + global_res = r; + return n; +} + +function load_result(filename) +{ + var f, str, res; + if (typeof std === "undefined") + return null; + f = std.open(filename, "r"); + if (!f) + return null; + str = f.readAsString(); + res = JSON.parse(str); + f.close(); + return res; +} + +function save_result(filename, obj) +{ + var f; + if (typeof std === "undefined") + return; + f = std.open(filename, "w"); + f.puts(JSON.stringify(obj, null, 2)); + f.puts("\n"); + f.close(); +} + +function main(argc, argv, g) +{ + var test_list = [ + empty_loop, + date_now, + prop_read, + prop_write, + prop_create, + prop_delete, + array_read, + array_write, + array_prop_create, + array_length_decr, + array_hole_length_decr, + array_push, + array_pop, + typed_array_read, + typed_array_write, + global_read, + global_write, + global_write_strict, + local_destruct, + global_destruct, + global_destruct_strict, + func_call, + closure_var, + int_arith, + float_arith, + map_set, + map_delete, + weak_map_set, + weak_map_delete, + array_for, + array_for_in, + array_for_of, + math_min, + object_null, + regexp_ascii, + regexp_utf16, + string_build1, + string_build2, + //string_build3, + //string_build4, + string_concat0, + string_concat1, + string_concat2, + string_concat3, + string_slice1, + string_slice2, + string_slice3, + sort_bench, + int_to_string, + int_toString, + float_to_string, + float_toString, + float_toFixed, + float_toPrecision, + float_toExponential, + string_to_int, + string_to_float, + ]; + var tests = []; + var i, j, n, f, name, found; + + if (typeof BigInt == "function") { + /* BigInt test */ + test_list.push(bigint64_arith); + test_list.push(bigint256_arith); + } + + for (i = 1; i < argc;) { + name = argv[i++]; + if (name == "-a") { + sort_bench.verbose = true; + continue; + } + if (name == "-t") { + name = argv[i++]; + sort_bench.array_type = g[name]; + if (typeof sort_bench.array_type != "function") { + console.log("unknown array type: " + name); + return 1; + } + continue; + } + if (name == "-n") { + sort_bench.array_size = +argv[i++]; + continue; + } + for (j = 0, found = false; j < test_list.length; j++) { + f = test_list[j]; + if (f.name.startsWith(name)) { + tests.push(f); + found = true; + } + } + if (!found) { + console.log("unknown benchmark: " + name); + return 1; + } + } + if (tests.length == 0) + tests = test_list; + + ref_data = load_result("microbench.txt"); + log_data = {}; + log_line.apply(null, heads); + n = 0; + + for(i = 0; i < tests.length; i++) { + f = tests[i]; + bench(f, f.name, ref_data, log_data); + if (ref_data && ref_data[f.name]) + n++; + } + if (ref_data) + log_line("total", "", total[2], total[3], total_score * 100 / total_scale); + else + log_line("total", "", total[2]); + + if (tests == test_list) + save_result("microbench-new.txt", log_data); +} + +if (typeof scriptArgs === "undefined") { + scriptArgs = []; + if (typeof process.argv === "object") + scriptArgs = process.argv.slice(1); +} +main(scriptArgs.length, scriptArgs, this); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/null_or_undefined.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/null_or_undefined.js new file mode 100755 index 00000000..38d82550 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/null_or_undefined.js @@ -0,0 +1,38 @@ +import {assert} from "./assert.js" + +let ex +try { + null.x +} catch (e) { + ex = e +} +assert(ex instanceof TypeError) +assert(ex.message, "cannot read property 'x' of null") +ex = undefined + +try { + null["x"] +} catch (e) { + ex = e +} +assert(ex instanceof TypeError) +assert(ex.message, "cannot read property 'x' of null") +ex = undefined + +try { + undefined.x +} catch (e) { + ex = e +} +assert(ex instanceof TypeError) +assert(ex.message, "cannot read property 'x' of undefined") +ex = undefined + +try { + undefined["x"] +} catch (e) { + ex = e +} +assert(ex instanceof TypeError) +assert(ex.message, "cannot read property 'x' of undefined") +ex = undefined diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/str-pad-leak.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/str-pad-leak.js new file mode 100755 index 00000000..5511a699 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/str-pad-leak.js @@ -0,0 +1,5 @@ +var v1 = ''; +try { + var v2 = v1.padEnd(2147483620, 0); +} catch(_) {} + diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_array_to_gc.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_array_to_gc.js new file mode 100755 index 00000000..6351f290 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_array_to_gc.js @@ -0,0 +1,69 @@ +import * as std from "qjs:std"; +import { assert } from "./assert.js"; + +// The non-mutating array methods (with, toReversed, toSpliced, toSorted) +// allocate a fast array and then populate it by pulling values from the +// source via JS_TryGetPropertyInt64. When the source is an array-like with +// a property getter that triggers GC, the GC must see fully initialized +// slots — otherwise it would walk uninitialized JSValues in the newly +// allocated array. Run under ASAN to catch regressions. + +function makeArrayLike(length, getterIndex) { + const obj = { length }; + Object.defineProperty(obj, getterIndex, { + configurable: true, + get() { + std.gc(); + return 1; + }, + }); + return obj; +} + +// with +{ + const obj = makeArrayLike(256, 0); + Object.defineProperty(obj, 1, { + value: 2, + writable: true, + configurable: true, + }); + const res = Array.prototype.with.call(obj, 1, 9); + assert(res.length, 256); + assert(res[0], 1); + assert(res[1], 9); + assert(res[2], undefined); + assert(res[255], undefined); +} + +// toReversed +{ + const obj = makeArrayLike(256, 255); + const res = Array.prototype.toReversed.call(obj); + assert(res.length, 256); + assert(res[0], 1); + assert(res[1], undefined); + assert(res[255], undefined); +} + +// toSpliced +{ + const obj = makeArrayLike(256, 0); + const res = Array.prototype.toSpliced.call(obj, 1, 0, 7); + assert(res.length, 257); + assert(res[0], 1); + assert(res[1], 7); + assert(res[2], undefined); + assert(res[256], undefined); +} + +// toSorted +{ + const obj = makeArrayLike(256, 0); + const res = Array.prototype.toSorted.call(obj); + assert(res.length, 256); + // Sort places `undefined` at the end, so the single defined value (1) is first. + assert(res[0], 1); + assert(res[1], undefined); + assert(res[255], undefined); +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_base64.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_base64.js new file mode 100755 index 00000000..cfb3b87c --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_base64.js @@ -0,0 +1,95 @@ +import { assert, assertThrows } from "./assert.js"; + +function test_base64() { + function bytesToBinString(bytes) { + let s = ""; + for (let i = 0; i < bytes.length; i++) + s += String.fromCharCode(bytes[i] & 0xff); + return s; + } + + function canonicalizeBase64(s) { + const alpha = /[A-Za-z0-9+/=]/g; + let t = (s.match(alpha) || []).join(""); + t = t.replace(/=/g, ""); + while (t.length % 4 !== 0) t += "="; + return t; + } + + const A = globalThis.atob; + const B = globalThis.btoa; + + // 1) Canonical vectors + const vectors = [ + ["", ""], + ["f", "Zg=="], + ["fo", "Zm8="], + ["foo", "Zm9v"], + ["foob", "Zm9vYg=="], + ["fooba", "Zm9vYmE="], + ["foobar", "Zm9vYmFy"], + ["\x00", "AA=="], + ["\x00\x00", "AAA="], + ["\x00\x00\x00", "AAAA"], + ["\xE9", "6Q=="], // é + ]; + for (const [plain, b64] of vectors) { + assert(B(plain), b64, "btoa vector"); + assert(A(b64), plain, "atob vector"); + } + + // 2) Full-byte roundtrip + const allBytes = new Uint8Array(256); + for (let i = 0; i < 256; i++) allBytes[i] = i; + const binAll = bytesToBinString(allBytes); + assert(A(B(binAll)), binAll, "roundtrip 0..255"); + + // 3) Padding shapes + function expectPad(len) { + const u = new Uint8Array(len); + for (let i = 0; i < len; i++) u[i] = i & 255; + const s = bytesToBinString(u); + const b = B(s); + const padCount = (b.match(/=/g) || []).length; + const expected = (3 - (len % 3)) % 3; + assert(padCount, expected, "padding count"); + assert(b.length % 4, 0, "output multiple of 4"); + assert(A(b), s, "decoded payload mismatch"); + } + [0,1,2,3,4,5,6,7,8,9,10,255,256,257].forEach(expectPad); + + // 4) atob invalid/tolerant inputs + function expectInvalidOrCanonSame(inStr) { + let threw = false, got, canon; + try { got = A(inStr); } catch { threw = true; } + if (threw) return; + const norm = canonicalizeBase64(inStr); + canon = A(norm); + assert(got, canon, "tolerant must equal canonical"); + } + [ + "A", "AAA", "====", "A===", "Zg=", "Zg===", + "Zg====", // extra invalid padding + "Zm=8", "Zm9=v", "*m9v", "mØ9v" + ].forEach(expectInvalidOrCanonSame); + + // 5) Whitespace tolerance (spec requires ignoring) + assert(A(" Z g = = \n\t"), "f", "atob must ignore whitespace"); + assert(A("Zg\f=="), "f", "atob must ignore form feed"); + + // 6) Pure padding / weird empties + assert(A(""), "", "empty input"); + assertThrows(DOMException, () => A("===="), "pure padding must throw"); + + // 7) btoa invalid input (non-Latin1 must throw TypeError) + const badBtoa = ["💩", "𝌆", "\uD83D", "\uDC36", "\u0100"]; + for (const s of badBtoa) { + assertThrows(DOMException, () => B(s)); + } + + // 8) Sanity + assert(B("test"), "dGVzdA==", "btoa test"); + assert(A("dGVzdA=="), "test", "atob test"); +} + +test_base64(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_bigint.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_bigint.js new file mode 100755 index 00000000..4dc977f7 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_bigint.js @@ -0,0 +1,107 @@ +import { assert, assertThrows } from "./assert.js"; + + +function bigint_pow(a, n) +{ + var r, i; + r = 1n; + for(i = 0n; i < n; i++) + r *= a; + return r; +} + +/* a must be < b */ +function test_less(a, b) +{ + assert(a < b); + assert(!(b < a)); + assert(a <= b); + assert(!(b <= a)); + assert(b > a); + assert(!(a > b)); + assert(b >= a); + assert(!(a >= b)); + assert(a != b); + assert(!(a == b)); +} + +/* a must be numerically equal to b */ +function test_eq(a, b) +{ + assert(a == b); + assert(b == a); + assert(!(a != b)); + assert(!(b != a)); + assert(a <= b); + assert(b <= a); + assert(!(a < b)); + assert(a >= b); + assert(b >= a); + assert(!(a > b)); +} + +function test_bigint1() +{ + var a, r; + + test_less(2n, 3n); + test_eq(3n, 3n); + + test_less(2, 3n); + test_eq(3, 3n); + + test_less(2.1, 3n); + test_eq(Math.sqrt(4), 2n); + + a = bigint_pow(3n, 100n); + assert((a - 1n) != a); + assert(a, 515377520732011331036461129765621272702107522001n); + assert(a, 0x5a4653ca673768565b41f775d6947d55cf3813d1n); + + r = 1n << 31n; + assert(r, 2147483648n, "1 << 31n === 2147483648n"); + + r = 1n << 32n; + assert(r, 4294967296n, "1 << 32n === 4294967296n"); + + assert(String(-9223372036854775808n), "-9223372036854775808"); +} + +function test_bigint2() +{ + assert(BigInt(""), 0n); + assert(BigInt(" 123"), 123n); + assert(BigInt(" 123 "), 123n); + assertThrows(SyntaxError, () => { BigInt("+") } ); + assertThrows(SyntaxError, () => { BigInt("-") } ); + assertThrows(SyntaxError, () => { BigInt("\x00a") } ); + assertThrows(SyntaxError, () => { BigInt(" 123 r") } ); +} + +function test_bigint_map() +{ + var m = new Map(); + assert(m.size, 0); + + for (let i = 0n; i < 1337n; i++) { + const r = m.set(i, i.toString()); + assert(r, m); + } + assert(m.size, 1337); + + for (let i = 0n; i < 1337n; i++) { + const r = m.get(i); + assert(r, i.toString()); + } + assert(m.get(1337n), undefined); + assert(m.size, 1337); + + for (let i = 0n; i < 1337n; i++) + assert(m.delete(i)); + assert(!m.delete(1337n)); + assert(m.size, 0); +} + +test_bigint1(); +test_bigint2(); +test_bigint_map(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_bjson.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_bjson.js new file mode 100755 index 00000000..fff1a9a5 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_bjson.js @@ -0,0 +1,366 @@ +import * as std from "qjs:std"; +import * as bjson from "qjs:bjson"; +import { assert } from "./assert.js"; + +function base64decode(s) { + var A = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var n = s.indexOf("="); + if (n < 0) n = s.length; + if (n & 3 === 1) throw Error("bad base64"); // too much padding + var r = new Uint8Array(3 * (n>>2) + (n>>1 & 1) + (n & 1)); + var a, b, c, d, i, j; + a = b = c = d = i = j = 0; + while (i+3 < n) { + a = A.indexOf(s[i++]); + b = A.indexOf(s[i++]); + c = A.indexOf(s[i++]); + d = A.indexOf(s[i++]); + if (~63 & (a|b|c|d)) throw Error("bad base64"); + r[j++] = a<<2 | b>>4; + r[j++] = 255 & b<<4 | c>>2; + r[j++] = 255 & c<<6 | d; + } + switch (n & 3) { + case 2: + a = A.indexOf(s[i++]); + b = A.indexOf(s[i++]); + if (~63 & (a|b)) throw Error("bad base64"); + if (b & 15) throw Error("bad base64"); + r[j++] = a<<2 | b>>4; + break; + case 3: + a = A.indexOf(s[i++]); + b = A.indexOf(s[i++]); + c = A.indexOf(s[i++]); + if (~63 & (a|b|c)) throw Error("bad base64"); + if (c & 3) throw Error("bad base64"); + r[j++] = a<<2 | b>>4; + r[j++] = 255 & b<<4 | c>>2; + break; + } + return r.buffer; +} + +function toHex(a) +{ + var i, s = "", tab, v; + tab = new Uint8Array(a); + for(i = 0; i < tab.length; i++) { + v = tab[i].toString(16); + if (v.length < 2) + v = "0" + v; + if (i !== 0) + s += " "; + s += v; + } + return s; +} + +function isArrayLike(a) +{ + return Array.isArray(a) || + (a instanceof Uint8ClampedArray) || + (a instanceof Uint8Array) || + (a instanceof Uint16Array) || + (a instanceof Uint32Array) || + (a instanceof Int8Array) || + (a instanceof Int16Array) || + (a instanceof Int32Array) || + (a instanceof Float16Array) || + (a instanceof Float32Array) || + (a instanceof Float64Array); +} + +function toStr(a) +{ + var s, i, props, prop; + + switch(typeof(a)) { + case "object": + if (a === null) + return "null"; + if (a instanceof Date) { + s = "Date(" + toStr(a.valueOf()) + ")"; + } else if (a instanceof Number) { + s = "Number(" + toStr(a.valueOf()) + ")"; + } else if (a instanceof String) { + s = "String(" + toStr(a.valueOf()) + ")"; + } else if (a instanceof Boolean) { + s = "Boolean(" + toStr(a.valueOf()) + ")"; + } else if (isArrayLike(a)) { + s = "["; + for(i = 0; i < a.length; i++) { + if (i != 0) + s += ","; + s += toStr(a[i]); + } + s += "]"; + } else { + props = Object.keys(a); + s = "{"; + for(i = 0; i < props.length; i++) { + if (i != 0) + s += ","; + prop = props[i]; + s += prop + ":" + toStr(a[prop]); + } + s += "}"; + } + return s; + case "undefined": + return "undefined"; + case "string": + return JSON.stringify(a); + case "number": + if (a == 0 && 1 / a < 0) + return "-0"; + else + return a.toString(); + break; + default: + return a.toString(); + } +} + +function bjson_test(a) +{ + var buf, r, a_str, r_str; + a_str = toStr(a); + buf = bjson.write(a); + if (0) { + print(a_str, "->", toHex(buf)); + } + r = bjson.read(buf, 0, buf.byteLength); + r_str = toStr(r); + if (a_str != r_str) { + print(a_str); + print(r_str); + assert(false); + } +} + +function bjson_test_arraybuffer() +{ + var buf, array_buffer; + + array_buffer = new ArrayBuffer(4); + assert(array_buffer.byteLength, 4); + assert(array_buffer.maxByteLength, 4); + assert(array_buffer.resizable, false); + buf = bjson.write(array_buffer); + array_buffer = bjson.read(buf, 0, buf.byteLength); + assert(array_buffer.byteLength, 4); + assert(array_buffer.maxByteLength, 4); + assert(array_buffer.resizable, false); + + array_buffer = new ArrayBuffer(4, {maxByteLength: 4}); + assert(array_buffer.byteLength, 4); + assert(array_buffer.maxByteLength, 4); + assert(array_buffer.resizable, true); + buf = bjson.write(array_buffer); + array_buffer = bjson.read(buf, 0, buf.byteLength); + assert(array_buffer.byteLength, 4); + assert(array_buffer.maxByteLength, 4); + assert(array_buffer.resizable, true); + + array_buffer = new ArrayBuffer(4, {maxByteLength: 8}); + assert(array_buffer.byteLength, 4); + assert(array_buffer.maxByteLength, 8); + assert(array_buffer.resizable, true); + buf = bjson.write(array_buffer); + array_buffer = bjson.read(buf, 0, buf.byteLength); + assert(array_buffer.byteLength, 4); + assert(array_buffer.maxByteLength, 8); + assert(array_buffer.resizable, true); +} + +/* test multiple references to an object including circular + references */ +function bjson_test_reference() +{ + var array, buf, i, n, array_buffer; + n = 16; + array = []; + for(i = 0; i < n; i++) + array[i] = {}; + array_buffer = new ArrayBuffer(n); + for(i = 0; i < n; i++) { + array[i].next = array[(i + 1) % n]; + array[i].idx = i; + array[i].typed_array = new Uint8Array(array_buffer, i, 1); + } + buf = bjson.write(array, bjson.WRITE_OBJ_REFERENCE); + + array = bjson.read(buf, 0, buf.byteLength, bjson.READ_OBJ_REFERENCE); + + /* check the result */ + for(i = 0; i < n; i++) { + assert(array[i].next, array[(i + 1) % n]); + assert(array[i].idx, i); + assert(array[i].typed_array.buffer, array_buffer); + assert(array[i].typed_array.length, 1); + assert(array[i].typed_array.byteOffset, i); + } +} + +function bjson_test_regexp() +{ + var buf, r; + + bjson_test(/xyzzy/); + bjson_test(/xyzzy/digu); + + buf = bjson.write(/(?<𝓓𝓸𝓰>dog)/); + r = bjson.read(buf, 0, buf.byteLength); + assert("sup dog".match(r).groups["𝓓𝓸𝓰"], "dog"); +} + +function bjson_test_map() +{ + var buf, r, xs; + + xs = [["key", "value"]]; + buf = bjson.write(new Map(xs)); + r = bjson.read(buf, 0, buf.byteLength); + assert(r instanceof Map); + assert([...r].toString(), xs.toString()); +} + +function bjson_test_set() +{ + var buf, r, xs; + + xs = ["one", "two", "three"]; + buf = bjson.write(new Set(xs)); + r = bjson.read(buf, 0, buf.byteLength); + assert(r instanceof Set); + assert([...r].toString(), xs.toString()); +} + +function bjson_test_symbol() +{ + var buf, r, o; + + o = {[Symbol.toStringTag]: "42"}; + buf = bjson.write(o); + r = bjson.read(buf, 0, buf.byteLength); + assert(o.toString(), r.toString()); + + o = Symbol('foo'); + buf = bjson.write(o); + r = bjson.read(buf, 0, buf.byteLength); + assert(o.toString(), r.toString()); + assert(o !== r); + + o = Symbol.for('foo'); + buf = bjson.write(o); + r = bjson.read(buf, 0, buf.byteLength); + assert(o, r); + + o = Symbol.toStringTag; + buf = bjson.write(o); + r = bjson.read(buf, 0, buf.byteLength); + assert(o, r); +} + +function bjson_test_bytecode() +{ + var buf, o, r, e, i; + + o = std.evalScript(";(function f(o){ return o.i })", {compile_only: true}); + buf = bjson.write(o, bjson.WRITE_OBJ_BYTECODE); + try { + bjson.read(buf, 0, buf.byteLength); + } catch (_e) { + e = _e; + } + assert(String(e), "SyntaxError: no bytecode allowed"); + + o = bjson.read(buf, 0, buf.byteLength, bjson.READ_OBJ_BYTECODE); + assert(String(o), "[function bytecode]"); + o = std.evalScript(o, {eval_function: true}); + for (i = 0; i < 42; i++) o({i}); // exercise o.i IC +} + +function bjson_test_fuzz() +{ + var corpus = [ + ["Gv////8QAAAAAARg"], + ["Gv/////m5uaCLQ=="], + ["Gv////8AEQATBgYGBgYGBgYGBgb/////EAARAC8R/78vEf+/"], + ["Gv////8ACH8ACv////9//////////////////////////////9//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAA+fn5+fn5+fn5+fn5AAAAAAAGAKs="], + ["Gv////8ADgAAABQA=", bjson.READ_OBJ_REFERENCE], + ]; + for (var [input, flags] of corpus) { + var buf = base64decode(input); + try { + bjson.read(buf, 0, buf.byteLength, flags); + } catch (e) { + if (/invalid version/.test(e.message)) throw e; // corpus needs update + if (/checksum error/.test(e.message)) throw e; + } + } +} + +function bjson_test_csum() +{ + var buf = bjson.write("fortytwo"); + var tab = new Uint8Array(buf); + for (var i = 5; i < tab.length; i++) { + for (var k = 0; k < 256; k++) { + var t = tab[i]; + if (t == k) + continue; + tab[i] = k; + var caught = false; + try { + bjson.read(buf, 0, buf.byteLength); + } catch (e) { + caught = /checksum error/.test(e.message); + } + assert(caught); + tab[i] = t; + } + } +} + +function bjson_test_all() +{ + var obj; + + bjson_test({x:1, y:2, if:3}); + bjson_test([1, 2, 3]); + bjson_test([1.0, "aa", true, false, undefined, null, NaN, -Infinity, -0.0]); + if (typeof BigInt !== "undefined") { + bjson_test([BigInt("1"), -BigInt("0x123456789"), + BigInt("0x123456789abcdef123456789abcdef")]); + } + + bjson_test([new Date(1234), new String("abc"), new Number(-12.1), new Boolean(true)]); + + bjson_test(new Int32Array([123123, 222111, -32222])); + bjson_test(new Float16Array([1024, 1024.5])); + bjson_test(new Float64Array([123123, 222111.5])); + + /* tested with a circular reference */ + obj = {}; + obj.x = obj; + try { + bjson.write(obj); + assert(false); + } catch(e) { + assert(e instanceof TypeError); + } + + bjson_test_arraybuffer(); + bjson_test_reference(); + bjson_test_regexp(); + bjson_test_map(); + bjson_test_set(); + bjson_test_symbol(); + bjson_test_bytecode(); + bjson_test_fuzz(); + bjson_test_csum(); +} + +bjson_test_all(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_builtin.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_builtin.js new file mode 100755 index 00000000..02acc17c --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_builtin.js @@ -0,0 +1,1314 @@ +import * as os from "qjs:os"; +import { assert, assertThrows } from "./assert.js"; + +// Keep this at the top; it tests source positions. +function test_exception_source_pos() +{ + var e; + + try { + throw new Error(""); // line 10, column 19 + } catch(_e) { + e = _e; + } + + assert(e.stack.includes("test_builtin.js:10:19")); +} + +// Keep this at the top; it tests source positions. +function test_function_source_pos() // line 19, column 1 +{ + function inner() {} // line 21, column 5 + var f = eval("function f() {} f"); + assert(`${test_function_source_pos.lineNumber}:${test_function_source_pos.columnNumber}`, "19:1"); + assert(`${inner.lineNumber}:${inner.columnNumber}`, "21:5"); + assert(`${f.lineNumber}:${f.columnNumber}`, "1:1"); +} + +// Keep this at the top; it tests source positions. +function test_exception_prepare_stack() +{ + var e; + + Error.prepareStackTrace = (_, frames) => { + // Just return the array to check. + return frames; + }; + + try { + throw new Error(""); // line 39, column 19 + } catch(_e) { + e = _e; + } + + Error.prepareStackTrace = undefined; + + assert(e.stack.length, 2); + const f = e.stack[0]; + assert(f.getFunctionName(), 'test_exception_prepare_stack'); + assert(f.getFileName().endsWith('test_builtin.js')); + assert(f.getLineNumber(), 39); + assert(f.getColumnNumber(), 19); + assert(!f.isNative()); +} + +// Keep this at the top; it tests source positions. +function test_exception_stack_size_limit() +{ + var e; + + Error.stackTraceLimit = 1; + Error.prepareStackTrace = (_, frames) => { + // Just return the array to check. + return frames; + }; + + try { + throw new Error(""); // line 67, column 19 + } catch(_e) { + e = _e; + } + + Error.stackTraceLimit = 10; + Error.prepareStackTrace = undefined; + + assert(e.stack.length, 1); + const f = e.stack[0]; + assert(f.getFunctionName(), 'test_exception_stack_size_limit'); + assert(f.getFileName().endsWith('test_builtin.js')); + assert(f.getLineNumber(), 67); + assert(f.getColumnNumber(), 19); + assert(!f.isNative()); +} + +function test_exception_capture_stack_trace() +{ + var o = {}; + + assertThrows(TypeError, (function() { + Error.captureStackTrace(); + })); + + Error.captureStackTrace(o); + + assert(typeof o.stack === 'string'); + assert(o.stack.includes('test_exception_capture_stack_trace')); +} + +function test_exception_capture_stack_trace_filter() +{ + var o = {}; + const fun1 = () => { fun2(); }; + const fun2 = () => { fun3(); }; + const fun3 = () => { log_stack(); }; + function log_stack() { + Error.captureStackTrace(o, fun3); + } + fun1(); + + Error.captureStackTrace(o); + + assert(!o.stack.includes('fun3')); + assert(!o.stack.includes('log_stack')); +} + +function my_func(a, b) +{ + return a + b; +} + +function test_function() +{ + function f(a, b) { + var i, tab = []; + tab.push(this); + for(i = 0; i < arguments.length; i++) + tab.push(arguments[i]); + return tab; + } + function constructor1(a) { + this.x = a; + } + + var r, g; + + r = my_func.call(null, 1, 2); + assert(r, 3, "call"); + + r = my_func.apply(null, [1, 2]); + assert(r, 3, "apply"); + + r = (function () { return 1; }).apply(null, undefined); + assert(r, 1); + + assertThrows(TypeError, (function() { + Reflect.apply((function () { return 1; }), null, undefined); + })); + + r = new Function("a", "b", "return a + b;"); + assert(r(2,3), 5, "function"); + + g = f.bind(1, 2); + assert(g.length, 1); + assert(g.name, "bound f"); + assert(g(3), [1,2,3]); + + g = constructor1.bind(null, 1); + r = new g(); + assert(r.x, 1); +} + +function test() +{ + var r, a, b, c, err; + + r = Error("hello"); + assert(r.message, "hello", "Error"); + + a = new Object(); + a.x = 1; + assert(a.x, 1, "Object"); + + assert(Object.getPrototypeOf(a), Object.prototype, "getPrototypeOf"); + Object.defineProperty(a, "y", { value: 3, writable: true, configurable: true, enumerable: true }); + assert(a.y, 3, "defineProperty"); + + Object.defineProperty(a, "z", { get: function () { return 4; }, set: function(val) { this.z_val = val; }, configurable: true, enumerable: true }); + assert(a.z, 4, "get"); + a.z = 5; + assert(a.z_val, 5, "set"); + + a = { get z() { return 4; }, set z(val) { this.z_val = val; } }; + assert(a.z, 4, "get"); + a.z = 5; + assert(a.z_val, 5, "set"); + + b = Object.create(a); + assert(Object.getPrototypeOf(b), a, "create"); + c = {u:2}; + /* XXX: refcount bug in 'b' instead of 'a' */ + Object.setPrototypeOf(a, c); + assert(Object.getPrototypeOf(a), c, "setPrototypeOf"); + + a = {}; + assert(a.toString(), "[object Object]", "toString"); + + a = {x:1}; + assert(Object.isExtensible(a), true, "extensible"); + Object.preventExtensions(a); + + err = false; + try { + a.y = 2; + } catch(e) { + err = true; + } + assert(Object.isExtensible(a), false, "extensible"); + assert(typeof a.y, "undefined", "extensible"); + assert(err, true, "extensible"); + + assertThrows(TypeError, () => Object.setPrototypeOf(Object.prototype, {})); +} + +function test_enum() +{ + var a, tab; + a = {x:1, + "18014398509481984": 1, + "9007199254740992": 1, + "9007199254740991": 1, + "4294967296": 1, + "4294967295": 1, + y:1, + "4294967294": 1, + "1": 2}; + tab = Object.keys(a); +// console.log("tab=" + tab.toString()); + assert(tab, ["1","4294967294","x","18014398509481984","9007199254740992","9007199254740991","4294967296","4294967295","y"], "keys"); +} + +function test_array() +{ + var a, err; + + a = [1, 2, 3]; + assert(a.length, 3, "array"); + assert(a[2], 3, "array1"); + + a = new Array(10); + assert(a.length, 10, "array2"); + + a = new Array(1, 2); + assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array3"); + + a = [1, 2, 3]; + a.length = 2; + assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array4"); + + a = []; + a[1] = 10; + a[4] = 3; + assert(a.length, 5); + + a = [1,2]; + a.length = 5; + a[4] = 1; + a.length = 4; + assert(a[4] !== 1, true, "array5"); + + a = [1,2]; + a.push(3,4); + assert(a.join(), "1,2,3,4", "join"); + + a = [1,2,3,4,5]; + Object.defineProperty(a, "3", { configurable: false }); + err = false; + try { + a.length = 2; + } catch(e) { + err = true; + } + assert(err && a.toString() === "1,2,3,4"); +} + +function test_string() +{ + var a; + a = String("abc"); + assert(a.length, 3, "string"); + assert(a[1], "b", "string"); + assert(a.charCodeAt(1), 0x62, "string"); + assert(String.fromCharCode(65), "A", "string"); + assert(String.fromCharCode.apply(null, [65, 66, 67]), "ABC", "string"); + assert(a.charAt(1), "b"); + assert(a.charAt(-1), ""); + assert(a.charAt(3), ""); + + a = "abcd"; + assert(a.substring(1, 3), "bc", "substring"); + a = String.fromCharCode(0x20ac); + assert(a.charCodeAt(0), 0x20ac, "unicode"); + assert(a, "€", "unicode"); + assert(a, "\u20ac", "unicode"); + assert(a, "\u{20ac}", "unicode"); + assert("a", "\x61", "unicode"); + + a = "\u{10ffff}"; + assert(a.length, 2, "unicode"); + assert(a, "\u{dbff}\u{dfff}", "unicode"); + assert(a.codePointAt(0), 0x10ffff); + assert(String.fromCodePoint(0x10ffff), a); + + assert("a".concat("b", "c"), "abc"); + + assert("abcabc".indexOf("cab"), 2); + assert("abcabc".indexOf("cab2"), -1); + assert("abc".indexOf("c"), 2); + + assert("aaa".indexOf("a"), 0); + assert("aaa".indexOf("a", NaN), 0); + assert("aaa".indexOf("a", -Infinity), 0); + assert("aaa".indexOf("a", -1), 0); + assert("aaa".indexOf("a", -0), 0); + assert("aaa".indexOf("a", 0), 0); + assert("aaa".indexOf("a", 1), 1); + assert("aaa".indexOf("a", 2), 2); + assert("aaa".indexOf("a", 3), -1); + assert("aaa".indexOf("a", 4), -1); + assert("aaa".indexOf("a", Infinity), -1); + + assert("aaa".indexOf(""), 0); + assert("aaa".indexOf("", NaN), 0); + assert("aaa".indexOf("", -Infinity), 0); + assert("aaa".indexOf("", -1), 0); + assert("aaa".indexOf("", -0), 0); + assert("aaa".indexOf("", 0), 0); + assert("aaa".indexOf("", 1), 1); + assert("aaa".indexOf("", 2), 2); + assert("aaa".indexOf("", 3), 3); + assert("aaa".indexOf("", 4), 3); + assert("aaa".indexOf("", Infinity), 3); + + assert("aaa".lastIndexOf("a"), 2); + assert("aaa".lastIndexOf("a", NaN), 2); + assert("aaa".lastIndexOf("a", -Infinity), 0); + assert("aaa".lastIndexOf("a", -1), 0); + assert("aaa".lastIndexOf("a", -0), 0); + assert("aaa".lastIndexOf("a", 0), 0); + assert("aaa".lastIndexOf("a", 1), 1); + assert("aaa".lastIndexOf("a", 2), 2); + assert("aaa".lastIndexOf("a", 3), 2); + assert("aaa".lastIndexOf("a", 4), 2); + assert("aaa".lastIndexOf("a", Infinity), 2); + + assert("aaa".lastIndexOf(""), 3); + assert("aaa".lastIndexOf("", NaN), 3); + assert("aaa".lastIndexOf("", -Infinity), 0); + assert("aaa".lastIndexOf("", -1), 0); + assert("aaa".lastIndexOf("", -0), 0); + assert("aaa".lastIndexOf("", 0), 0); + assert("aaa".lastIndexOf("", 1), 1); + assert("aaa".lastIndexOf("", 2), 2); + assert("aaa".lastIndexOf("", 3), 3); + assert("aaa".lastIndexOf("", 4), 3); + assert("aaa".lastIndexOf("", Infinity), 3); + + assert("a,b,c".split(","), ["a","b","c"]); + assert(",b,c".split(","), ["","b","c"]); + assert("a,b,".split(","), ["a","b",""]); + + assert("aaaa".split(), [ "aaaa" ]); + assert("aaaa".split(undefined, 0), [ ]); + assert("aaaa".split(""), [ "a", "a", "a", "a" ]); + assert("aaaa".split("", 0), [ ]); + assert("aaaa".split("", 1), [ "a" ]); + assert("aaaa".split("", 2), [ "a", "a" ]); + assert("aaaa".split("a"), [ "", "", "", "", "" ]); + assert("aaaa".split("a", 2), [ "", "" ]); + assert("aaaa".split("aa"), [ "", "", "" ]); + assert("aaaa".split("aa", 0), [ ]); + assert("aaaa".split("aa", 1), [ "" ]); + assert("aaaa".split("aa", 2), [ "", "" ]); + assert("aaaa".split("aaa"), [ "", "a" ]); + assert("aaaa".split("aaaa"), [ "", "" ]); + assert("aaaa".split("aaaaa"), [ "aaaa" ]); + assert("aaaa".split("aaaaa", 0), [ ]); + assert("aaaa".split("aaaaa", 1), [ "aaaa" ]); + + assert(eval('"\0"'), "\0"); + + assert("abc".padStart(Infinity, ""), "abc"); + + assert(qjs.getStringKind("xyzzy".slice(1)), + /*JS_STRING_KIND_NORMAL*/0); + assert(qjs.getStringKind("xyzzy".repeat(512).slice(1)), + /*JS_STRING_KIND_SLICE*/1); +} + +function rope_concat(n, dir) +{ + var i, s; + s = ""; + if (dir > 0) { + for(i = 0; i < n; i++) + s += String.fromCharCode(i & 0xffff); + } else { + for(i = n - 1; i >= 0; i--) + s = String.fromCharCode(i & 0xffff) + s; + } + + for(i = 0; i < n; i++) { + /* test before the assert to go faster */ + if (s.charCodeAt(i) != (i & 0xffff)) { + assert(s.charCodeAt(i), i & 0xffff); + } + } +} + +function test_rope() +{ + var i, s, s2; + + /* test forward and backward concatenation */ + rope_concat(100000, 1); + rope_concat(100000, -1); + + /* test rope comparison */ + s = ""; + s2 = ""; + for (i = 0; i < 10000; i++) { + s += "abc"; + s2 += "abc"; + } + assert(s === s2, true); + assert(s < s2, false); + assert(s > s2, false); + + /* test rope indexing */ + s = ""; + for (i = 0; i < 10000; i++) + s += "x"; + assert(s.length, 10000); + assert(s[0], "x"); + assert(s[5000], "x"); + assert(s[9999], "x"); + + /* test rope with string methods */ + s = ""; + for (i = 0; i < 1000; i++) + s += "test"; + assert(s.indexOf("test"), 0); + assert(s.lastIndexOf("test"), 3996); + assert(s.includes("test"), true); + assert(s.slice(0, 8), "testtest"); + assert(s.substring(0, 8), "testtest"); +} + +function test_math() +{ + var a; + a = 1.4; + assert(Math.floor(a), 1); + assert(Math.ceil(a), 2); + assert(Math.imul(0x12345678, 123), -1088058456); + assert(Math.imul(0xB505, 0xB504), 2147441940); + assert(Math.imul(0xB505, 0xB505), -2147479015); + assert(Math.imul((-2)**31, (-2)**31), 0); + assert(Math.imul(2**31-1, 2**31-1), 1); + assert(Math.fround(0.1), 0.10000000149011612); + assert(Math.hypot(), 0); + assert(Math.hypot(-2), 2); + assert(Math.hypot(3, 4), 5); + assert(Math.abs(Math.hypot(3, 4, 5) - 7.0710678118654755) <= 1e-15); + assert(Math.sumPrecise([1,Number.EPSILON/2,Number.MIN_VALUE]), 1.0000000000000002); +} + +function test_number() +{ + assert(parseInt("123"), 123); + assert(parseInt(" 123r"), 123); + assert(parseInt("0x123"), 0x123); + assert(parseInt("0o123"), 0); + assert(+" 123 ", 123); + assert(+"0b111", 7); + assert(+"0o123", 83); + assert(parseFloat("2147483647"), 2147483647); + assert(parseFloat("2147483648"), 2147483648); + assert(parseFloat("-2147483647"), -2147483647); + assert(parseFloat("-2147483648"), -2147483648); + assert(parseFloat("0x1234"), 0); + assert(parseFloat("Infinity"), Infinity); + assert(parseFloat("-Infinity"), -Infinity); + assert(parseFloat("123.2"), 123.2); + assert(parseFloat("123.2e3"), 123200); + assert(Number.isNaN(Number("+"))); + assert(Number.isNaN(Number("-"))); + assert(Number.isNaN(Number("\x00a"))); + + assert((1-2**-53).toString(12), "0.bbbbbbbbbbbbbba"); + assert((1000000000000000128).toString(), "1000000000000000100"); + assert((1000000000000000128).toFixed(0), "1000000000000000128"); + assert((25).toExponential(0), "3e+1"); + assert((-25).toExponential(0), "-3e+1"); + assert((2.5).toPrecision(1), "3"); + assert((-2.5).toPrecision(1), "-3"); + assert((25).toPrecision(1) === "3e+1"); + assert((1.125).toFixed(2), "1.13"); + assert((-1.125).toFixed(2), "-1.13"); + assert((0.5).toFixed(0), "1"); + assert((-0.5).toFixed(0), "-1"); + assert((-1e-10).toFixed(0), "-0"); + + assert((1.3).toString(7), "1.2046204620462046205"); + assert((1.3).toString(35), "1.ahhhhhhhhhm"); + + assert((123.456).toExponential(100), + "1.2345600000000000306954461848363280296325683593750000000000000000000000000000000000000000000000000000e+2"); + assert((1.23e-99).toExponential(100), + "1.2299999999999999636794326616259654935901564299639709630577493044757187515388707554223010856511630028e-99"); + assert((-0.0007).toExponential(100), + "-6.9999999999999999288763374849509091291110962629318237304687500000000000000000000000000000000000000000e-4"); + assert((0).toExponential(100), + "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+0"); +} + +function test_eval2() +{ + var g_call_count = 0; + /* force non strict mode for f1 and f2 */ + var f1 = new Function("eval", "eval(1, 2)"); + var f2 = new Function("eval", "eval(...[1, 2])"); + function g(a, b) { + assert(a, 1); + assert(b, 2); + g_call_count++; + } + f1(g); + f2(g); + assert(g_call_count, 2); + var e; + try { + new class extends Object { + constructor() { + (() => { + for (const _ in this); + eval(""); + })(); + } + }; + } catch (_e) { + e = _e; + } + assert(e?.message, "this is not initialized"); +} + +function test_eval() +{ + function f(b) { + var x = 1; + return eval(b); + } + var r, a; + + r = eval("1+1;"); + assert(r, 2, "eval"); + + r = eval("var my_var=2; my_var;"); + assert(r, 2, "eval"); + assert(typeof my_var, "undefined"); + + assert(eval("if (1) 2; else 3;"), 2); + assert(eval("if (0) 2; else 3;"), 3); + + assert(f.call(1, "this"), 1); + + a = 2; + assert(eval("a"), 2); + + eval("a = 3"); + assert(a, 3); + + assert(f("arguments.length", 1), 2); + assert(f("arguments[1]", 1), 1); + + a = 4; + assert(f("a"), 4); + f("a=3"); + assert(a, 3); + + test_eval2(); +} + +function test_typed_array() +{ + var buffer, a, i, str, b; + + a = new Uint8Array(4); + assert(a.length, 4); + for(i = 0; i < a.length; i++) + a[i] = i; + assert(a.join(","), "0,1,2,3"); + a[0] = -1; + assert(a[0], 255); + + a = new Int8Array(3); + a[0] = 255; + assert(a[0], -1); + + a = new Int32Array(3); + a[0] = Math.pow(2, 32) - 1; + assert(a[0], -1); + assert(a.BYTES_PER_ELEMENT, 4); + + a = new Uint8ClampedArray(4); + a[0] = -100; + a[1] = 1.5; + a[2] = 0.5; + a[3] = 1233.5; + assert(a.toString(), "0,2,0,255"); + + buffer = new ArrayBuffer(16); + assert(buffer.byteLength, 16); + a = new Uint32Array(buffer, 12, 1); + assert(a.length, 1); + a[0] = -1; + + a = new Uint16Array(buffer, 2); + a[0] = -1; + + a = new Float16Array(buffer, 8, 1); + a[0] = 1; + + a = new Float32Array(buffer, 8, 1); + a[0] = 1; + + a = new Uint8Array(buffer); + + str = a.toString(); + /* test little and big endian cases */ + if (str !== "0,0,255,255,0,0,0,0,0,0,128,63,255,255,255,255" && + str !== "0,0,255,255,0,0,0,0,63,128,0,0,255,255,255,255") { + assert(false); + } + + assert(a.buffer, buffer); + + a = new Uint8Array([1, 2, 3, 4]); + assert(a.toString(), "1,2,3,4"); + a.set([10, 11], 2); + assert(a.toString(), "1,2,10,11"); + + a = new Uint8Array(buffer, 0, 4); + a.constructor = { + [Symbol.species]: function (len) { + return new Uint8Array(buffer, 1, len); + }, + }; + b = a.slice(); + assert(a.buffer, b.buffer); + assert(a.toString(), "0,0,0,255"); + assert(b.toString(), "0,0,255,255"); + + const TypedArray = class extends Object.getPrototypeOf(Uint8Array) {}; + let caught = false; + try { + new TypedArray(); // extensible but not instantiable + } catch (e) { + assert(e instanceof TypeError); + assert(/cannot be called/.test(e.message)); + caught = true; + } + assert(caught); + + // https://github.com/quickjs-ng/quickjs/issues/1208 + buffer = new ArrayBuffer(16); + a = new Uint8Array(buffer); + a.fill(42); + assert(a[0], 42); + buffer.transfer(); + assert(a[0], undefined); + + // https://github.com/quickjs-ng/quickjs/issues/1210 + var buffer = new ArrayBuffer(16, {maxByteLength: 16}); + var desc = Object.getOwnPropertyDescriptor(ArrayBuffer, Symbol.species); + assert(typeof desc.get, "function"); + var get = function() { + buffer.resize(1); + return ArrayBuffer; + }; + Object.defineProperty(ArrayBuffer, Symbol.species, {...desc, get}); + let ex; + try { + buffer.slice(); + } catch (ex_) { + ex = ex_; + } + Object.defineProperty(ArrayBuffer, Symbol.species, desc); // restore + assert(ex instanceof TypeError); + assert("ArrayBuffer is detached", ex.message); + + var buffer = new ArrayBuffer(2); + var ta = new Uint16Array(buffer); + var desc = Object.getOwnPropertyDescriptor(ta, "0"); + ta[0] = 42; + assert(ta[0], 42); + Object.defineProperty(ta, "0", {value: 1337}); + assert(ta[0], 1337); + assert(desc.writable, true); + assert(desc.enumerable, true); + assert(desc.configurable, true); + + var buffer = new ArrayBuffer(2).sliceToImmutable(); + var ta = new Uint16Array(buffer); + var desc = Object.getOwnPropertyDescriptor(ta, "0"); + ta[0] = 42; + assert(ta[0], 0); + Object.defineProperty(ta, "0", {value: 1337}); + assert(ta[0], 0); + assert(desc.writable, false); + assert(desc.enumerable, true); + assert(desc.configurable, false); +} + +function test_json() +{ + var a, s; + s = '{"x":1,"y":true,"z":null,"a":[1,2,3],"s":"str"}'; + a = JSON.parse(s); + assert(a.x, 1); + assert(a.y, true); + assert(a.z, null); + assert(JSON.stringify(a), s); + + /* indentation test */ + assert(JSON.stringify([[{x:1,y:{},z:[]},2,3]],undefined,1), +`[ + [ + { + "x": 1, + "y": {}, + "z": [] + }, + 2, + 3 + ] +]`); +} + +function test_date() +{ + // Date Time String format is YYYY-MM-DDTHH:mm:ss.sssZ + // accepted date formats are: YYYY, YYYY-MM and YYYY-MM-DD + // accepted time formats are: THH:mm, THH:mm:ss, THH:mm:ss.sss + // expanded years are represented with 6 digits prefixed by + or - + // -000000 is invalid. + // A string containing out-of-bounds or nonconforming elements + // is not a valid instance of this format. + // Hence the fractional part after . should have 3 digits and how + // a different number of digits is handled is implementation defined. + assert(Date.parse(""), NaN); + assert(Date.parse("13"), NaN); + assert(Date.parse("31"), NaN); + assert(Date.parse("1000"), -30610224000000); + assert(Date.parse("1969"), -31536000000); + assert(Date.parse("1970"), 0); + assert(Date.parse("2000"), 946684800000); + assert(Date.parse("9999"), 253370764800000); + assert(Date.parse("275761"), NaN); + assert(Date.parse("999999"), NaN); + assert(Date.parse("1000000000"), NaN); + assert(Date.parse("-271821"), NaN); + assert(Date.parse("-271820"), -8639977881600000); + assert(Date.parse("-100000"), -3217862419200000); + assert(Date.parse("+100000"), 3093527980800000); + assert(Date.parse("+275760"), 8639977881600000); + assert(Date.parse("+275761"), NaN); + assert(Date.parse("2000-01"), 946684800000); + assert(Date.parse("2000-01-01"), 946684800000); + assert(Date.parse("2000-01-01T"), NaN); + assert(Date.parse("2000-01-01T00Z"), NaN); + assert(Date.parse("2000-01-01T00:00Z"), 946684800000); + assert(Date.parse("2000-01-01T00:00:00Z"), 946684800000); + assert(Date.parse("2000-01-01T00:00:00.1Z"), 946684800100); + assert(Date.parse("2000-01-01T00:00:00.10Z"), 946684800100); + assert(Date.parse("2000-01-01T00:00:00.100Z"), 946684800100); + assert(Date.parse("2000-01-01T00:00:00.1000Z"), 946684800100); + assert(Date.parse("2000-01-01T00:00:00+00:00"), 946684800000); + //assert(Date.parse("2000-01-01T00:00:00+00:30"), 946686600000); + var d = new Date("2000T00:00"); // Jan 1st 2000, 0:00:00 local time + assert(typeof d === 'object' && d.toString() != 'Invalid Date'); + assert((new Date('Jan 1 2000')).toISOString(), + d.toISOString()); + assert((new Date('Jan 1 2000 00:00')).toISOString(), + d.toISOString()); + assert((new Date('Jan 1 2000 00:00:00')).toISOString(), + d.toISOString()); + assert((new Date('Jan 1 2000 00:00:00 GMT+0100')).toISOString(), + '1999-12-31T23:00:00.000Z'); + assert((new Date('Jan 1 2000 00:00:00 GMT+0200')).toISOString(), + '1999-12-31T22:00:00.000Z'); + assert((new Date('Sat Jan 1 2000')).toISOString(), + d.toISOString()); + assert((new Date('Sat Jan 1 2000 00:00')).toISOString(), + d.toISOString()); + assert((new Date('Sat Jan 1 2000 00:00:00')).toISOString(), + d.toISOString()); + assert((new Date('Sat Jan 1 2000 00:00:00 GMT+0100')).toISOString(), + '1999-12-31T23:00:00.000Z'); + assert((new Date('Sat Jan 1 2000 00:00:00 GMT+0200')).toISOString(), + '1999-12-31T22:00:00.000Z'); + + var d = new Date(1506098258091); + assert(d.toISOString(), "2017-09-22T16:37:38.091Z"); + d.setUTCHours(18, 10, 11); + assert(d.toISOString(), "2017-09-22T18:10:11.091Z"); + var a = Date.parse(d.toISOString()); + assert((new Date(a)).toISOString(), d.toISOString()); + + assert((new Date("2020-01-01T01:01:01.123Z")).toISOString(), + "2020-01-01T01:01:01.123Z"); + /* implementation defined behavior */ + assert((new Date("2020-01-01T01:01:01.1Z")).toISOString(), + "2020-01-01T01:01:01.100Z"); + assert((new Date("2020-01-01T01:01:01.12Z")).toISOString(), + "2020-01-01T01:01:01.120Z"); + assert((new Date("2020-01-01T01:01:01.1234Z")).toISOString(), + "2020-01-01T01:01:01.123Z"); + assert((new Date("2020-01-01T01:01:01.12345Z")).toISOString(), + "2020-01-01T01:01:01.123Z"); + assert((new Date("2020-01-01T01:01:01.1235Z")).toISOString(), + "2020-01-01T01:01:01.123Z"); + assert((new Date("2020-01-01T01:01:01.9999Z")).toISOString(), + "2020-01-01T01:01:01.999Z"); + + assert(Date.UTC(2017), 1483228800000); + assert(Date.UTC(2017, 9), 1506816000000); + assert(Date.UTC(2017, 9, 22), 1508630400000); + assert(Date.UTC(2017, 9, 22, 18), 1508695200000); + assert(Date.UTC(2017, 9, 22, 18, 10), 1508695800000); + assert(Date.UTC(2017, 9, 22, 18, 10, 11), 1508695811000); + assert(Date.UTC(2017, 9, 22, 18, 10, 11, 91), 1508695811091); + + assert(Date.UTC(NaN), NaN); + assert(Date.UTC(2017, NaN), NaN); + assert(Date.UTC(2017, 9, NaN), NaN); + assert(Date.UTC(2017, 9, 22, NaN), NaN); + assert(Date.UTC(2017, 9, 22, 18, NaN), NaN); + assert(Date.UTC(2017, 9, 22, 18, 10, NaN), NaN); + assert(Date.UTC(2017, 9, 22, 18, 10, 11, NaN), NaN); + assert(Date.UTC(2017, 9, 22, 18, 10, 11, 91, NaN), 1508695811091); + + // TODO: Fix rounding errors on Windows/Cygwin. + if (!['win32', 'cygwin'].includes(os.platform)) { + // from test262/test/built-ins/Date/UTC/fp-evaluation-order.js + assert(Date.UTC(1970, 0, 1, 80063993375, 29, 1, -288230376151711740), 29312, + 'order of operations / precision in MakeTime'); + assert(Date.UTC(1970, 0, 213503982336, 0, 0, 0, -18446744073709552000), 34447360, + 'precision in MakeDate'); + } + //assert(Date.UTC(2017 - 1e9, 9 + 12e9), 1506816000000); // node fails this + assert(Date.UTC(2017, 9, 22 - 1e10, 18 + 24e10), 1508695200000); + assert(Date.UTC(2017, 9, 22, 18 - 1e10, 10 + 60e10), 1508695800000); + assert(Date.UTC(2017, 9, 22, 18, 10 - 1e10, 11 + 60e10), 1508695811000); + assert(Date.UTC(2017, 9, 22, 18, 10, 11 - 1e12, 91 + 1000e12), 1508695811091); + assert(new Date("2024 Apr 7 1:00 AM").toLocaleString(), "04/07/2024, 01:00:00 AM"); + assert(new Date("2024 Apr 7 2:00 AM").toLocaleString(), "04/07/2024, 02:00:00 AM"); + assert(new Date("2024 Apr 7 11:00 AM").toLocaleString(), "04/07/2024, 11:00:00 AM"); + assert(new Date("2024 Apr 7 12:00 AM").toLocaleString(), "04/07/2024, 12:00:00 AM"); + assert(new Date("2024 Apr 7 1:00 PM").toLocaleString(), "04/07/2024, 01:00:00 PM"); + assert(new Date("2024 Apr 7 2:00 PM").toLocaleString(), "04/07/2024, 02:00:00 PM"); + assert(new Date("2024 Apr 7 11:00 PM").toLocaleString(), "04/07/2024, 11:00:00 PM"); + assert(new Date("2024 Apr 7 12:00 PM").toLocaleString(), "04/07/2024, 12:00:00 PM"); +} + +function test_regexp() +{ + var a, str; + str = "abbbbbc"; + a = /(b+)c/.exec(str); + assert(a[0], "bbbbbc"); + assert(a[1], "bbbbb"); + assert(a.index, 1); + assert(a.input, str); + a = /(b+)c/.test(str); + assert(a, true); + assert(/\x61/.exec("a")[0], "a"); + assert(/\u0061/.exec("a")[0], "a"); + assert(/\ca/.exec("\x01")[0], "\x01"); + assert(/\\a/.exec("\\a")[0], "\\a"); + assert(/\c0/.exec("\\c0")[0], "\\c0"); + + a = /(\.(?=com|org)|\/)/.exec("ah.com"); + assert(a.index === 2 && a[0] === "."); + + a = /(\.(?!com|org)|\/)/.exec("ah.com"); + assert(a, null); + + a = /(?=(a+))/.exec("baaabac"); + assert(a.index === 1 && a[0] === "" && a[1] === "aaa"); + + a = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac"); + assert(a, ["zaacbbbcac","z","ac","a",,"c"]); + + a = eval("/\0a/"); + assert(a.toString(), "/\0a/"); + assert(a.exec("\0a")[0], "\0a"); + + assert(/{1a}/.toString(), "/{1a}/"); + a = /a{1+/.exec("a{11"); + assert(a, ["a{11"] ); + + eval("/[a-]/"); // accepted with no flag + eval("/[a-]/u"); // accepted with 'u' flag + + let ex; + try { + eval("/[a-]/v"); // rejected with 'v' flag + } catch (_ex) { + ex = _ex; + } + assert(ex?.message, "invalid class range"); + + eval("/[\\-]/"); + eval("/[\\-]/u"); + + /* test zero length matches */ + a = /()*?a/.exec(","); + assert(a, null); + a = /(?:(?=(abc)))a/.exec("abc"); + assert(a, ["a", "abc"]); + a = /(?:(?=(abc)))?a/.exec("abc"); + assert(a, ["a", undefined]); + a = /(?:(?=(abc))){0,2}a/.exec("abc"); + assert(a, ["a", undefined]); + a = /(?:|[\w])+([0-9])/.exec("123a23"); + assert(a, ["123a23", "3"]); + a = "ab".split(/(c)*/); + assert(a, ["a", undefined, "b"]); +} + +function test_symbol() +{ + var a, b, obj, c; + a = Symbol("abc"); + obj = {}; + obj[a] = 2; + assert(obj[a], 2); + assert(typeof obj["abc"], "undefined"); + assert(String(a), "Symbol(abc)"); + b = Symbol("abc"); + assert(a == a); + assert(a === a); + assert(a != b); + assert(a !== b); + + b = Symbol.for("abc"); + c = Symbol.for("abc"); + assert(b === c); + assert(b !== a); + + assert(Symbol.keyFor(b), "abc"); + assert(Symbol.keyFor(a), undefined); + + a = Symbol("aaa"); + assert(a.valueOf(), a); + assert(a.toString(), "Symbol(aaa)"); + + b = Object(a); + assert(b.valueOf(), a); + assert(b.toString(), "Symbol(aaa)"); +} + +function test_map() +{ + var a, i, n, tab, o, v; + n = 1000; + + a = new Map(); + for (var i = 0; i < n; i++) { + a.set(i, i); + } + a.set(-2147483648, 1); + assert(a.get(-2147483648), 1); + assert(a.get(-2147483647 - 1), 1); + assert(a.get(-2147483647.5 - 0.5), 1); + + a = new Map(); + tab = []; + for(i = 0; i < n; i++) { + v = { }; + o = { id: i }; + tab[i] = [o, v]; + a.set(o, v); + } + + assert(a.size, n); + for(i = 0; i < n; i++) { + assert(a.get(tab[i][0]), tab[i][1]); + } + + i = 0; + a.forEach(function (v, o) { + assert(o, tab[i++][0]); + assert(a.has(o)); + assert(a.delete(o)); + assert(!a.has(o)); + }); + + assert(a.size, 0); +} + +function test_weak_map() +{ + var a, e, i, n, tab, o, v, n2; + a = new WeakMap(); + n = 10; + tab = []; + for (const k of [null, 42, "no", Symbol.for("forbidden")]) { + e = undefined; + try { + a.set(k, 42); + } catch (_e) { + e = _e; + } + assert(!!e); + assert(e.message, "invalid value used as WeakMap key"); + } + for(i = 0; i < n; i++) { + v = { }; + o = { id: i }; + tab[i] = [o, v]; + a.set(o, v); + } + o = null; + + n2 = n >> 1; + for(i = 0; i < n2; i++) { + a.delete(tab[i][0]); + } + for(i = n2; i < n; i++) { + tab[i][0] = null; /* should remove the object from the WeakMap too */ + } + /* the WeakMap should be empty here */ +} + +function test_set() +{ + const iter = { + a: [4, 5, 6], + nextCalls: 0, + returnCalls: 0, + next() { + const done = this.nextCalls >= this.a.length + const value = this.a[this.nextCalls] + this.nextCalls++ + return {done, value} + }, + return() { + this.returnCalls++ + return this + }, + } + const setlike = { + size: iter.a.length, + has(v) { return iter.a.includes(v) }, + keys() { return iter }, + } + // set must be bigger than iter.a to hit iter.next and iter.return + assert(new Set([4,5,6,7]).isSupersetOf(setlike), true) + assert(iter.nextCalls, 4) + assert(iter.returnCalls, 0) + iter.nextCalls = iter.returnCalls = 0 + assert(new Set([0,1,2,3]).isSupersetOf(setlike), false) + assert(iter.nextCalls, 1) + assert(iter.returnCalls, 1) + iter.nextCalls = iter.returnCalls = 0 + // set must be bigger than iter.a to hit iter.next and iter.return + assert(new Set([4,5,6,7]).isDisjointFrom(setlike), false) + assert(iter.nextCalls, 1) + assert(iter.returnCalls, 1) + iter.nextCalls = iter.returnCalls = 0 + assert(new Set([0,1,2,3]).isDisjointFrom(setlike), true) + assert(iter.nextCalls, 4) + assert(iter.returnCalls, 0) + iter.nextCalls = iter.returnCalls = 0 + function expectException(klass, sizes) { + for (const size of sizes) { + let ex + try { + new Set([]).union({size}) + } catch (e) { + ex = e + } + assert(ex instanceof klass) + assert(typeof ex.message, "string") + assert(ex.message.includes(".size")) + } + } + expectException(RangeError, [-1, -(Number.MAX_SAFE_INTEGER+1), -Infinity]) + expectException(TypeError, [NaN]) + const legal = [ + 0, -0, 1, 2, + Number.MAX_SAFE_INTEGER + 1, + Number.MAX_SAFE_INTEGER + 2, + Number.MAX_SAFE_INTEGER + 3, + Infinity + ] + for (const size of legal) { + new Set([]).union({ + size, + has() { return false }, + keys() { return [].values() }, + }) + } +} + +function test_weak_set() +{ + var a, e; + a = new WeakSet(); + for (const k of [null, 42, "no", Symbol.for("forbidden")]) { + e = undefined; + try { + a.add(k); + } catch (_e) { + e = _e; + } + assert(!!e); + assert(e.message, "invalid value used as WeakSet key"); + } +} + +function test_generator() +{ + function *f() { + var ret; + yield 1; + ret = yield 2; + assert(ret, "next_arg"); + return 3; + } + function *f2() { + yield 1; + yield 2; + return "ret_val"; + } + function *f1() { + var ret = yield *f2(); + assert(ret, "ret_val"); + return 3; + } + function *f3() { + var ret; + /* test stack consistency with nip_n to handle yield return + + * finally clause */ + try { + ret = 2 + (yield 1); + } catch(e) { + } finally { + ret++; + } + return ret; + } + var g, v; + g = f(); + v = g.next(); + assert(v.value === 1 && v.done === false); + v = g.next(); + assert(v.value === 2 && v.done === false); + v = g.next("next_arg"); + assert(v.value === 3 && v.done === true); + v = g.next(); + assert(v.value === undefined && v.done === true); + + g = f1(); + v = g.next(); + assert(v.value === 1 && v.done === false); + v = g.next(); + assert(v.value === 2 && v.done === false); + v = g.next(); + assert(v.value === 3 && v.done === true); + v = g.next(); + assert(v.value === undefined && v.done === true); + + g = f3(); + v = g.next(); + assert(v.value === 1 && v.done === false); + v = g.next(3); + assert(v.value === 6 && v.done === true); +} + +function test_proxy_iter() +{ + const p = new Proxy({}, { + getOwnPropertyDescriptor() { + return {configurable: true, enumerable: true, value: 42}; + }, + ownKeys() { + return ["x", "y"]; + }, + }); + const a = []; + for (const x in p) a.push(x); + assert(a[0], "x"); + assert(a[1], "y"); +} + +/* CVE-2023-31922 */ +function test_proxy_is_array() +{ + for (var r = new Proxy([], {}), y = 0; y < 331072; y++) + r = new Proxy(r, {}); + + try { + /* Without ASAN */ + assert(Array.isArray(r)); + } catch(e) { + /* With ASAN expect RangeError "Maximum call stack size exceeded" to be raised */ + if (e instanceof RangeError) { + assert(e.message, "Maximum call stack size exceeded", "Stack overflow error was not raised") + } else { + throw e; + } + } +} + +function test_finalization_registry() +{ + { + let expected = {}; + let actual; + let finrec = new FinalizationRegistry(v => { actual = v }); + finrec.register({}, expected); + queueMicrotask(() => { + assert(actual, expected); + }); + } + { + let expected = 42; + let actual; + let finrec = new FinalizationRegistry(v => { actual = v }); + finrec.register({}, expected); + queueMicrotask(() => { + assert(actual, expected); + }); + } +} + +function test_cur_pc() +{ + var a = []; + Object.defineProperty(a, '1', { + get: function() { throw Error("a[1]_get"); }, + set: function(x) { throw Error("a[1]_set"); } + }); + assertThrows(Error, function() { return a[1]; }); + assertThrows(Error, function() { a[1] = 1; }); + assertThrows(Error, function() { return [...a]; }); + assertThrows(Error, function() { return ({...b} = a); }); + + var o = {}; + Object.defineProperty(o, 'x', { + get: function() { throw Error("o.x_get"); }, + set: function(x) { throw Error("o.x_set"); } + }); + o.valueOf = function() { throw Error("o.valueOf"); }; + assertThrows(Error, function() { return +o; }); + assertThrows(Error, function() { return -o; }); + assertThrows(Error, function() { return o+1; }); + assertThrows(Error, function() { return o-1; }); + assertThrows(Error, function() { return o*1; }); + assertThrows(Error, function() { return o/1; }); + assertThrows(Error, function() { return o%1; }); + assertThrows(Error, function() { return o**1; }); + assertThrows(Error, function() { return o<<1; }); + assertThrows(Error, function() { return o>>1; }); + assertThrows(Error, function() { return o>>>1; }); + assertThrows(Error, function() { return o&1; }); + assertThrows(Error, function() { return o|1; }); + assertThrows(Error, function() { return o^1; }); + assertThrows(Error, function() { return o<1; }); + assertThrows(Error, function() { return o==1; }); + assertThrows(Error, function() { return o++; }); + assertThrows(Error, function() { return o--; }); + assertThrows(Error, function() { return ++o; }); + assertThrows(Error, function() { return --o; }); + assertThrows(Error, function() { return ~o; }); + + Object.defineProperty(globalThis, 'xxx', { + get: function() { throw Error("xxx_get"); }, + set: function(x) { throw Error("xxx_set"); } + }); + assertThrows(Error, function() { return xxx; }); + assertThrows(Error, function() { xxx = 1; }); +} + +test(); +test_function(); +test_enum(); +test_array(); +test_string(); +test_rope(); +test_math(); +test_number(); +test_eval(); +test_typed_array(); +test_json(); +test_date(); +test_regexp(); +test_symbol(); +test_map(); +test_weak_map(); +test_set(); +test_weak_set(); +test_generator(); +test_proxy_iter(); +test_proxy_is_array(); +test_finalization_registry(); +test_exception_source_pos(); +test_function_source_pos(); +test_exception_prepare_stack(); +test_exception_stack_size_limit(); +test_exception_capture_stack_trace(); +test_exception_capture_stack_trace_filter(); +test_cur_pc(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_closure.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_closure.js new file mode 100755 index 00000000..4d638795 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_closure.js @@ -0,0 +1,220 @@ +// This test cannot use imports because it needs to run in non-strict mode. + +function assert(actual, expected, message) { + if (arguments.length == 1) + expected = true; + + if (actual === expected) + return; + + if (actual !== null && expected !== null + && typeof actual == 'object' && typeof expected == 'object' + && actual.toString() === expected.toString()) + return; + + throw Error("assertion failed: got |" + actual + "|" + + ", expected |" + expected + "|" + + (message ? " (" + message + ")" : "")); +} + +/*----------------*/ + +var log_str = ""; + +function log(str) +{ + log_str += str + ","; +} + +function f(a, b, c) +{ + var x = 10; + log("a="+a); + function g(d) { + function h() { + log("d=" + d); + log("x=" + x); + } + log("b=" + b); + log("c=" + c); + h(); + } + g(4); + return g; +} + +var g1 = f(1, 2, 3); +g1(5); + +assert(log_str, "a=1,b=2,c=3,d=4,x=10,b=2,c=3,d=5,x=10,", "closure1"); + +function test_closure1() +{ + function f2() + { + var val = 1; + + function set(a) { + val = a; + } + function get(a) { + return val; + } + return { "set": set, "get": get }; + } + + var obj = f2(); + obj.set(10); + var r; + r = obj.get(); + assert(r, 10, "closure2"); +} + +function test_closure2() +{ + var expr_func = function myfunc1(n) { + function myfunc2(n) { + return myfunc1(n - 1); + } + if (n == 0) + return 0; + else + return myfunc2(n); + }; + var r; + r = expr_func(1); + assert(r, 0, "expr_func"); +} + +function test_closure3() +{ + function fib(n) + { + if (n <= 0) + return 0; + else if (n == 1) + return 1; + else + return fib(n - 1) + fib(n - 2); + } + + var fib_func = function fib1(n) + { + if (n <= 0) + return 0; + else if (n == 1) + return 1; + else + return fib1(n - 1) + fib1(n - 2); + }; + + assert(fib(6), 8, "fib"); + assert(fib_func(6), 8, "fib_func"); +} + +function test_arrow_function() +{ + "use strict"; + + function f1() { + return (() => arguments)(); + } + function f2() { + return (() => this)(); + } + function f3() { + return (() => eval("this"))(); + } + function f4() { + return (() => eval("new.target"))(); + } + var a; + + a = f1(1, 2); + assert(a.length, 2); + assert(a[0] === 1 && a[1] === 2); + + assert(f2.call("this_val"), "this_val"); + assert(f3.call("this_val"), "this_val"); + assert(new f4(), f4); + + var o1 = { f() { return this; } }; + var o2 = { f() { + return (() => eval("super.f()"))(); + } }; + o2.__proto__ = o1; + + assert(o2.f(), o2); +} + +function test_with() +{ + var o1 = { x: "o1", y: "o1" }; + var x = "local"; + eval('var z="var_obj";'); + assert(z, "var_obj"); + with (o1) { + assert(x, "o1"); + assert(eval("x"), "o1"); + var f = function () { + o2 = { x: "o2" }; + with (o2) { + assert(x, "o2"); + assert(y, "o1"); + assert(z, "var_obj"); + assert(eval("x"), "o2"); + assert(eval("y"), "o1"); + assert(eval("z"), "var_obj"); + assert(eval('eval("x")'), "o2"); + } + }; + f(); + } +} + +function test_eval_closure() +{ + var tab; + + tab = []; + for(let i = 0; i < 3; i++) { + eval("tab.push(function g1() { return i; })"); + } + for(let i = 0; i < 3; i++) { + assert(tab[i](), i); + } + + tab = []; + for(let i = 0; i < 3; i++) { + let f = function f() { + eval("tab.push(function g2() { return i; })"); + }; + f(); + } + for(let i = 0; i < 3; i++) { + assert(tab[i](), i); + } +} + +function test_eval_const() +{ + const a = 1; + var success = false; + var f = function () { + eval("a = 1"); + }; + try { + f(); + } catch(e) { + success = (e instanceof TypeError); + } + assert(success); +} + +test_closure1(); +test_closure2(); +test_closure3(); +test_arrow_function(); +test_with(); +test_eval_closure(); +test_eval_const(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_cyclic_import.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_cyclic_import.js new file mode 100755 index 00000000..bf51d9b1 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_cyclic_import.js @@ -0,0 +1,12 @@ +/*--- +negative: + phase: resolution + type: SyntaxError +---*/ +// FIXME(bnoordhuis) shouldn't throw SyntaxError but that's still better +// than segfaulting, see https://github.com/quickjs-ng/quickjs/issues/567 +import {assert} from "./assert.js" +import {f} from "./fixture_cyclic_import.js" +export {f} +export function g(x) { return x + 1 } +assert(f(1), 4) diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_domexception.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_domexception.js new file mode 100755 index 00000000..70ff1e79 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_domexception.js @@ -0,0 +1,35 @@ +import { assert, assertThrows } from "./assert.js"; + +function test_code() { + let ex = new DOMException(); + assert(ex.code, 0); + ex = new DOMException("", "HierarchyRequestError\0test"); + assert(ex.code, 0); + ex = new DOMException("test", "HierarchyRequestError"); + assert(ex.code, 3); + assert(ex.code, ex.HIERARCHY_REQUEST_ERR); + assert(ex.code, DOMException.HIERARCHY_REQUEST_ERR); + ex = new DOMException("", "DataCloneError"); + assert(ex.code, ex.DATA_CLONE_ERR); + assert(ex.code, 25); + ex = new DOMException("", "IndexSizeError"); + assert(ex.code, ex.INDEX_SIZE_ERR); + assert(ex.code, 1); +} + +function test_properties() { + let ex = new DOMException("test"); + assert(ex.message, "test"); + assert(ex.name, "Error"); + ex = new DOMException("test", "InvalidCharacterError"); + assert(ex.name, "InvalidCharacterError"); + assertThrows(TypeError, () => ex.message = ""); + assertThrows(TypeError, () => ex.name = "test"); + assert(ex.__proto__, DOMException.prototype); + /* Note: browsers set "stack" on the prototype, not the object. + * This follows node. */ + assert(Object.getOwnPropertyNames(ex), ["stack"]); +} + +test_code(); +test_properties(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_for_of_line_numbers.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_for_of_line_numbers.js new file mode 100755 index 00000000..9d2e9bb1 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_for_of_line_numbers.js @@ -0,0 +1,50 @@ +import { assert } from "./assert.js"; + +function closingIterable(stacks) +{ + return { + [Symbol.iterator]() { + return { + next() { + return { done: false, value: 1 }; + }, + return() { + stacks.push(new Error().stack); + return { done: true }; + }, + }; + }, + }; +} + +function assertCallerLine(frames, expectedLine, message) +{ + assert(frames.length >= 2, true, message); + assert(frames[1].getFileName().endsWith("test_for_of_line_numbers.js"), true, message); + assert(frames[1].getLineNumber(), expectedLine, message); +} + +function test_for_of_empty_body_line_number() +{ + const stacks = []; + const expectedLine = 31; + for (const _ of closingIterable(stacks)) break; + assertCallerLine(stacks[0], expectedLine, "for-of iterator close"); +} + +function test_for_of_destructuring_line_number() +{ + const stacks = []; + const outer = [closingIterable(stacks)]; + const expectedLine = 40; + for (const [_] of outer) break; + assertCallerLine(stacks[0], expectedLine, "destructuring iterator close"); +} + +Error.prepareStackTrace = (_, frames) => frames; +try { + test_for_of_empty_body_line_number(); + test_for_of_destructuring_line_number(); +} finally { + Error.prepareStackTrace = undefined; +} diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_language.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_language.js new file mode 100755 index 00000000..ee0ebea0 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_language.js @@ -0,0 +1,1112 @@ +// This test cannot use imports because it needs to run in non-strict mode. + +function assert(actual, expected, message) { + if (arguments.length == 1) + expected = true; + + if (actual === expected) + return; + + if (typeof actual == 'number' && isNaN(actual) + && typeof expected == 'number' && isNaN(expected)) + return; + + if (actual !== null && expected !== null + && typeof actual == 'object' && typeof expected == 'object' + && actual.toString() === expected.toString()) + return; + + var msg = message ? " (" + message + ")" : ""; + throw Error("assertion failed: got |" + actual + "|" + + ", expected |" + expected + "|" + msg); +} + +function assert_throws(expected_error, func, message) +{ + var err = false; + var msg = message ? " (" + message + ")" : ""; + try { + switch (typeof func) { + case 'string': + eval(func); + break; + case 'function': + func(); + break; + } + } catch(e) { + err = true; + if (!(e instanceof expected_error)) { + throw Error(`expected ${expected_error.name}, got ${e.name}${msg}`); + } + } + if (!err) { + throw Error(`expected ${expected_error.name}${msg}`); + } +} + +/*----------------*/ + +function test_op1() +{ + var r, a; + r = 1 + 2; + assert(r, 3, "1 + 2 === 3"); + + r = 1 - 2; + assert(r, -1, "1 - 2 === -1"); + + r = -1; + assert(r, -1, "-1 === -1"); + + r = +2; + assert(r, 2, "+2 === 2"); + + r = 2 * 3; + assert(r, 6, "2 * 3 === 6"); + + r = 4 / 2; + assert(r, 2, "4 / 2 === 2"); + + r = 4 % 3; + assert(r, 1, "4 % 3 === 3"); + + r = 4 << 2; + assert(r, 16, "4 << 2 === 16"); + + r = 1 << 0; + assert(r, 1, "1 << 0 === 1"); + + r = 1 << 31; + assert(r, -2147483648, "1 << 31 === -2147483648"); + + r = 1 << 32; + assert(r, 1, "1 << 32 === 1"); + + r = (1 << 31) < 0; + assert(r, true, "(1 << 31) < 0 === true"); + + r = -4 >> 1; + assert(r, -2, "-4 >> 1 === -2"); + + r = -4 >>> 1; + assert(r, 0x7ffffffe, "-4 >>> 1 === 0x7ffffffe"); + + r = 1 & 1; + assert(r, 1, "1 & 1 === 1"); + + r = 0 | 1; + assert(r, 1, "0 | 1 === 1"); + + r = 1 ^ 1; + assert(r, 0, "1 ^ 1 === 0"); + + r = ~1; + assert(r, -2, "~1 === -2"); + + r = !1; + assert(r, false, "!1 === false"); + + assert((1 < 2), true, "(1 < 2) === true"); + + assert((2 > 1), true, "(2 > 1) === true"); + + assert(('b' > 'a'), true, "('b' > 'a') === true"); + + assert(2 ** 8, 256, "2 ** 8 === 256"); +} + +function test_cvt() +{ + assert((NaN | 0), 0); + assert((Infinity | 0), 0); + assert(((-Infinity) | 0), 0); + assert(("12345" | 0), 12345); + assert(("0x12345" | 0), 0x12345); + assert(((4294967296 * 3 - 4) | 0), -4); + + assert(("12345" >>> 0), 12345); + assert(("0x12345" >>> 0), 0x12345); + assert((NaN >>> 0), 0); + assert((Infinity >>> 0), 0); + assert(((-Infinity) >>> 0), 0); + assert(((4294967296 * 3 - 4) >>> 0), (4294967296 - 4)); + assert((19686109595169230000).toString(), "19686109595169230000"); +} + +function test_eq() +{ + assert(null == undefined); + assert(undefined == null); + assert(true == 1); + assert(0 == false); + assert("" == 0); + assert("123" == 123); + assert("122" != 123); + assert((new Number(1)) == 1); + assert(2 == (new Number(2))); + assert((new String("abc")) == "abc"); + assert({} != "abc"); +} + +function test_inc_dec() +{ + var a, r; + + a = 1; + r = a++; + assert(r === 1 && a === 2, true, "++"); + + a = 1; + r = ++a; + assert(r === 2 && a === 2, true, "++"); + + a = 1; + r = a--; + assert(r === 1 && a === 0, true, "--"); + + a = 1; + r = --a; + assert(r === 0 && a === 0, true, "--"); + + a = {x:true}; + a.x++; + assert(a.x, 2, "++"); + + a = {x:true}; + a.x--; + assert(a.x, 0, "--"); + + a = [true]; + a[0]++; + assert(a[0], 2, "++"); + + a = {x:true}; + r = a.x++; + assert(r === 1 && a.x === 2, true, "++"); + + a = {x:true}; + r = a.x--; + assert(r === 1 && a.x === 0, true, "--"); + + a = [true]; + r = a[0]++; + assert(r === 1 && a[0] === 2, true, "++"); + + a = [true]; + r = a[0]--; + assert(r === 1 && a[0] === 0, true, "--"); +} + +function F(x) +{ + this.x = x; +} + +function test_op2() +{ + var a, b; + a = new Object; + a.x = 1; + assert(a.x, 1, "new"); + b = new F(2); + assert(b.x, 2, "new"); + + a = {x : 2}; + assert(("x" in a), true, "in"); + assert(("y" in a), false, "in"); + + a = {}; + assert((a instanceof Object), true, "instanceof"); + assert((a instanceof String), false, "instanceof"); + + assert((typeof 1), "number", "typeof"); + assert((typeof Object), "function", "typeof"); + assert((typeof null), "object", "typeof"); + assert((typeof unknown_var), "undefined", "typeof"); + + a = {x: 1, if: 2, async: 3}; + assert(a.if === 2); + assert(a.async === 3); +} + +function test_delete() +{ + var a, err; + + a = {x: 1, y: 1}; + assert((delete a.x), true, "delete"); + assert(("x" in a), false, "delete"); + + /* the following are not tested by test262 */ + assert(delete "abc"[100], true); + + err = false; + try { + delete null.a; + } catch(e) { + err = (e instanceof TypeError); + } + assert(err, true, "delete"); + + err = false; + try { + a = { f() { delete super.a; } }; + a.f(); + } catch(e) { + err = (e instanceof ReferenceError); + } + assert(err, true, "delete"); +} + +function test_constructor() +{ + function *G() {} + let ex + try { new G() } catch (ex_) { ex = ex_ } + assert(ex instanceof TypeError) + assert(ex.message, "G is not a constructor") +} + +function test_prototype() +{ + var f = function f() { }; + assert(f.prototype.constructor, f, "prototype"); + + var g = function g() { }; + /* QuickJS bug */ + Object.defineProperty(g, "prototype", { writable: false }); + assert(g.prototype.constructor, g, "prototype"); +} + +function test_arguments() +{ + function f2() { + assert(arguments.length, 2, "arguments"); + assert(arguments[0], 1, "arguments"); + assert(arguments[1], 3, "arguments"); + } + f2(1, 3); + + /* mapped arguments with GC must not crash (non-detached var_refs) */ + function f3(a) { + arguments; + gc(); + } + f3(0); +} + +function test_class() +{ + var o; + class C { + constructor() { + this.x = 10; + } + f() { + return 1; + } + static F() { + return -1; + } + get y() { + return 12; + } + }; + class D extends C { + constructor() { + super(); + this.z = 20; + } + g() { + return 2; + } + static G() { + return -2; + } + h() { + return super.f(); + } + static H() { + return super["F"](); + } + } + + assert(C.F(), -1); + assert(Object.getOwnPropertyDescriptor(C.prototype, "y").get.name === "get y"); + + o = new C(); + assert(o.f(), 1); + assert(o.x, 10); + + assert(D.F(), -1); + assert(D.G(), -2); + assert(D.H(), -1); + + o = new D(); + assert(o.f(), 1); + assert(o.g(), 2); + assert(o.x, 10); + assert(o.z, 20); + assert(o.h(), 1); + + /* test class name scope */ + var E1 = class E { static F() { return E; } }; + assert(E1, E1.F()); + + class S { + static x = 42; + static y = S.x; + static z = this.x; + } + assert(S.x, 42); + assert(S.y, 42); + assert(S.z, 42); + + class P { + get; + set; + async; + get = () => "123"; + set = () => "456"; + async = () => "789"; + static() { return 42; } + } + assert(new P().get(), "123"); + assert(new P().set(), "456"); + assert(new P().async(), "789"); + assert(new P().static(), 42); + + /* test that division after private field in parens is not parsed as regex */ + class Q { + #x = 10; + f() { return (this.#x / 2); } + } + assert(new Q().f(), 5); +}; + +function test_template() +{ + var a, b; + b = 123; + a = `abc${b}d`; + assert(a, "abc123d"); + + a = String.raw `abc${b}d`; + assert(a, "abc123d"); + + a = "aaa"; + b = "bbb"; + assert(`aaa${a, b}ccc`, "aaabbbccc"); +} + +function test_template_skip() +{ + var a = "Bar"; + var { b = `${a + `a${a}` }baz` } = {}; + assert(b, "BaraBarbaz"); +} + +function test_object_literal() +{ + var x = 0, get = 1, set = 2; async = 3; + a = { get: 2, set: 3, async: 4, get a(){ return this.get} }; + assert(JSON.stringify(a), '{"get":2,"set":3,"async":4,"a":2}'); + assert(a.a, 2); + + a = { x, get, set, async }; + assert(JSON.stringify(a), '{"x":0,"get":1,"set":2,"async":3}'); +} + +function test_regexp_skip() +{ + var a, b; + [a, b = /abc\(/] = [1]; + assert(a, 1); + + [a, b =/abc\(/] = [2]; + assert(a, 2); +} + +function test_labels() +{ + do x: { break x; } while(0); + if (1) + x: { break x; } + else + x: { break x; } + with ({}) x: { break x; }; + while (0) x: { break x; }; +} + +function test_destructuring() +{ + function * g () { return 0; }; + var [x] = g(); + assert(x, void 0); +} + +function test_spread() +{ + var x; + x = [1, 2, ...[3, 4]]; + assert(x.toString(), "1,2,3,4"); + + x = [ ...[ , ] ]; + assert(Object.getOwnPropertyNames(x).toString(), "0,length"); +} + +function test_function_length() +{ + assert( ((a, b = 1, c) => {}).length, 1); + assert( (([a,b]) => {}).length, 1); + assert( (({a,b}) => {}).length, 1); + assert( ((c, [a,b] = 1, d) => {}).length, 1); +} + +function test_argument_scope() +{ + var f; + var c = "global"; + + f = function(a = eval("var arguments")) {}; + // for some reason v8 does not throw an exception here + if (typeof require === 'undefined') + assert_throws(SyntaxError, f); + + f = function(a = eval("1"), b = arguments[0]) { return b; }; + assert(f(12), 12); + + f = function(a, b = arguments[0]) { return b; }; + assert(f(12), 12); + + f = function(a, b = () => arguments) { return b; }; + assert(f(12)()[0], 12); + + f = function(a = eval("1"), b = () => arguments) { return b; }; + assert(f(12)()[0], 12); + + (function() { + "use strict"; + f = function(a = this) { return a; }; + assert(f.call(123), 123); + + f = function f(a = f) { return a; }; + assert(f(), f); + + f = function f(a = eval("f")) { return a; }; + assert(f(), f); + })(); + + f = (a = eval("var c = 1"), probe = () => c) => { + var c = 2; + assert(c, 2); + assert(probe(), 1); + } + f(); + + f = (a = eval("var arguments = 1"), probe = () => arguments) => { + var arguments = 2; + assert(arguments, 2); + assert(probe(), 1); + } + f(); + + f = function f(a = eval("var c = 1"), b = c, probe = () => c) { + assert(b, 1); + assert(c, 1); + assert(probe(), 1) + } + f(); + + assert(c, "global"); + f = function f(a, b = c, probe = () => c) { + eval("var c = 1"); + assert(c, 1); + assert(b, "global"); + assert(probe(), "global") + } + f(); + assert(c, "global"); + + f = function f(a = eval("var c = 1"), probe = (d = eval("c")) => d) { + assert(probe(), 1) + } + f(); +} + +function test_function_expr_name() +{ + var f; + + /* non strict mode test : assignment to the function name silently + fails */ + + f = function myfunc() { + myfunc = 1; + return myfunc; + }; + assert(f(), f); + + f = function myfunc() { + myfunc = 1; + (() => { + myfunc = 1; + })(); + return myfunc; + }; + assert(f(), f); + + f = function myfunc() { + eval("myfunc = 1"); + return myfunc; + }; + assert(f(), f); + + /* strict mode test : assignment to the function name raises a + TypeError exception */ + + f = function myfunc() { + "use strict"; + myfunc = 1; + }; + assert_throws(TypeError, f); + + f = function myfunc() { + "use strict"; + (() => { + myfunc = 1; + })(); + }; + assert_throws(TypeError, f); + + f = function myfunc() { + "use strict"; + eval("myfunc = 1"); + }; + assert_throws(TypeError, f); +} + +function test_expr(expr, err) { + if (err) + assert_throws(err, expr, `for ${expr}`); + else + assert(1, eval(expr), `for ${expr}`); +} + +function test_name(name, err) +{ + test_expr(`(function() { return typeof ${name} ? 1 : 1; })()`); + test_expr(`(function() { var ${name}; ${name} = 1; return ${name}; })()`); + test_expr(`(function() { let ${name}; ${name} = 1; return ${name}; })()`, name == 'let' ? SyntaxError : undefined); + test_expr(`(function() { const ${name} = 1; return ${name}; })()`, name == 'let' ? SyntaxError : undefined); + test_expr(`(function(${name}) { ${name} = 1; return ${name}; })()`); + test_expr(`(function({${name}}) { ${name} = 1; return ${name}; })({})`); + test_expr(`(function ${name}() { return ${name} ? 1 : 0; })()`); + test_expr(`"use strict"; (function() { return typeof ${name} ? 1 : 1; })()`, err); + test_expr(`"use strict"; (function() { if (0) ${name} = 1; return 1; })()`, err); + test_expr(`"use strict"; (function() { var x; if (0) x = ${name}; return 1; })()`, err); + test_expr(`"use strict"; (function() { var ${name}; return 1; })()`, err); + test_expr(`"use strict"; (function() { let ${name}; return 1; })()`, err); + test_expr(`"use strict"; (function() { const ${name} = 1; return 1; })()`, err); + test_expr(`"use strict"; (function() { var ${name}; ${name} = 1; return 1; })()`, err); + test_expr(`"use strict"; (function() { var ${name}; ${name} = 1; return ${name}; })()`, err); + test_expr(`"use strict"; (function(${name}) { return 1; })()`, err); + test_expr(`"use strict"; (function({${name}}) { return 1; })({})`, err); + test_expr(`"use strict"; (function ${name}() { return 1; })()`, err); + test_expr(`(function() { "use strict"; return typeof ${name} ? 1 : 1; })()`, err); + test_expr(`(function() { "use strict"; if (0) ${name} = 1; return 1; })()`, err); + test_expr(`(function() { "use strict"; var x; if (0) x = ${name}; return 1; })()`, err); + test_expr(`(function() { "use strict"; var ${name}; return 1; })()`, err); + test_expr(`(function() { "use strict"; let ${name}; return 1; })()`, err); + test_expr(`(function() { "use strict"; const ${name} = 1; return 1; })()`, err); + test_expr(`(function() { "use strict"; var ${name}; ${name} = 1; return 1; })()`, err); + test_expr(`(function() { "use strict"; var ${name}; ${name} = 1; return ${name}; })()`, err); + test_expr(`(function(${name}) { "use strict"; return 1; })()`, err); + test_expr(`(function({${name}}) { "use strict"; return 1; })({})`, SyntaxError); + test_expr(`(function ${name}() { "use strict"; return 1; })()`, err); +} + +function test_reserved_names() +{ + test_name('await'); + test_name('yield', SyntaxError); + test_name('implements', SyntaxError); + test_name('interface', SyntaxError); + test_name('let', SyntaxError); + test_name('package', SyntaxError); + test_name('private', SyntaxError); + test_name('protected', SyntaxError); + test_name('public', SyntaxError); + test_name('static', SyntaxError); +} + +function test_number_literals() +{ + assert(0.1.a, undefined); + assert(0x1.a, undefined); + assert(0b1.a, undefined); + assert(01.a, undefined); + assert(0o1.a, undefined); + test_expr('0.a', SyntaxError); + assert(parseInt("0_1"), 0); + assert(parseInt("1_0"), 1); + assert(parseInt("0_1", 8), 0); + assert(parseInt("1_0", 8), 1); + assert(parseFloat("0_1"), 0); + assert(parseFloat("1_0"), 1); + assert(1_0, 10); + assert(parseInt("Infinity"), NaN); + assert(parseFloat("Infinity"), Infinity); + assert(parseFloat("Infinity1"), Infinity); + assert(parseFloat("Infinity_"), Infinity); + assert(parseFloat("Infinity."), Infinity); + test_expr('0_0', SyntaxError); + test_expr('00_0', SyntaxError); + test_expr('01_0', SyntaxError); + test_expr('08_0', SyntaxError); + test_expr('09_0', SyntaxError); +} + +function test_syntax() +{ + assert_throws(SyntaxError, "do"); + assert_throws(SyntaxError, "do;"); + assert_throws(SyntaxError, "do{}"); + assert_throws(SyntaxError, "if"); + assert_throws(SyntaxError, "if\n"); + assert_throws(SyntaxError, "if 1"); + assert_throws(SyntaxError, "if \0"); + assert_throws(SyntaxError, "if ;"); + assert_throws(SyntaxError, "if 'abc'"); + assert_throws(SyntaxError, "if `abc`"); + assert_throws(SyntaxError, "if /abc/"); + assert_throws(SyntaxError, "if abc"); + assert_throws(SyntaxError, "if abc\u0064"); + assert_throws(SyntaxError, "if abc\\u0064"); + assert_throws(SyntaxError, "if \u0123"); + assert_throws(SyntaxError, "if \\u0123"); +} + +/* optional chaining tests not present in test262 */ +function test_optional_chaining() +{ + var a, z; + z = null; + a = { b: { c: 2 } }; + assert(delete z?.b.c, true); + assert(delete a?.b.c, true); + assert(JSON.stringify(a), '{"b":{}}', "optional chaining delete"); + + a = { b: { c: 2 } }; + assert(delete z?.b["c"], true); + assert(delete a?.b["c"], true); + assert(JSON.stringify(a), '{"b":{}}'); + + a = { + b() { return this._b; }, + _b: { c: 42 } + }; + + assert((a?.b)().c, 42); + + assert((a?.["b"])().c, 42); +} + +function test_parse_semicolon() +{ + /* 'yield' or 'await' may not be considered as a token if the + previous ';' is missing */ + function *f() + { + function func() { + } + yield 1; + var h = x => x + 1 + yield 2; + } + async function g() + { + function func() { + } + await 1; + var h = x => x + 1 + await 2; + } +} + +function test_non_extensible_receiver_existing_property_set() +{ + var proto, receiver, ret; + + proto = { x: 1 }; + receiver = { x: 0 }; + Object.preventExtensions(receiver); + ret = Reflect.set(proto, "x", 2, receiver); + assert(ret, true, "non-extensible receiver existing property Reflect.set result"); + assert(receiver.x, 2, "non-extensible receiver existing property Reflect.set value"); + + class A { + } + A.prototype.x = 1; + + class B extends A { + setX(value) { + super.x = value; + } + } + + receiver = new B(); + receiver.x = 0; + Object.preventExtensions(receiver); + receiver.setX(3); + assert(receiver.x, 3, "non-extensible receiver existing property super set value"); +} + +function assert_array_eq(actual, expected, message) +{ + assert(Array.isArray(actual), true, message); + assert(actual.length, expected.length, message); + for (var i = 0; i < expected.length; i++) { + assert(actual[i], expected[i], + (message ? message + ": " : "") + "index " + i); + } +} + +/* TC39 explicit resource management: `using` declaration */ +function test_using() +{ + /* AddDisposableResource validates and snapshots the dispose method at + declaration; the body must not run on failure. */ + + /* Missing Symbol.dispose → TypeError before the body runs. */ + (function() { + var bodyRan = false; + var caught; + try { + (function() { using x = {}; bodyRan = true; })(); + } catch (e) { caught = e; } + assert(bodyRan, false); + assert(caught instanceof TypeError, true); + })(); + + /* Non-object, non-null → TypeError. */ + (function() { + var bodyRan = false; + var caught; + try { + (function() { using x = 42; bodyRan = true; })(); + } catch (e) { caught = e; } + assert(bodyRan, false); + assert(caught instanceof TypeError, true); + })(); + + /* Symbol.dispose getter throwing propagates at declaration. */ + (function() { + var bodyRan = false; + var caught; + try { + (function() { + var o = {}; + Object.defineProperty(o, Symbol.dispose, { + get() { throw new Error("getter"); } + }); + using y = o; + bodyRan = true; + })(); + } catch (e) { caught = e; } + assert(bodyRan, false); + assert(caught instanceof Error, true); + assert(caught.message, "getter"); + })(); + + /* Non-callable dispose → TypeError. */ + (function() { + var bodyRan = false; + var caught; + try { + (function() { + using x = { [Symbol.dispose]: 123 }; + bodyRan = true; + })(); + } catch (e) { caught = e; } + assert(bodyRan, false); + assert(caught instanceof TypeError, true); + })(); + + /* null / undefined are spec-permitted and must not throw. */ + (function() { + var disposed = 0; + (function() { + using a = null; + using b = undefined; + using c = { [Symbol.dispose]() { disposed++; } }; + })(); + assert(disposed, 1); + })(); + + /* for-of using: validation applies per-iteration. */ + (function() { + var iters = 0; + var caught; + try { + (function() { + for (using x of [{ [Symbol.dispose]() {} }, 42]) { + iters++; + } + })(); + } catch (e) { caught = e; } + assert(iters, 1); + assert(caught instanceof TypeError, true); + })(); + + /* for-of using: normal completion must not throw (regression for + a prior bug where each iteration threw `undefined`). */ + (function() { + var log = []; + (function() { + for (using x of [ + { tag: "a", [Symbol.dispose]() { log.push(this.tag); } }, + { tag: "b", [Symbol.dispose]() { log.push(this.tag); } }, + { tag: "c", [Symbol.dispose]() { log.push(this.tag); } }, + ]) { + log.push("iter"); + } + })(); + assert_array_eq(log, ["iter", "a", "iter", "b", "iter", "c"]); + })(); + + /* LIFO disposal order. */ + (function() { + var log = []; + (function() { + using a = { [Symbol.dispose]() { log.push("a"); } }; + using b = { [Symbol.dispose]() { log.push("b"); } }; + using c = { [Symbol.dispose]() { log.push("c"); } }; + })(); + assert_array_eq(log, ["c", "b", "a"]); + })(); + + /* Multiple dispose errors chain as SuppressedError (error=new, + suppressed=previous). */ + (function() { + var caught; + try { + (function() { + using a = { [Symbol.dispose]() { throw new Error("a"); } }; + using b = { [Symbol.dispose]() { throw new Error("b"); } }; + using c = { [Symbol.dispose]() { throw new Error("c"); } }; + })(); + } catch (e) { caught = e; } + /* LIFO: c first → error_state=c. b → Suppressed(b, c). + a → Suppressed(a, Suppressed(b, c)). */ + assert(caught instanceof SuppressedError, true); + assert(caught.error.message, "a"); + assert(caught.suppressed instanceof SuppressedError, true); + assert(caught.suppressed.error.message, "b"); + assert(caught.suppressed.suppressed.message, "c"); + })(); + + /* Symbol.dispose is read exactly once at declaration (snapshot). */ + (function() { + var reads = 0; + var disposed = 0; + var target = {}; + Object.defineProperty(target, Symbol.dispose, { + get() { + reads++; + return function() { disposed++; }; + } + }); + (function() { using x = target; })(); + assert(reads, 1); + assert(disposed, 1); + })(); + + /* DisposableStack.prototype.move uses the %DisposableStack% + intrinsic; tampering with or deleting the global binding must + not redirect it. */ + (function() { + var saved = globalThis.DisposableStack; + try { + var ds = new saved(); + var disposed = 0; + ds.use({ [Symbol.dispose]() { disposed++; } }); + globalThis.DisposableStack = class Other {}; + var moved = ds.move(); + assert(Object.getPrototypeOf(moved), saved.prototype); + moved.dispose(); + assert(disposed, 1); + delete globalThis.DisposableStack; + var ds2 = new saved(); + ds2.use({ [Symbol.dispose]() {} }); + var moved2 = ds2.move(); + assert(Object.getPrototypeOf(moved2), saved.prototype); + } finally { + globalThis.DisposableStack = saved; + } + })(); + + /* SuppressedError wrapping can't be hijacked via prototype.constructor. */ + (function() { + var savedCtor = SuppressedError.prototype.constructor; + try { + var hijacked = false; + SuppressedError.prototype.constructor = function() { + hijacked = true; + throw new Error("hijack"); + }; + var caught; + try { + (function() { + using a = { [Symbol.dispose]() { throw new Error("a"); } }; + using b = { [Symbol.dispose]() { throw new Error("b"); } }; + })(); + } catch (e) { caught = e; } + assert(hijacked, false); + assert(caught instanceof SuppressedError, true); + assert(caught.error.message, "a"); + assert(caught.suppressed.message, "b"); + } finally { + SuppressedError.prototype.constructor = savedCtor; + } + })(); +} + +/* Async counterpart: `await using` and AsyncDisposableStack. */ +async function test_await_using() +{ + /* await using validates the async/sync dispose method at declaration. */ + { + var bodyRan = false; + var caught; + try { + await (async function() { + await using x = {}; + bodyRan = true; + })(); + } catch (e) { caught = e; } + assert(bodyRan, false); + assert(caught instanceof TypeError, true); + } + + /* Falls back to Symbol.dispose when @@asyncDispose is absent. */ + { + var ok = false; + await (async function() { + await using x = { [Symbol.dispose]() {} }; + ok = true; + })(); + assert(ok, true); + } + + /* AsyncDisposableStack.disposeAsync must await each dispose's returned + promise before invoking the next one (regression for a prior bug + that called all disposes in a single synchronous pass). */ + { + var log = []; + var stack = new AsyncDisposableStack(); + stack.use({ + async [Symbol.asyncDispose]() { log.push("outer-called"); } + }); + stack.use({ + async [Symbol.asyncDispose]() { + log.push("inner-called"); + await null; + log.push("inner-after-await"); + } + }); + var p = stack.disposeAsync(); + log.push("after-sync-dispose"); + await p; + assert_array_eq(log, [ + "inner-called", + "after-sync-dispose", + "inner-after-await", + "outer-called" + ]); + } + + /* disposeAsync called twice without awaiting the first must still + dispose all resources in LIFO order. */ + { + var log = []; + var stack = new AsyncDisposableStack(); + stack.use({ [Symbol.asyncDispose]() { log.push(42); } }); + stack.use({ [Symbol.asyncDispose]() { log.push(43); } }); + stack.disposeAsync(); + assert(stack.disposed, true); + await stack.disposeAsync(); + assert_array_eq(log, [43, 42]); + } + + /* LIFO. */ + { + var log = []; + var stack = new AsyncDisposableStack(); + stack.use({ [Symbol.asyncDispose]() { log.push("a"); } }); + stack.use({ [Symbol.asyncDispose]() { log.push("b"); } }); + stack.use({ [Symbol.asyncDispose]() { log.push("c"); } }); + await stack.disposeAsync(); + assert_array_eq(log, ["c", "b", "a"]); + } + + /* SuppressedError chaining across async dispose errors. */ + { + var stack = new AsyncDisposableStack(); + stack.use({ + async [Symbol.asyncDispose]() { throw new Error("first"); } + }); + stack.use({ + async [Symbol.asyncDispose]() { throw new Error("second"); } + }); + var caught; + try { + await stack.disposeAsync(); + } catch (e) { caught = e; } + /* LIFO: second throws → completion=second. first throws → + Suppressed(error=first, suppressed=second). */ + assert(caught instanceof SuppressedError, true); + assert(caught.error.message, "first"); + assert(caught.suppressed.message, "second"); + } + + /* disposeAsync always resolves to undefined. */ + { + var stack = new AsyncDisposableStack(); + stack.use({ [Symbol.asyncDispose]() { return 42; } }); + stack.use({ async [Symbol.asyncDispose]() { return "hello"; } }); + var result = await stack.disposeAsync(); + assert(result, undefined); + } +} + + +test_op1(); +test_cvt(); +test_eq(); +test_inc_dec(); +test_op2(); +test_delete(); +test_constructor(); +test_prototype(); +test_arguments(); +test_class(); +test_template(); +test_template_skip(); +test_object_literal(); +test_regexp_skip(); +test_labels(); +test_destructuring(); +test_spread(); +test_function_length(); +test_argument_scope(); +test_function_expr_name(); +test_reserved_names(); +test_number_literals(); +test_syntax(); +test_optional_chaining(); +test_parse_semicolon(); +test_non_extensible_receiver_existing_property_set(); +test_using(); +test_await_using().catch(e => { throw e; }); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_loop.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_loop.js new file mode 100755 index 00000000..97fc2f68 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_loop.js @@ -0,0 +1,367 @@ +// This test cannot use imports because it needs to run in non-strict mode. + +function assert(actual, expected, message) { + if (arguments.length == 1) + expected = true; + + if (actual === expected) + return; + + if (actual !== null && expected !== null + && typeof actual == 'object' && typeof expected == 'object' + && actual.toString() === expected.toString()) + return; + + throw Error("assertion failed: got |" + actual + "|" + + ", expected |" + expected + "|" + + (message ? " (" + message + ")" : "")); +} + +/*----------------*/ + +function test_while() +{ + var i, c; + i = 0; + c = 0; + while (i < 3) { + c++; + i++; + } + assert(c, 3); +} + +function test_while_break() +{ + var i, c; + i = 0; + c = 0; + while (i < 3) { + c++; + if (i == 1) + break; + i++; + } + assert(c === 2 && i === 1); +} + +function test_do_while() +{ + var i, c; + i = 0; + c = 0; + do { + c++; + i++; + } while (i < 3); + assert(c === 3 && i === 3); +} + +function test_for() +{ + var i, c; + c = 0; + for(i = 0; i < 3; i++) { + c++; + } + assert(c === 3 && i === 3); + + c = 0; + for(var j = 0; j < 3; j++) { + c++; + } + assert(c === 3 && j === 3); +} + +function test_for_in() +{ + var i, tab, a, b; + + tab = []; + for(i in {x:1, y: 2}) { + tab.push(i); + } + assert(tab.toString(), "x,y", "for_in"); + + /* prototype chain test */ + a = {x:2, y: 2, "1": 3}; + b = {"4" : 3 }; + Object.setPrototypeOf(a, b); + tab = []; + for(i in a) { + tab.push(i); + } + assert(tab.toString(), "1,x,y,4", "for_in"); + + /* non enumerable properties hide enumerables ones in the + prototype chain */ + a = {y: 2, "1": 3}; + Object.defineProperty(a, "x", { value: 1 }); + b = {"x" : 3 }; + Object.setPrototypeOf(a, b); + tab = []; + for(i in a) { + tab.push(i); + } + assert(tab.toString(), "1,y", "for_in"); + + /* array optimization */ + a = []; + for(i = 0; i < 10; i++) + a.push(i); + tab = []; + for(i in a) { + tab.push(i); + } + assert(tab.toString(), "0,1,2,3,4,5,6,7,8,9", "for_in"); + + /* iterate with a field */ + a={x:0}; + tab = []; + for(a.x in {x:1, y: 2}) { + tab.push(a.x); + } + assert(tab.toString(), "x,y", "for_in"); + + /* iterate with a variable field */ + a=[0]; + tab = []; + for(a[0] in {x:1, y: 2}) { + tab.push(a[0]); + } + assert(tab.toString(), "x,y", "for_in"); + + /* variable definition in the for in */ + tab = []; + for(var j in {x:1, y: 2}) { + tab.push(j); + } + assert(tab.toString(), "x,y", "for_in"); + + /* variable assigment in the for in */ + tab = []; + for(var k = 2 in {x:1, y: 2}) { + tab.push(k); + } + assert(tab.toString(), "x,y", "for_in"); +} + +function test_for_in2() +{ + var i; + tab = []; + for(i in {x:1, y: 2, z:3}) { + if (i === "y") + continue; + tab.push(i); + } + assert(tab.toString() == "x,z"); + + tab = []; + for(i in {x:1, y: 2, z:3}) { + if (i === "z") + break; + tab.push(i); + } + assert(tab.toString() == "x,y"); +} + +function test_for_break() +{ + var i, c; + c = 0; + L1: for(i = 0; i < 3; i++) { + c++; + if (i == 0) + continue; + while (1) { + break L1; + } + } + assert(c === 2 && i === 1); +} + +function test_switch1() +{ + var i, a, s; + s = ""; + for(i = 0; i < 3; i++) { + a = "?"; + switch(i) { + case 0: + a = "a"; + break; + case 1: + a = "b"; + break; + default: + a = "c"; + break; + } + s += a; + } + assert(s === "abc" && i === 3); +} + +function test_switch2() +{ + var i, a, s; + s = ""; + for(i = 0; i < 4; i++) { + a = "?"; + switch(i) { + case 0: + a = "a"; + break; + case 1: + a = "b"; + break; + case 2: + continue; + default: + a = "" + i; + break; + } + s += a; + } + assert(s === "ab3" && i === 4); +} + +function test_try_catch1() +{ + try { + throw "hello"; + } catch (e) { + assert(e, "hello", "catch"); + return; + } + assert(false, "catch"); +} + +function test_try_catch2() +{ + var a; + try { + a = 1; + } catch (e) { + a = 2; + } + assert(a, 1, "catch"); +} + +function test_try_catch3() +{ + var s; + s = ""; + try { + s += "t"; + } catch (e) { + s += "c"; + } finally { + s += "f"; + } + assert(s, "tf", "catch"); +} + +function test_try_catch4() +{ + var s; + s = ""; + try { + s += "t"; + throw "c"; + } catch (e) { + s += e; + } finally { + s += "f"; + } + assert(s, "tcf", "catch"); +} + +function test_try_catch5() +{ + var s; + s = ""; + for(;;) { + try { + s += "t"; + break; + s += "b"; + } finally { + s += "f"; + } + } + assert(s, "tf", "catch"); +} + +function test_try_catch6() +{ + function f() { + try { + s += 't'; + return 1; + } finally { + s += "f"; + } + } + var s = ""; + assert(f() === 1); + assert(s, "tf", "catch6"); +} + +function test_try_catch7() +{ + var s; + s = ""; + + try { + try { + s += "t"; + throw "a"; + } finally { + s += "f"; + } + } catch(e) { + s += e; + } finally { + s += "g"; + } + assert(s, "tfag", "catch"); +} + +function test_try_catch8() +{ + var i, s; + + s = ""; + for(var i in {x:1, y:2}) { + try { + s += i; + throw "a"; + } catch (e) { + s += e; + } finally { + s += "f"; + } + } + assert(s === "xafyaf"); +} + +test_while(); +test_while_break(); +test_do_while(); +test_for(); +test_for_break(); +test_switch1(); +test_switch2(); +test_for_in(); +test_for_in2(); + +test_try_catch1(); +test_try_catch2(); +test_try_catch3(); +test_try_catch4(); +test_try_catch5(); +test_try_catch6(); +test_try_catch7(); +test_try_catch8(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_queue_microtask.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_queue_microtask.js new file mode 100755 index 00000000..f06dc8bd --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_queue_microtask.js @@ -0,0 +1,39 @@ +import { assert, assertArrayEquals, assertThrows } from "./assert.js"; + +function test_types() { + assertThrows(TypeError, () => queueMicrotask(), "no argument"); + assertThrows(TypeError, () => queueMicrotask(undefined), "undefined"); + assertThrows(TypeError, () => queueMicrotask(null), "null"); + assertThrows(TypeError, () => queueMicrotask(0), "0"); + assertThrows(TypeError, () => queueMicrotask({ handleEvent() { } }), "an event handler object"); + assertThrows(TypeError, () => queueMicrotask("window.x = 5;"), "a string"); +} + +function test_async() { + let called = false; + queueMicrotask(() => { + called = true; + }); + assert(!called); +} + +function test_arguments() { + queueMicrotask(function () { // note: intentionally not an arrow function + assert(arguments.length === 0); + }, "x", "y"); +}; + +function test_async_order() { + const happenings = []; + Promise.resolve().then(() => happenings.push("a")); + queueMicrotask(() => happenings.push("b")); + Promise.reject().catch(() => happenings.push("c")); + queueMicrotask(() => { + assertArrayEquals(happenings, ["a", "b", "c"]); + }); +} + +test_types(); +test_async(); +test_arguments(); +test_async_order(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_std.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_std.js new file mode 100755 index 00000000..443b6990 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_std.js @@ -0,0 +1,340 @@ +import * as std from "qjs:std"; +import * as os from "qjs:os"; +import { assert } from "./assert.js"; + +const isWin = os.platform === 'win32'; +const isCygwin = os.platform === 'cygwin'; + + +function test_printf() +{ + assert(std.sprintf("a=%d s=%s", 123, "abc"), "a=123 s=abc"); + assert(std.sprintf("%010d", 123), "0000000123"); + assert(std.sprintf("%x", -2), "fffffffe"); + assert(std.sprintf("%lx", -2), "fffffffffffffffe"); + assert(std.sprintf("%10.1f", 2.1), " 2.1"); + assert(std.sprintf("%*.*f", 10, 2, -2.13), " -2.13"); + assert(std.sprintf("%#lx", 0x7fffffffffffffffn), "0x7fffffffffffffff"); +} + +function test_file1() +{ + var f, len, str, size, buf, ret, i, str1, ab; + + f = std.tmpfile(); + str = "hello world\n"; + f.puts(str); + + f.seek(0, std.SEEK_SET); + ab = f.readAsArrayBuffer(); + assert([...new Uint8Array(ab)], str.split("").map(c => c.charCodeAt(0))); + + f.seek(0, std.SEEK_SET); + str1 = f.readAsString(); + assert(str1, str); + + f.seek(0, std.SEEK_END); + size = f.tell(); + assert(size, str.length); + + f.seek(0, std.SEEK_SET); + + buf = new Uint8Array(size); + ret = f.read(buf.buffer, 0, size); + assert(ret, size); + for(i = 0; i < size; i++) + assert(buf[i], str.charCodeAt(i)); + + f.close(); +} + +function test_file2() +{ + var f, str, i, size; + f = std.tmpfile(); + str = "hello world\n"; + size = str.length; + for(i = 0; i < size; i++) + f.putByte(str.charCodeAt(i)); + f.seek(0, std.SEEK_SET); + for(i = 0; i < size; i++) { + assert(str.charCodeAt(i), f.getByte()); + } + assert(f.getByte(), -1); + f.close(); +} + +function test_getline() +{ + var f, line, line_count, lines, i; + + lines = ["hello world", "line 1", "line 2" ]; + f = std.tmpfile(); + for(i = 0; i < lines.length; i++) { + f.puts(lines[i], "\n"); + } + + f.seek(0, std.SEEK_SET); + assert(!f.eof()); + line_count = 0; + for(;;) { + line = f.getline(); + if (line === null) + break; + assert(line, lines[line_count]); + line_count++; + } + assert(f.eof()); + assert(line_count, lines.length); + + f.close(); +} + +function test_popen() +{ + var str, f, fname = "tmp_file.txt"; + var ta, content = "hello world"; + var cmd = isWin ? "type" : "cat"; + + ta = new Uint8Array([...content].map(c => c.charCodeAt(0))); + std.writeFile(fname, ta); + assert(std.loadFile(fname), content); + std.writeFile(fname, ta.buffer); + assert(std.loadFile(fname), content); + std.writeFile(fname, content); + assert(std.loadFile(fname), content); + + // popen pipe is unidirectional so mode should + // be either read or write but not both + let caught = false; + try { + std.popen(cmd, "rw"); + } catch (e) { + assert(/invalid file mode/.test(e.message)); + caught = true; + } + assert(caught); + + /* execute shell command */ + f = std.popen(cmd + " " + fname, "r"); + str = f.readAsString(); + f.close(); + + assert(str, content); + + os.remove(fname); +} + +function test_os() +{ + var fd, fpath, fname, fdir, buf, buf2, i, files, err, fdate, st, link_path; + + // XXX(bnoordhuis) disabled because stdio is not a tty on CI + //assert(os.isatty(0)); + + fdir = "test_tmp_dir"; + fname = "tmp_file.txt"; + fpath = fdir + "/" + fname; + link_path = fdir + "/test_link"; + + os.remove(link_path); + os.remove(fpath); + os.remove(fdir); + + err = os.mkdir(fdir, 0o755); + assert(err, 0); + + fd = os.open(fpath, os.O_RDWR | os.O_CREAT | os.O_TRUNC); + assert(fd >= 0); + + buf = new Uint8Array(10); + for(i = 0; i < buf.length; i++) + buf[i] = i; + assert(os.write(fd, buf.buffer, 0, buf.length), buf.length); + + assert(os.seek(fd, 0, std.SEEK_SET), 0); + buf2 = new Uint8Array(buf.length); + assert(os.read(fd, buf2.buffer, 0, buf2.length), buf2.length); + + for(i = 0; i < buf.length; i++) + assert(buf[i] == buf2[i]); + + if (typeof BigInt !== "undefined") { + assert(os.seek(fd, BigInt(6), std.SEEK_SET), BigInt(6)); + assert(os.read(fd, buf2.buffer, 0, 1), 1); + assert(buf[6] == buf2[0]); + } + + assert(os.close(fd), 0); + + [files, err] = os.readdir(fdir); + assert(err, 0); + assert(files.length >= 3); + assert(files.includes(fname)); + assert(files.includes(".")); + assert(files.includes("..")); + + fdate = 10000; + + err = os.utimes(fpath, fdate, fdate); + assert(err, 0); + + [st, err] = os.stat(fpath); + assert(err, 0); + assert(st.mode & os.S_IFMT, os.S_IFREG); + assert(st.mtime, fdate); + + if (!isWin) { + err = os.symlink(fname, link_path); + assert(err, 0); + + [st, err] = os.lstat(link_path); + assert(err, 0); + assert(st.mode & os.S_IFMT, os.S_IFLNK); + + [buf, err] = os.readlink(link_path); + assert(err, 0); + assert(buf, fname); + + assert(os.remove(link_path) === 0); + } + + [buf, err] = os.getcwd(); + assert(err, 0); + + [buf2, err] = os.realpath("."); + assert(err, 0); + + assert(buf, buf2); + + assert(os.remove(fpath) === 0); + + fd = os.open(fpath, os.O_RDONLY); + assert(fd < 0); + + assert(os.remove(fdir) === 0); + + if (!isWin) { + [fdir, err] = os.mkdtemp(); + assert(err, 0); + assert(fdir.startsWith("tmp")); + assert(fdir.length, 9); + + [fpath, fd] = os.mkstemp(`${fdir}/XXXXXX`); + assert(fdir.startsWith(`${fdir}`)); + assert(fd >= 0); + + const f = std.fdopen(fd, "w+"); + f.write("xyzzy"); + f.flush(); + const b = new Uint8Array(5); + f.seek(0, std.SEEK_SET); + assert(5, f.read(b.buffer)); + const s = [...b].map(c => String.fromCharCode(c)).join(""); + assert(s, "xyzzy"); + f.seek(0, std.SEEK_SET); + assert(0, f.read(b.buffer, 5, 42)); + f.close(); + + assert(os.remove(fpath), 0); + assert(os.remove(fdir), 0); + } +} + +function test_os_exec() +{ + var ret, fds, pid, f, status; + + ret = os.exec(["true"]); + assert(ret, 0); + + ret = os.exec(["/bin/sh", "-c", "exit 1"], { usePath: false }); + assert(ret, 1); + + fds = os.pipe(); + pid = os.exec(["sh", "-c", "echo $FOO"], { + stdout: fds[1], + block: false, + env: { FOO: "hello" }, + } ); + assert(pid >= 0); + os.close(fds[1]); /* close the write end (as it is only in the child) */ + f = std.fdopen(fds[0], "r"); + assert(f.getline(), "hello"); + assert(f.getline(), null); + f.close(); + [ret, status] = os.waitpid(pid, 0); + assert(ret, pid); + assert(status & 0x7f, 0); /* exited */ + assert(status >> 8, 0); /* exit code */ + + pid = os.exec(["cat"], { block: false } ); + assert(pid >= 0); + os.kill(pid, os.SIGTERM); + [ret, status] = os.waitpid(pid, 0); + assert(ret, pid); + // Flaky on cygwin for unclear reasons, see + // https://github.com/quickjs-ng/quickjs/issues/184 + if (!isCygwin) { + assert(status & 0x7f, os.SIGTERM); + } +} + +function test_interval() +{ + var t = os.setInterval(f, 1); + function f() { + if (++f.count === 3) os.clearInterval(t); + } + f.count = 0; +} + +function test_timeout() +{ + var th, i; + + /* just test that a timer can be inserted and removed */ + th = []; + for(i = 0; i < 3; i++) + th[i] = os.setTimeout(function () { }, 1000); + for(i = 0; i < 3; i++) + os.clearTimeout(th[i]); +} + +function test_timeout_order() +{ + var s = ""; + os.setTimeout(a, 0); + os.setTimeout(b, 100); + os.setTimeout(d, 700); + function a() { s += "a"; os.setTimeout(c, 300); } + function b() { s += "b"; } + function c() { s += "c"; } + function d() { assert(s, "abc"); } // not "acb" +} + +function test_stdio_close() +{ + for (const f of [std.in, std.out, std.err]) { + let caught = false; + try { + f.close(); + } catch (e) { + assert(/cannot close stdio/.test(e.message)); + caught = true; + } + assert(caught); + } +} + +test_printf(); +test_file1(); +test_file2(); +test_getline(); +test_popen(); +test_os(); +!isWin && test_os_exec(); +test_interval(); +test_timeout(); +test_timeout_order(); +test_stdio_close(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_string_exports.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_string_exports.js new file mode 100755 index 00000000..3198716e --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_string_exports.js @@ -0,0 +1,25 @@ +// Test ES2020 string export/import names +import { assert } from "./assert.js"; +import * as mod from "./fixture_string_exports.js"; + +// Test string import names +import { "string-export-1" as str1 } from "./fixture_string_exports.js"; +import { "string-export-2" as str2 } from "./fixture_string_exports.js"; +import { "string-name" as strMixed } from "./fixture_string_exports.js"; + +// Test regular imports still work +import { regularExport, normalName } from "./fixture_string_exports.js"; + +// Verify values +assert(str1, "value-1"); +assert(str2, "value-2"); +assert(strMixed, "mixed-value"); +assert(regularExport, "regular"); +assert(normalName, "mixed-value"); + +// Verify module namespace has string-named exports +assert(mod["string-export-1"], "value-1"); +assert(mod["string-export-2"], "value-2"); +assert(mod["string-name"], "mixed-value"); +assert(mod.regularExport, "regular"); +assert(mod.normalName, "mixed-value"); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_worker.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_worker.js new file mode 100755 index 00000000..d1660ce5 --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_worker.js @@ -0,0 +1,43 @@ +import * as os from "qjs:os"; +import { assert } from "./assert.js"; + +var worker; + +function test_worker() +{ + var counter; + + worker = new os.Worker("./test_worker_module.js"); + + counter = 0; + worker.onmessage = function (e) { + var ev = e.data; +// print("recv", JSON.stringify(ev)); + switch(ev.type) { + case "num": + assert(ev.num, counter); + counter++; + if (counter == 10) { + /* test SharedArrayBuffer modification */ + let sab = new SharedArrayBuffer(10); + let buf = new Uint8Array(sab); + worker.postMessage({ type: "sab", buf: buf }); + } + break; + case "sab_done": + { + let buf = ev.buf; + /* check that the SharedArrayBuffer was modified */ + assert(buf[2], 10); + worker.postMessage({ type: "abort" }); + } + break; + case "done": + /* terminate */ + worker.onmessage = null; + break; + } + }; +} + +test_worker(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_worker_module.js b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_worker_module.js new file mode 100755 index 00000000..7280c69c --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/tests/test_worker_module.js @@ -0,0 +1,30 @@ +/* Worker code for test_worker.js */ +import * as os from "qjs:os"; + +var parent = os.Worker.parent; + +function handle_msg(e) { + var ev = e.data; + // print("child_recv", JSON.stringify(ev)); + switch(ev.type) { + case "abort": + parent.postMessage({ type: "done" }); + break; + case "sab": + /* modify the SharedArrayBuffer */ + ev.buf[2] = 10; + parent.postMessage({ type: "sab_done", buf: ev.buf }); + break; + } +} + +function worker_main() { + var i; + + parent.onmessage = handle_msg; + for(i = 0; i < 10; i++) { + parent.postMessage({ type: "num", num: i }); + } +} + +worker_main(); diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/unicode_download.sh b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/unicode_download.sh index fb8343a6..cc31b2aa 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/unicode_download.sh +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/unicode_download.sh @@ -1,7 +1,7 @@ #!/bin/sh set -e -url="ftp://ftp.unicode.org/Public/16.0.0/ucd" +url="https://www.unicode.org/Public/17.0.0/ucd" emoji_url="${url}/emoji/emoji-data.txt" files="CaseFolding.txt DerivedNormalizationProps.txt PropList.txt \ diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/unicode_gen_def.h b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/unicode_gen_def.h index 913d173a..7052496d 100755 --- a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/unicode_gen_def.h +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/unicode_gen_def.h @@ -54,6 +54,7 @@ DEF(Bamum, "Bamu") DEF(Bassa_Vah, "Bass") DEF(Batak, "Batk") DEF(Bengali, "Beng") +DEF(Beria_Erfe, "Berf") DEF(Bhaiksuki, "Bhks") DEF(Bopomofo, "Bopo") DEF(Brahmi, "Brah") @@ -107,6 +108,7 @@ DEF(Javanese, "Java") DEF(Kaithi, "Kthi") DEF(Kannada, "Knda") DEF(Katakana, "Kana") +DEF(Katakana_Or_Hiragana, "Hrkt") DEF(Kawi, "Kawi") DEF(Kayah_Li, "Kali") DEF(Kharoshthi, "Khar") @@ -178,6 +180,7 @@ DEF(Saurashtra, "Saur") DEF(Sharada, "Shrd") DEF(Shavian, "Shaw") DEF(Siddham, "Sidd") +DEF(Sidetic, "Sidt") DEF(SignWriting, "Sgnw") DEF(Sinhala, "Sinh") DEF(Sogdian, "Sogd") @@ -192,6 +195,7 @@ DEF(Tagbanwa, "Tagb") DEF(Tai_Le, "Tale") DEF(Tai_Tham, "Lana") DEF(Tai_Viet, "Tavt") +DEF(Tai_Yo, "Tayo") DEF(Takri, "Takr") DEF(Tamil, "Taml") DEF(Tangut, "Tang") @@ -203,6 +207,7 @@ DEF(Tifinagh, "Tfng") DEF(Tirhuta, "Tirh") DEF(Tangsa, "Tnsa") DEF(Todhri, "Todr") +DEF(Tolong_Siki, "Tols") DEF(Toto, "Toto") DEF(Tulu_Tigalari, "Tutg") DEF(Ugaritic, "Ugar") diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/update-version.sh b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/update-version.sh new file mode 100755 index 00000000..a9cb071b --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/source_ng/update-version.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +set -e + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +VERSION="$1" +MAJOR=$(echo "$VERSION" | cut -d. -f1) +MINOR=$(echo "$VERSION" | cut -d. -f2) +PATCH=$(echo "$VERSION" | cut -d. -f3) + +if [ -z "$MAJOR" ] || [ -z "$MINOR" ] || [ -z "$PATCH" ]; then + echo "Error: version must be in major.minor.patch format" + exit 1 +fi + +sed -i.bak \ + -e "s/^#define QJS_VERSION_MAJOR .*/#define QJS_VERSION_MAJOR $MAJOR/" \ + -e "s/^#define QJS_VERSION_MINOR .*/#define QJS_VERSION_MINOR $MINOR/" \ + -e "s/^#define QJS_VERSION_PATCH .*/#define QJS_VERSION_PATCH $PATCH/" \ + quickjs.h + +sed -i.bak \ + -e "s/^ version: '.*'/ version: '$VERSION'/" \ + meson.build + +rm -f quickjs.h.bak meson.build.bak + +echo "Version updated to $VERSION" diff --git a/test-app/runtime/src/main/cpp/napi/quickjs/update-quickjs.sh b/test-app/runtime/src/main/cpp/napi/quickjs/update-quickjs.sh new file mode 100755 index 00000000..a8d84c9a --- /dev/null +++ b/test-app/runtime/src/main/cpp/napi/quickjs/update-quickjs.sh @@ -0,0 +1,120 @@ +#!/usr/bin/env bash +# +# update-quickjs.sh — refresh a vendored QuickJS engine from upstream master +# and re-apply NativeScript's local patches. +# +# Two variants are supported: +# ng quickjs-ng -> https://github.com/quickjs-ng/quickjs.git -> ./source_ng +# bellard quickjs -> https://github.com/bellard/quickjs -> ./source +# +# We always track the upstream `master` branch. +# +# Usage: +# ./update-quickjs.sh [ng|bellard|all] (default: all) +# +# What it does, per selected variant: +# 1. Shallow-clones upstream master into a temp dir. +# 2. Copies every top-level *.c / *.h into the vendored source dir +# (engine only; NativeScript's quickjs-api.c / jsr.cpp live one level up +# and are never touched). +# 3. Re-applies the matching patch from ./patches. +# +# NativeScript only modifies the engine's quickjs.c (host-object support), so +# the patch targets that single file. If a future upstream refactor moves the +# patched lines, `patch` falls back to fuzzy matching and, failing that, writes +# a .rej for manual fixup. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PATCH_DIR="$SCRIPT_DIR/patches" + +NG_REPO="https://github.com/quickjs-ng/quickjs.git" +BELLARD_REPO="https://github.com/bellard/quickjs" + +err() { printf '\033[31m%s\033[0m\n' "$*" >&2; } +info() { printf '\033[36m%s\033[0m\n' "$*"; } +ok() { printf '\033[32m%s\033[0m\n' "$*"; } + +# update_variant +update_variant() { + local name="$1" repo="$2" dest="$3" patch="$4" + + info "==> [$name] updating $dest" + + if [[ ! -d "$dest" ]]; then + err "destination '$dest' does not exist — aborting $name" + return 1 + fi + if [[ ! -f "$patch" ]]; then + err "patch '$patch' not found — aborting $name" + return 1 + fi + + # Warn if anything other than quickjs.c has uncommitted local edits: those + # would be silently overwritten by the upstream copy. + if git -C "$dest" rev-parse --is-inside-work-tree >/dev/null 2>&1; then + local dirty + dirty="$(git -C "$dest" status --porcelain -- . | awk '{print $2}' | grep -v '^quickjs\.c$' || true)" + if [[ -n "$dirty" ]]; then + err "WARNING: uncommitted changes in $dest (besides quickjs.c) will be overwritten:" + err "$dirty" + read -r -p "Continue? [y/N] " reply + [[ "$reply" == [yY] ]] || { err "skipping $name"; return 1; } + fi + fi + + local tmp + tmp="$(mktemp -d)" + trap 'rm -rf "$tmp"' RETURN + + info " cloning $repo (master, shallow)" + git clone --depth 1 --branch master "$repo" "$tmp/src" >/dev/null 2>&1 \ + || git clone --depth 1 "$repo" "$tmp/src" >/dev/null 2>&1 + + local rev + rev="$(git -C "$tmp/src" rev-parse --short HEAD)" + info " upstream master @ $rev" + + info " copying top-level *.c / *.h -> $dest" + # Only top-level engine sources; never recurse into upstream's tests/, etc. + find "$tmp/src" -maxdepth 1 -type f \( -name '*.c' -o -name '*.h' \) \ + -exec cp -f {} "$dest"/ \; + + info " applying $(basename "$patch")" + if patch -p1 --forward --fuzz=3 -d "$dest" < "$patch" >/dev/null; then + ok " [$name] done (upstream $rev + patch applied)" + else + err " [$name] PATCH DID NOT APPLY CLEANLY — see *.rej in $dest" + err " re-generate the patch after fixing: " + err " git -C $dest diff --relative -- quickjs.c > $patch" + return 1 + fi +} + +main() { + local target="${1:-all}" + case "$target" in + ng) + update_variant ng "$NG_REPO" "$SCRIPT_DIR/source_ng" \ + "$PATCH_DIR/host-object-getproperty.ng.patch" + ;; + bellard) + update_variant bellard "$BELLARD_REPO" "$SCRIPT_DIR/source" \ + "$PATCH_DIR/host-object-getproperty.bellard.patch" + ;; + all) + update_variant ng "$NG_REPO" "$SCRIPT_DIR/source_ng" \ + "$PATCH_DIR/host-object-getproperty.ng.patch" + update_variant bellard "$BELLARD_REPO" "$SCRIPT_DIR/source" \ + "$PATCH_DIR/host-object-getproperty.bellard.patch" + ;; + *) + err "usage: $0 [ng|bellard|all]" + exit 2 + ;; + esac + ok "All requested variants updated. Review 'git diff' and rebuild." +} + +main "$@" diff --git a/test-app/runtime/src/main/cpp/napi/v8/jsr.cpp b/test-app/runtime/src/main/cpp/napi/v8/jsr.cpp index 48b382fe..a9b2e408 100644 --- a/test-app/runtime/src/main/cpp/napi/v8/jsr.cpp +++ b/test-app/runtime/src/main/cpp/napi/v8/jsr.cpp @@ -31,9 +31,9 @@ std::unique_ptr JSR::platform = nullptr; bool JSR::s_mainThreadInitialized = false; std::unordered_map JSR::env_to_jsr_cache; -napi_status js_create_runtime(napi_runtime *runtime) { +napi_status js_create_runtime(jsr_ns_runtime *runtime) { if (!runtime) return napi_invalid_arg; - *runtime = (napi_runtime) new JSR(); + *runtime = (jsr_ns_runtime) new JSR(); return napi_ok; } @@ -65,7 +65,7 @@ napi_status js_unlock_env(napi_env env) { return napi_ok; } -napi_status js_create_napi_env(napi_env *env, napi_runtime runtime) { +napi_status js_create_napi_env(napi_env *env, jsr_ns_runtime runtime) { if (env == nullptr) return napi_invalid_arg; JSR *jsr = (JSR *) runtime; // Must enter explictly @@ -122,7 +122,7 @@ napi_status js_free_napi_env(napi_env env) { return napi_ok; } -napi_status js_free_runtime(napi_runtime runtime) { +napi_status js_free_runtime(jsr_ns_runtime runtime) { JSR *jsr = (JSR *) runtime; jsr->isolate->Dispose(); delete jsr; diff --git a/test-app/runtime/src/main/cpp/napi/v8/jsr.h b/test-app/runtime/src/main/cpp/napi/v8/jsr.h index 90ef0127..09149e19 100644 --- a/test-app/runtime/src/main/cpp/napi/v8/jsr.h +++ b/test-app/runtime/src/main/cpp/napi/v8/jsr.h @@ -12,8 +12,6 @@ #include "JEnv.h" -typedef struct napi_runtime__ *napi_runtime; - class JSR { public: JSR(); diff --git a/test-app/runtime/src/main/cpp/napi/v8/v8-api.cpp b/test-app/runtime/src/main/cpp/napi/v8/v8-api.cpp index 1b23df4d..b9e110cd 100644 --- a/test-app/runtime/src/main/cpp/napi/v8/v8-api.cpp +++ b/test-app/runtime/src/main/cpp/napi/v8/v8-api.cpp @@ -3542,754 +3542,351 @@ napi_status NAPI_CDECL napi_is_detached_arraybuffer(napi_env env, return napi_clear_last_error(env); } -#ifdef __V8_13__ -namespace v8impl { - class NapiHostObject { - public: - NapiHostObject(napi_env env, bool is_array, napi_finalize finalize, void *data, - v8::Local value, v8::Local getter, - v8::Local setter) - : env_(env), is_array_(is_array), finalize_(finalize), data_(data) { - value_.Reset(env->isolate, value); - getter_.Reset(env->isolate, getter); - setter_.Reset(env->isolate, setter); - } - - ~NapiHostObject() { - value_.Reset(); - getter_.Reset(); - setter_.Reset(); - } - - // NOTE: Updated signatures to v18-style callbacks that return Intercepted - static v8::Intercepted - Getter(v8::Local property, const v8::PropertyCallbackInfo &info) { - auto isolate = info.GetIsolate(); - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - v8::Local v8Value = hostObject->value_.Get(isolate); - v8::Local target = v8Value.As(); - - if (hostObject->is_array_) { - v8::Local v8Getter = hostObject->getter_.Get(isolate); - napi_value js_property = v8impl::JsValueFromV8LocalValue(property); - napi_value result; - - napi_value argv[3] = { - v8impl::JsValueFromV8LocalValue(v8Value), - js_property, - v8impl::JsValueFromV8LocalValue(self) - }; - - napi_status status = napi_call_function(hostObject->env_, - v8impl::JsValueFromV8LocalValue( - isolate->GetCurrentContext()->Global()), - v8impl::JsValueFromV8LocalValue(v8Getter), - 3, - argv, &result); - if (status == napi_ok) { - info.GetReturnValue().Set(v8impl::V8LocalValueFromJsValue(result)); - return v8::Intercepted::kYes; - } else { - napi_value ex; - napi_get_and_clear_last_exception(hostObject->env_, &ex); - info.GetIsolate()->ThrowException(v8impl::V8LocalValueFromJsValue(ex)); - return v8::Intercepted::kYes; // handled (threw) - } - } else { - v8::Local result; - if (target->Get(isolate->GetCurrentContext(), property).ToLocal(&result)) { - info.GetReturnValue().Set(result); - return v8::Intercepted::kYes; - } - return v8::Intercepted::kNo; - } - } - - static v8::Intercepted Setter(v8::Local property, v8::Local value, - const v8::PropertyCallbackInfo &info) { - auto isolate = info.GetIsolate(); - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - - v8::Local v8Value = hostObject->value_.Get(isolate); - v8::Local target = v8Value.As(); - - if (hostObject->is_array_) { - v8::Local v8Setter = hostObject->setter_.Get(isolate); - napi_value js_property = v8impl::JsValueFromV8LocalValue(property); - napi_value js_value = v8impl::JsValueFromV8LocalValue(value); - napi_value result; - - napi_value argv[4] = { - v8impl::JsValueFromV8LocalValue(v8Value), - js_property, - js_value, - v8impl::JsValueFromV8LocalValue(self) - }; - - napi_status status = napi_call_function(hostObject->env_, - v8impl::JsValueFromV8LocalValue( - isolate->GetCurrentContext()->Global()), - v8impl::JsValueFromV8LocalValue(v8Setter), - 4, - argv, &result); - if (status == napi_ok) { - return v8::Intercepted::kYes; - } else { - napi_value ex; - napi_get_and_clear_last_exception(hostObject->env_, &ex); - info.GetIsolate()->ThrowException(v8impl::V8LocalValueFromJsValue(ex)); - return v8::Intercepted::kYes; // handled (threw) - } - } else { - target->Set(isolate->GetCurrentContext(), property, value).FromMaybe(false); - return v8::Intercepted::kYes; - } - } - - static v8::Intercepted - Query(v8::Local property, const v8::PropertyCallbackInfo &info) { - auto isolate = info.GetIsolate(); - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - - v8::Local v8Value = hostObject->value_.Get(isolate); - v8::Local target = v8Value.As(); - - if (target->Has(isolate->GetCurrentContext(), property).FromMaybe(false)) { - info.GetReturnValue().Set(v8::Integer::New(isolate, v8::None)); - return v8::Intercepted::kYes; - } - return v8::Intercepted::kNo; - } - - static v8::Intercepted - Deleter(v8::Local property, const v8::PropertyCallbackInfo &info) { - auto isolate = info.GetIsolate(); - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - - v8::Local v8Value = hostObject->value_.Get(isolate); - v8::Local target = v8Value.As(); - - if (target->Delete(isolate->GetCurrentContext(), property).FromMaybe(false)) { - info.GetReturnValue().Set(true); - return v8::Intercepted::kYes; - } - return v8::Intercepted::kNo; - } - - static void Enumerator(const v8::PropertyCallbackInfo &info) { - auto isolate = info.GetIsolate(); - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - - v8::Local v8Value = hostObject->value_.Get(isolate); - v8::Local target = v8Value.As(); - - v8::Local propertyNames = target->GetPropertyNames( - isolate->GetCurrentContext()).ToLocalChecked(); - info.GetReturnValue().Set(propertyNames); - } - - static v8::Intercepted IndexedGetter(uint32_t index, const v8::PropertyCallbackInfo &info) { - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - - v8::Local v8Value = hostObject->value_.Get(info.GetIsolate()); - v8::Local target = v8Value.As(); - - if (hostObject->is_array_) { - v8::Local v8Getter = v8::Local::New(info.GetIsolate(), - hostObject->getter_); - napi_value js_index = v8impl::JsValueFromV8LocalValue( - v8::Number::New(info.GetIsolate(), index)); - napi_value result; - - napi_value argv[3] = { - v8impl::JsValueFromV8LocalValue(v8Value), - js_index, - v8impl::JsValueFromV8LocalValue(info.Holder()) - }; - - napi_status status = napi_call_function(hostObject->env_, - v8impl::JsValueFromV8LocalValue( - info.GetIsolate()->GetCurrentContext()->Global()), - v8impl::JsValueFromV8LocalValue(v8Getter), - 3, - argv, &result); - if (status == napi_ok) { - info.GetReturnValue().Set(v8impl::V8LocalValueFromJsValue(result)); - return v8::Intercepted::kYes; - } else { - napi_value ex; - napi_get_and_clear_last_exception(hostObject->env_, &ex); - info.GetIsolate()->ThrowException(v8impl::V8LocalValueFromJsValue(ex)); - return v8::Intercepted::kYes; - } - } else { - v8::Local result; - if (target->Get(info.GetIsolate()->GetCurrentContext(), index).ToLocal(&result)) { - info.GetReturnValue().Set(result); - return v8::Intercepted::kYes; - } - return v8::Intercepted::kNo; - } - } - - static v8::Intercepted IndexedSetter(uint32_t index, v8::Local value, - const v8::PropertyCallbackInfo& info) { - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - - v8::Local v8Value = hostObject->value_.Get(info.GetIsolate()); - v8::Local target = v8Value.As(); - - - if (hostObject->is_array_) { - v8::Local v8Setter = v8::Local::New(info.GetIsolate(), - hostObject->setter_); - napi_value js_index = v8impl::JsValueFromV8LocalValue( - v8::Number::New(info.GetIsolate(), index)); - napi_value js_value = v8impl::JsValueFromV8LocalValue(value); - napi_value result; - - napi_value argv[4] = { - v8impl::JsValueFromV8LocalValue(v8Value), - js_index, - js_value, - v8impl::JsValueFromV8LocalValue(info.Holder()) - }; - - napi_status status = napi_call_function(hostObject->env_, - v8impl::JsValueFromV8LocalValue( - info.GetIsolate()->GetCurrentContext()->Global()), - v8impl::JsValueFromV8LocalValue(v8Setter), - 4, - argv, &result); - if (status == napi_ok) { - info.GetReturnValue().Set(v8impl::V8LocalValueFromJsValue(result)); - return v8::Intercepted::kYes; - } else { - napi_value ex; - napi_get_and_clear_last_exception(hostObject->env_, &ex); - info.GetIsolate()->ThrowException(v8impl::V8LocalValueFromJsValue(ex)); - return v8::Intercepted::kYes; - } - } else { - if (target->Set(info.GetIsolate()->GetCurrentContext(), index, value).FromMaybe( - false)) { - info.GetReturnValue().Set(value); - return v8::Intercepted::kYes; - } - return v8::Intercepted::kNo; - } - } - - static v8::Intercepted - IndexedQuery(uint32_t index, const v8::PropertyCallbackInfo &info) { - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - - v8::Local v8Value = hostObject->value_.Get(info.GetIsolate()); - v8::Local target = v8Value.As(); +#ifdef USE_HOST_OBJECT - if (target->Has(info.GetIsolate()->GetCurrentContext(), index).FromMaybe(false)) { - info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), v8::None)); - return v8::Intercepted::kYes; - } - return v8::Intercepted::kNo; - } - - static v8::Intercepted - IndexedDeleter(uint32_t index, const v8::PropertyCallbackInfo &info) { - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - - v8::Local v8Value = hostObject->value_.Get(info.GetIsolate()); - v8::Local target = v8Value.As(); - - if (target->Delete(info.GetIsolate()->GetCurrentContext(), index).FromMaybe(false)) { - info.GetReturnValue().Set(true); - return v8::Intercepted::kYes; - } - return v8::Intercepted::kNo; - } - - static void IndexedEnumerator(const v8::PropertyCallbackInfo &info) { - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - - v8::Local v8Value = hostObject->value_.Get(info.GetIsolate()); - v8::Local target = v8Value.As(); - - v8::Local propertyNames = target->GetPropertyNames( - info.GetIsolate()->GetCurrentContext()).ToLocalChecked(); - info.GetReturnValue().Set(propertyNames); - } - - napi_env env_; - bool is_array_; - napi_finalize finalize_; - void *data_; - v8::Persistent value_; - v8::Persistent getter_; - v8::Persistent setter_; - }; -} - -#else namespace v8impl { - class NapiHostObject { - public: - NapiHostObject(napi_env env, bool is_array, napi_finalize finalize, void *data, - v8::Local value, v8::Local getter, - v8::Local setter) - : env_(env), is_array_(is_array), finalize_(finalize), data_(data) { - value_.Reset(env->isolate, value); - getter_.Reset(env->isolate, getter); - setter_.Reset(env->isolate, setter); - } - - ~NapiHostObject() { - value_.Reset(); - getter_.Reset(); - setter_.Reset(); - } - - static void - Getter(v8::Local property, const v8::PropertyCallbackInfo &info) { - auto isolate = info.GetIsolate(); - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - v8::Local v8Value = hostObject->value_.Get(isolate); - v8::Local target = v8Value.As(); - - if (hostObject->is_array_) { - v8::Local v8Getter = hostObject->getter_.Get(isolate); - napi_value js_property = v8impl::JsValueFromV8LocalValue(property); - napi_value result; - - napi_value argv[3] = { - v8impl::JsValueFromV8LocalValue(v8Value), - js_property, - v8impl::JsValueFromV8LocalValue(self) - }; - - napi_status status = napi_call_function(hostObject->env_, - v8impl::JsValueFromV8LocalValue( - isolate->GetCurrentContext()->Global()), - v8impl::JsValueFromV8LocalValue(v8Getter), - 3, - argv, &result); - if (status == napi_ok) { - info.GetReturnValue().Set(v8impl::V8LocalValueFromJsValue(result)); - } else { - napi_value ex; - napi_get_and_clear_last_exception(hostObject->env_, &ex); - info.GetIsolate()->ThrowException(v8impl::V8LocalValueFromJsValue(ex)); - } - } else { - v8::Local result; - if (target->Get(isolate->GetCurrentContext(), property).ToLocal(&result)) { - info.GetReturnValue().Set(result); - } - } - } - static void Setter(v8::Local property, v8::Local value, - const v8::PropertyCallbackInfo &info) { - auto isolate = info.GetIsolate(); - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - - v8::Local v8Value = hostObject->value_.Get(isolate); - v8::Local target = v8Value.As(); - - if (hostObject->is_array_) { - v8::Local v8Setter = hostObject->setter_.Get(isolate); - napi_value js_property = v8impl::JsValueFromV8LocalValue(property); - napi_value js_value = v8impl::JsValueFromV8LocalValue(value); - napi_value result; - - napi_value argv[4] = { - v8impl::JsValueFromV8LocalValue(v8Value), - js_property, - js_value, - v8impl::JsValueFromV8LocalValue(self) - }; - - napi_status status = napi_call_function(hostObject->env_, - v8impl::JsValueFromV8LocalValue( - isolate->GetCurrentContext()->Global()), - v8impl::JsValueFromV8LocalValue(v8Setter), - 4, - argv, &result); - if (status == napi_ok) { - info.GetReturnValue().Set(v8impl::V8LocalValueFromJsValue(result)); - } else { - napi_value ex; - napi_get_and_clear_last_exception(hostObject->env_, &ex); - info.GetIsolate()->ThrowException(v8impl::V8LocalValueFromJsValue(ex)); - } - } else { - target->Set(isolate->GetCurrentContext(), property, value).FromMaybe(false); - info.GetReturnValue().Set(value); - } - } +// Property interceptors return v8::Intercepted on V8 12.1+ (here __V8_13__) and +// void on older V8 (the __else__ / V8_10 branch). These macros let the single +// host-object implementation below serve both ABIs. +#ifdef __V8_13__ +#define HOST_INTERCEPTED v8::Intercepted +#define HOST_HANDLED return v8::Intercepted::kYes +#define HOST_FALLTHROUGH return v8::Intercepted::kNo +#define HOST_SETTER_INFO const v8::PropertyCallbackInfo& +#define HOST_SETTER_HANDLED return v8::Intercepted::kYes +#else +#define HOST_INTERCEPTED void +#define HOST_HANDLED return +#define HOST_FALLTHROUGH return +#define HOST_SETTER_INFO const v8::PropertyCallbackInfo& +#define HOST_SETTER_HANDLED \ + do { \ + info.GetReturnValue().Set(value); \ + return; \ + } while (0) +#endif - static void - Query(v8::Local property, const v8::PropertyCallbackInfo &info) { - auto isolate = info.GetIsolate(); - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); +// A "host object" is a transparent proxy: every property operation is +// dispatched to the native callbacks in `methods_`, which receive the host +// object itself and the `data` pointer. There is no JS target and no prototype +// fiddling at this layer (callers do that); this keeps the proxy fully native. +class NapiHostObject { + public: + // Internal field 0 holds the wrapper; field 1 holds a process-unique sentinel + // so a host object can be recognized by a fast internal-field read. + enum InternalFields { kSlot = 0, kTypeSlot = 1, kInternalFieldCount = 2 }; + static void* TypeId() { + static char id = 0; + return &id; + } - v8::Local v8Value = hostObject->value_.Get(isolate); - v8::Local target = v8Value.As(); + static NapiHostObject* New(napi_env env, + napi_finalize finalize, + void* data, + const napi_host_object_methods* methods) { + return new NapiHostObject(env, finalize, data, methods); + } - if (target->Has(isolate->GetCurrentContext(), property).FromMaybe(false)) { - info.GetReturnValue().Set(v8::Integer::New(isolate, v8::None)); - } - } + static void Wrap(v8::Local object, NapiHostObject* self) { + object->SetAlignedPointerInInternalField(kSlot, self); + object->SetAlignedPointerInInternalField(kTypeSlot, TypeId()); + } - static void - Deleter(v8::Local property, const v8::PropertyCallbackInfo &info) { - auto isolate = info.GetIsolate(); - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); + static bool IsHostObject(v8::Local object) { + return object->InternalFieldCount() >= kInternalFieldCount && + object->GetAlignedPointerFromInternalField(kTypeSlot) == TypeId(); + } - v8::Local v8Value = hostObject->value_.Get(isolate); - v8::Local target = v8Value.As(); + static NapiHostObject* From(v8::Local object) { + return static_cast( + object->GetAlignedPointerFromInternalField(kSlot)); + } - if (target->Delete(isolate->GetCurrentContext(), property).FromMaybe(false)) { - info.GetReturnValue().Set(true); - } - } + void* Data() { return data_; } - static void Enumerator(const v8::PropertyCallbackInfo &info) { - auto isolate = info.GetIsolate(); - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); + // Runs (via a Reference finalizer) after the host object is collected: + // invokes the user finalizer (if any) and frees the wrapper. + static void Finalize(napi_env env, void* data, void* /*hint*/) { + auto* self = static_cast(data); + if (self->finalize_ != nullptr) { + self->finalize_(env, self->data_, nullptr); + } + delete self; + } - v8::Local v8Value = hostObject->value_.Get(isolate); - v8::Local target = v8Value.As(); + // ---------------- named interceptors ---------------- + static HOST_INTERCEPTED Getter( + v8::Local property, + const v8::PropertyCallbackInfo& info) { + v8::Local holder = info.Holder(); + auto* w = From(holder); + napi_value host = JsValueFromV8LocalValue(holder); + napi_value prop = JsValueFromV8LocalValue(property); + napi_value result = nullptr; + w->env_->CallIntoModule([&](napi_env env) { + result = w->methods_.get(env, host, prop, w->data_); + }); + if (result != nullptr) { + info.GetReturnValue().Set(V8LocalValueFromJsValue(result)); + } + HOST_HANDLED; + } - v8::Local propertyNames = target->GetPropertyNames( - isolate->GetCurrentContext()).ToLocalChecked(); - info.GetReturnValue().Set(propertyNames); - } + static HOST_INTERCEPTED Setter(v8::Local property, + v8::Local value, + HOST_SETTER_INFO info) { + v8::Local holder = info.Holder(); + auto* w = From(holder); + napi_value host = JsValueFromV8LocalValue(holder); + napi_value prop = JsValueFromV8LocalValue(property); + napi_value val = JsValueFromV8LocalValue(value); + w->env_->CallIntoModule([&](napi_env env) { + w->methods_.set(env, host, prop, val, w->data_); + }); + HOST_SETTER_HANDLED; + } - static void IndexedGetter(uint32_t index, const v8::PropertyCallbackInfo &info) { - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - - v8::Local v8Value = hostObject->value_.Get(info.GetIsolate()); - v8::Local target = v8Value.As(); - - if (hostObject->is_array_) { - v8::Local v8Getter = v8::Local::New(info.GetIsolate(), - hostObject->getter_); - napi_value js_index = v8impl::JsValueFromV8LocalValue( - v8::Number::New(info.GetIsolate(), index)); - napi_value result; - - napi_value argv[3] = { - v8impl::JsValueFromV8LocalValue(v8Value), - js_index, - v8impl::JsValueFromV8LocalValue(info.Holder()) - }; - - napi_status status = napi_call_function(hostObject->env_, - v8impl::JsValueFromV8LocalValue( - info.GetIsolate()->GetCurrentContext()->Global()), - v8impl::JsValueFromV8LocalValue(v8Getter), - 3, - argv, &result); - if (status == napi_ok) { - info.GetReturnValue().Set(v8impl::V8LocalValueFromJsValue(result)); - } else { - napi_value ex; - napi_get_and_clear_last_exception(hostObject->env_, &ex); - info.GetIsolate()->ThrowException(v8impl::V8LocalValueFromJsValue(ex)); - } - } else { - v8::Local result; - if (target->Get(info.GetIsolate()->GetCurrentContext(), index).ToLocal(&result)) { - info.GetReturnValue().Set(result); - } - } - } + static HOST_INTERCEPTED Query( + v8::Local property, + const v8::PropertyCallbackInfo& info) { + v8::Local holder = info.Holder(); + auto* w = From(holder); + if (w->methods_.has == nullptr) HOST_FALLTHROUGH; + napi_value host = JsValueFromV8LocalValue(holder); + napi_value prop = JsValueFromV8LocalValue(property); + bool present = false; + w->env_->CallIntoModule([&](napi_env env) { + present = w->methods_.has(env, host, prop, w->data_); + }); + if (!present) HOST_FALLTHROUGH; + info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), v8::None)); + HOST_HANDLED; + } - static void IndexedSetter(uint32_t index, v8::Local value, - const v8::PropertyCallbackInfo &info) { - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); - - v8::Local v8Value = hostObject->value_.Get(info.GetIsolate()); - v8::Local target = v8Value.As(); - - - if (hostObject->is_array_) { - v8::Local v8Setter = v8::Local::New(info.GetIsolate(), - hostObject->setter_); - napi_value js_index = v8impl::JsValueFromV8LocalValue( - v8::Number::New(info.GetIsolate(), index)); - napi_value js_value = v8impl::JsValueFromV8LocalValue(value); - napi_value result; - - napi_value argv[4] = { - v8impl::JsValueFromV8LocalValue(v8Value), - js_index, - js_value, - v8impl::JsValueFromV8LocalValue(info.Holder()) - }; - - napi_status status = napi_call_function(hostObject->env_, - v8impl::JsValueFromV8LocalValue( - info.GetIsolate()->GetCurrentContext()->Global()), - v8impl::JsValueFromV8LocalValue(v8Setter), - 4, - argv, &result); - if (status == napi_ok) { - info.GetReturnValue().Set(v8impl::V8LocalValueFromJsValue(result)); - } else { - napi_value ex; - napi_get_and_clear_last_exception(hostObject->env_, &ex); - info.GetIsolate()->ThrowException(v8impl::V8LocalValueFromJsValue(ex)); - } - } else { - if (target->Set(info.GetIsolate()->GetCurrentContext(), index, value).FromMaybe( - false)) { - info.GetReturnValue().Set(value); - } - } - } + static HOST_INTERCEPTED Deleter( + v8::Local property, + const v8::PropertyCallbackInfo& info) { + v8::Local holder = info.Holder(); + auto* w = From(holder); + if (w->methods_.delete_property == nullptr) HOST_FALLTHROUGH; + napi_value host = JsValueFromV8LocalValue(holder); + napi_value prop = JsValueFromV8LocalValue(property); + bool deleted = false; + w->env_->CallIntoModule([&](napi_env env) { + deleted = w->methods_.delete_property(env, host, prop, w->data_); + }); + info.GetReturnValue().Set(deleted); + HOST_HANDLED; + } - static void - IndexedQuery(uint32_t index, const v8::PropertyCallbackInfo &info) { - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); + static void Enumerator(const v8::PropertyCallbackInfo& info) { + v8::Local holder = info.Holder(); + auto* w = From(holder); + if (w->methods_.own_keys == nullptr) return; + napi_value host = JsValueFromV8LocalValue(holder); + napi_value keys = nullptr; + w->env_->CallIntoModule([&](napi_env env) { + keys = w->methods_.own_keys(env, host, w->data_); + }); + if (keys == nullptr) return; + v8::Local keys_value = V8LocalValueFromJsValue(keys); + if (keys_value->IsArray()) { + info.GetReturnValue().Set(keys_value.As()); + } + } - v8::Local v8Value = hostObject->value_.Get(info.GetIsolate()); - v8::Local target = v8Value.As(); + // ---------------- indexed interceptors ---------------- + static HOST_INTERCEPTED IndexedGetter( + uint32_t index, const v8::PropertyCallbackInfo& info) { + v8::Local holder = info.Holder(); + auto* w = From(holder); + napi_value host = JsValueFromV8LocalValue(holder); + napi_value result = nullptr; + if (w->methods_.indexed_get != nullptr) { + w->env_->CallIntoModule([&](napi_env env) { + result = w->methods_.indexed_get(env, host, index, w->data_); + }); + } else { + napi_value prop = JsValueFromV8LocalValue( + v8::Integer::NewFromUnsigned(info.GetIsolate(), index)); + w->env_->CallIntoModule([&](napi_env env) { + result = w->methods_.get(env, host, prop, w->data_); + }); + } + if (result != nullptr) { + info.GetReturnValue().Set(V8LocalValueFromJsValue(result)); + } + HOST_HANDLED; + } - if (target->Has(info.GetIsolate()->GetCurrentContext(), index).FromMaybe(false)) { - info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), v8::None)); - } - } + static HOST_INTERCEPTED IndexedSetter(uint32_t index, + v8::Local value, + HOST_SETTER_INFO info) { + v8::Local holder = info.Holder(); + auto* w = From(holder); + napi_value host = JsValueFromV8LocalValue(holder); + napi_value val = JsValueFromV8LocalValue(value); + if (w->methods_.indexed_set != nullptr) { + w->env_->CallIntoModule([&](napi_env env) { + w->methods_.indexed_set(env, host, index, val, w->data_); + }); + } else { + napi_value prop = JsValueFromV8LocalValue( + v8::Integer::NewFromUnsigned(info.GetIsolate(), index)); + w->env_->CallIntoModule([&](napi_env env) { + w->methods_.set(env, host, prop, val, w->data_); + }); + } + HOST_SETTER_HANDLED; + } - static void - IndexedDeleter(uint32_t index, const v8::PropertyCallbackInfo &info) { - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); + static HOST_INTERCEPTED IndexedQuery( + uint32_t index, const v8::PropertyCallbackInfo& info) { + v8::Local holder = info.Holder(); + auto* w = From(holder); + if (w->methods_.has == nullptr) HOST_FALLTHROUGH; + napi_value host = JsValueFromV8LocalValue(holder); + napi_value prop = JsValueFromV8LocalValue( + v8::Integer::NewFromUnsigned(info.GetIsolate(), index)); + bool present = false; + w->env_->CallIntoModule([&](napi_env env) { + present = w->methods_.has(env, host, prop, w->data_); + }); + if (!present) HOST_FALLTHROUGH; + info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), v8::None)); + HOST_HANDLED; + } - v8::Local v8Value = hostObject->value_.Get(info.GetIsolate()); - v8::Local target = v8Value.As(); + static HOST_INTERCEPTED IndexedDeleter( + uint32_t index, const v8::PropertyCallbackInfo& info) { + v8::Local holder = info.Holder(); + auto* w = From(holder); + if (w->methods_.delete_property == nullptr) HOST_FALLTHROUGH; + napi_value host = JsValueFromV8LocalValue(holder); + napi_value prop = JsValueFromV8LocalValue( + v8::Integer::NewFromUnsigned(info.GetIsolate(), index)); + bool deleted = false; + w->env_->CallIntoModule([&](napi_env env) { + deleted = w->methods_.delete_property(env, host, prop, w->data_); + }); + info.GetReturnValue().Set(deleted); + HOST_HANDLED; + } - if (target->Delete(info.GetIsolate()->GetCurrentContext(), index).FromMaybe(false)) { - info.GetReturnValue().Set(true); - } - } + private: + NapiHostObject(napi_env env, + napi_finalize finalize, + void* data, + const napi_host_object_methods* methods) + : env_(env), finalize_(finalize), data_(data), methods_(*methods) {} - static void IndexedEnumerator(const v8::PropertyCallbackInfo &info) { - v8::Local self = info.Holder(); - auto *hostObject = static_cast(self->GetAlignedPointerFromInternalField( - 0)); + ~NapiHostObject() = default; - v8::Local v8Value = hostObject->value_.Get(info.GetIsolate()); - v8::Local target = v8Value.As(); + napi_env env_; + napi_finalize finalize_; + void* data_; + napi_host_object_methods methods_; +}; - v8::Local propertyNames = target->GetPropertyNames( - info.GetIsolate()->GetCurrentContext()).ToLocalChecked(); - info.GetReturnValue().Set(propertyNames); - } +#undef HOST_INTERCEPTED +#undef HOST_HANDLED +#undef HOST_FALLTHROUGH +#undef HOST_SETTER_INFO +#undef HOST_SETTER_HANDLED - napi_env env_; - bool is_array_; - napi_finalize finalize_; - void *data_; - v8::Persistent value_; - v8::Persistent getter_; - v8::Persistent setter_; - }; -} -#endif +} // namespace v8impl +napi_status NAPI_CDECL +napi_create_host_object(napi_env env, + napi_finalize finalize, + void* data, + const napi_host_object_methods* methods, + napi_value* result) { + CHECK_ARG(env, methods); + CHECK_ARG(env, result); + RETURN_STATUS_IF_FALSE( + env, methods->get != nullptr && methods->set != nullptr, + napi_invalid_arg); -napi_status -napi_create_host_object(napi_env env, napi_value value, napi_finalize finalize, void *data, - bool is_array, napi_value getter, napi_value setter, napi_value *result) { - v8::Isolate *isolate = env->isolate; + v8::Isolate* isolate = env->isolate; v8::Local context = isolate->GetCurrentContext(); - // Convert napi_value to v8::Local - v8::Local v8Value = v8impl::V8LocalValueFromJsValue(value); - - // Check if the template is already cached if (env->host_object_template.IsEmpty()) { - // Create an ObjectTemplate for the host object - v8::Local hostObjectTemplate = v8::ObjectTemplate::New(isolate); - hostObjectTemplate->SetInternalFieldCount(4); // To store the NapiHostObject instance - - // Define the property handler configuration - v8::NamedPropertyHandlerConfiguration handlerConfiguration( - v8impl::NapiHostObject::Getter, - v8impl::NapiHostObject::Setter, - v8impl::NapiHostObject::Query, - v8impl::NapiHostObject::Deleter, - v8impl::NapiHostObject::Enumerator, - v8::Local(), // Data - v8::PropertyHandlerFlags::kNonMasking - ); - - // Set the property handler configuration on the template - hostObjectTemplate->SetHandler(handlerConfiguration); - - // Define the indexed property handler configuration - v8::IndexedPropertyHandlerConfiguration indexedHandlerConfiguration( - v8impl::NapiHostObject::IndexedGetter, - v8impl::NapiHostObject::IndexedSetter, - v8impl::NapiHostObject::IndexedQuery, - v8impl::NapiHostObject::IndexedDeleter, - nullptr, - nullptr, - nullptr - ); - - // Set the indexed property handler configuration on the template - hostObjectTemplate->SetHandler(indexedHandlerConfiguration); - - - // Cache the template - env->host_object_template.Reset(isolate, hostObjectTemplate); - } - - - // Create an instance of the host object - v8::Local hostObjectTemplate = env->host_object_template.Get(isolate); - v8::Local hostObject = hostObjectTemplate->NewInstance(context).ToLocalChecked(); - - v8::Local v8Getter; - v8::Local v8Setter; - if (is_array) { - v8Getter = v8impl::V8LocalValueFromJsValue(getter); - v8Setter = v8impl::V8LocalValueFromJsValue(setter); + v8::Local tpl = v8::ObjectTemplate::New(isolate); + tpl->SetInternalFieldCount( + v8impl::NapiHostObject::kInternalFieldCount); + + v8::NamedPropertyHandlerConfiguration named( + v8impl::NapiHostObject::Getter, + v8impl::NapiHostObject::Setter, + v8impl::NapiHostObject::Query, + v8impl::NapiHostObject::Deleter, + v8impl::NapiHostObject::Enumerator, + v8::Local(), + v8::PropertyHandlerFlags::kNonMasking); + tpl->SetHandler(named); + + v8::IndexedPropertyHandlerConfiguration indexed( + v8impl::NapiHostObject::IndexedGetter, + v8impl::NapiHostObject::IndexedSetter, + v8impl::NapiHostObject::IndexedQuery, + v8impl::NapiHostObject::IndexedDeleter, + nullptr, + nullptr, + nullptr); + tpl->SetHandler(indexed); + + env->host_object_template.Reset(isolate, tpl); + } + + v8::Local tpl = env->host_object_template.Get(isolate); + v8::Local hostObject = tpl->NewInstance(context).ToLocalChecked(); + + auto* self = v8impl::NapiHostObject::New(env, finalize, data, methods); + v8impl::NapiHostObject::Wrap(hostObject, self); - } - - // Store the NapiHostObject instance in the internal field - auto *hostInfo = new v8impl::NapiHostObject(env, is_array, finalize, data, v8Value, v8Getter, - v8Setter); - - - hostObject->SetAlignedPointerInInternalField(0, hostInfo); - - // Set the prototype of the host object to the prototype of the value - v8::Local valueObject = v8Value.As(); - hostObject->SetPrototype(context, valueObject->GetPrototype()); - - v8::Local superPropertyName = v8::String::NewFromUtf8(isolate, - "super").ToLocalChecked(); - -#ifdef __V8_13__ - v8::Local superGetter; - v8::MaybeLocal maybeGetter = v8::Function::New( - context, - [](const v8::FunctionCallbackInfo& info) { - v8::Local jsThis = info.Data().As(); - v8::Local property = info.This().As(); - v8::Local superValue; - if (jsThis->Get(info.GetIsolate()->GetCurrentContext(), property).ToLocal(&superValue)) { - info.GetReturnValue().Set(superValue); - } - }, - valueObject - ); - - if (maybeGetter.ToLocal(&superGetter)) { - hostObject->SetAccessorProperty( - superPropertyName, - superGetter, - v8::Local(), // No setter - v8::PropertyAttribute::None - ); - } -#else - hostObject->SetAccessor(context, superPropertyName, [](v8::Local property, - const v8::PropertyCallbackInfo &info) { - v8::Local jsThis = info.Data().As(); - v8::Local superValue; - if (jsThis->Get(info.GetIsolate()->GetCurrentContext(), property).ToLocal(&superValue)) { - info.GetReturnValue().Set(superValue); - } - }, nullptr, valueObject); -#endif - // Wrap the host object in a napi_value *result = v8impl::JsValueFromV8LocalValue(hostObject); - // Set the finalizer if provided - if (finalize != nullptr) { - v8impl::Reference::New(env, hostObject, 0, v8impl::Ownership::kRuntime, - [](napi_env env, void *d1, void *d2) { - auto hostInfo = reinterpret_cast(d1); - if (hostInfo->finalize_) { - hostInfo->finalize_(env, hostInfo->data_, nullptr); - } - delete hostInfo; - }, hostInfo, nullptr); - } + // Free the wrapper (and run the user finalizer, if any) once the host + // object is collected. Registered unconditionally so the wrapper never + // leaks. + v8impl::Reference::New(env, + hostObject, + 0, + v8impl::Ownership::kRuntime, + v8impl::NapiHostObject::Finalize, + self, + nullptr); - return napi_ok; + return napi_clear_last_error(env); } -napi_status napi_get_host_object_data(napi_env env, napi_value object, void **data) { - v8::Local v8Value = v8::Local::Cast( - v8impl::V8LocalValueFromJsValue(object)); +napi_status NAPI_CDECL +napi_get_host_object_data(napi_env env, napi_value object, void** data) { + CHECK_ARG(env, object); + CHECK_ARG(env, data); - if (v8Value->InternalFieldCount() != 4) { - *data = nullptr; - return napi_ok; + v8::Local value = v8impl::V8LocalValueFromJsValue(object); + *data = nullptr; + if (value->IsObject()) { + v8::Local obj = value.As(); + if (v8impl::NapiHostObject::IsHostObject(obj)) { + *data = v8impl::NapiHostObject::From(obj)->Data(); + } } - void *v8data = v8Value->GetAlignedPointerFromInternalField(0); - - auto hostInfo = reinterpret_cast(v8data); - - *data = hostInfo->data_; - - return napi_ok; + return napi_clear_last_error(env); } +napi_status NAPI_CDECL +napi_is_host_object(napi_env env, napi_value object, bool* result) { + CHECK_ARG(env, object); + CHECK_ARG(env, result); -napi_status napi_is_host_object(napi_env env, napi_value object, bool* result) { - v8::Local v8Value = v8::Local::Cast( - v8impl::V8LocalValueFromJsValue(object)); - - if (v8Value->InternalFieldCount() != 4) { - *result = false; - return napi_ok; - } - - *result = true; + v8::Local value = v8impl::V8LocalValueFromJsValue(object); + *result = value->IsObject() && + v8impl::NapiHostObject::IsHostObject(value.As()); + return napi_clear_last_error(env); +} - return napi_ok; -} \ No newline at end of file +#endif // USE_HOST_OBJECT diff --git a/test-app/runtime/src/main/cpp/runtime/Runtime.cpp b/test-app/runtime/src/main/cpp/runtime/Runtime.cpp index 8243b9a8..555ba92e 100644 --- a/test-app/runtime/src/main/cpp/runtime/Runtime.cpp +++ b/test-app/runtime/src/main/cpp/runtime/Runtime.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include "zipconf.h" #include "NativeScriptException.h" @@ -26,9 +28,6 @@ #include "ManualInstrumentation.h" #include "GlobalHelpers.h" #include "Timers.h" -#ifdef __JSC__ -#include "WeakRef.h" -#endif #ifdef APPLICATION_IN_DEBUG // #include "NetworkDomainCallbackHandlers.h" @@ -36,10 +35,66 @@ #endif #include "NSRuntimeModules.h" +#include "LooperTasks.h" using namespace tns; using namespace std; +namespace { + // std::terminate handler: log an uncaught native exception (with its message + // where available) before aborting, so the crash is diagnosable instead of a + // bare abort. + void LogAndAbortUncaught() { + try { + throw; // rethrow the current in-flight exception + } catch (const tns::NativeScriptException &e) { + __android_log_print(ANDROID_LOG_FATAL, "TNS.Native", + "Uncaught NativeScriptException: %s", e.what()); + } catch (const std::exception &e) { + __android_log_print(ANDROID_LOG_FATAL, "TNS.Native", + "Uncaught std::exception: %s", e.what()); + } catch (...) { + __android_log_print(ANDROID_LOG_FATAL, "TNS.Native", + "Uncaught unknown native exception"); + } + + // Preserve default abort behavior so crashes are visible to tooling. + std::_Exit(EXIT_FAILURE); + } + + // queueMicrotask(callback) per spec: + // https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask + // Implemented via Promise.resolve().then(callback) so it schedules a real + // microtask on every engine the napi runtime targets (V8, QuickJS, Hermes, + // JSC). This preserves ordering with Promise microtasks and runs before timers. + napi_value QueueMicrotaskCallback(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value argv[1]; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + + napi_valuetype type = napi_undefined; + if (argc >= 1) { + napi_typeof(env, argv[0], &type); + } + if (argc < 1 || type != napi_function) { + napi_throw_type_error(env, nullptr, + "queueMicrotask: callback must be a function"); + return nullptr; + } + + napi_value global, promiseCtor, resolveFn, resolved, thenFn; + napi_get_global(env, &global); + napi_get_named_property(env, global, "Promise", &promiseCtor); + napi_get_named_property(env, promiseCtor, "resolve", &resolveFn); + napi_call_function(env, promiseCtor, resolveFn, 0, nullptr, &resolved); + napi_get_named_property(env, resolved, "then", &thenFn); + napi_value thenArgs[1] = {argv[0]}; + napi_call_function(env, resolved, thenFn, 1, thenArgs, nullptr); + + return nullptr; + } +} + bool tns::LogEnabled = false; void Runtime::Init(JavaVM *vm) { @@ -61,6 +116,9 @@ void Runtime::Init(JavaVM *vm) { sigaction(SIGABRT, &action, NULL); sigaction(SIGSEGV, &action, NULL); } + + // Log uncaught native exceptions before aborting. + std::set_terminate(LogAndAbortUncaught); } /** * Returns the runtime based on the current thread id @@ -174,9 +232,8 @@ void Runtime::Init(JNIEnv *_env, jstring filesPath, jstring nativeLibsDir, napi_value global; napi_get_global(env, &global); -#ifdef __JSC__ - tns::WeakRef::Init(env); -#endif + // Newer JSC ships a native `WeakRef` global, so the old polyfill (which was + // actually a strong reference and leaked) is no longer needed. #ifdef APPLICATION_IN_DEBUG Console::createConsole(env, JsV8InspectorClient::consoleLogCallback, maxLogcatObjectSize, forceLog); @@ -238,10 +295,7 @@ void Runtime::Init(JNIEnv *_env, jstring filesPath, jstring nativeLibsDir, m_objectManager->Init(env); m_module.Init(env, ArgConverter::jstringToString(callingDir)); - /* - * Attach `Worker` object constructor only to the main thread (isolate)'s global object - * Workers should not be created from within other Workers, for now - */ + if (!s_mainThreadInitialized) { m_isMainThread = true; @@ -268,23 +322,11 @@ void Runtime::Init(JNIEnv *_env, jstring filesPath, jstring nativeLibsDir, ALooper_addFd(m_mainLooper, m_mainLooper_fd[0], ALOOPER_POLL_CALLBACK, ALOOPER_EVENT_INPUT, CallbackHandlers::RunOnMainThreadFdCallback, nullptr); - - napi_value worker; - napi_define_class(env, "Worker", strlen("Worker"), CallbackHandlers::NewThreadCallback, - nullptr, 0, nullptr, &worker); - napi_value prototype = napi_util::get_prototype(env, worker); - napi_util::napi_set_function(env, prototype, "postMessage", - CallbackHandlers::WorkerObjectPostMessageCallback, nullptr); - napi_util::napi_set_function(env, prototype, "terminate", - CallbackHandlers::WorkerObjectTerminateCallback, nullptr); - napi_util::napi_set_function(env, prototype, "close", - CallbackHandlers::WorkerGlobalCloseCallback, nullptr); - - napi_set_named_property(env, global, "Worker", worker); } /* * Emulate a `WorkerGlobalScope` - * Attach 'postMessage', 'close' to the global object + * Attach 'postMessage', 'close' to the global object of every non-main + * (worker) env. */ else { m_isMainThread = false; @@ -297,6 +339,22 @@ void Runtime::Init(JNIEnv *_env, jstring filesPath, jstring nativeLibsDir, napi_util::define_property(env, global, "__ns__worker", napi_util::get_true(env)); } + /* + * Attach the `Worker` object constructor to EVERY env's global object so + * that nested workers (a worker spawning its own workers) are supported. + */ + { + napi_value worker; + napi_define_class(env, "Worker", strlen("Worker"), CallbackHandlers::NewThreadCallback, + nullptr, 0, nullptr, &worker); + napi_value prototype = napi_util::get_prototype(env, worker); + napi_util::napi_set_function(env, prototype, "postMessage", + CallbackHandlers::WorkerObjectPostMessageCallback, nullptr); + napi_util::napi_set_function(env, prototype, "terminate", + CallbackHandlers::WorkerObjectTerminateCallback, nullptr); + napi_set_named_property(env, global, "Worker", worker); + } + napi_util::define_property(env, global, "global", nullptr, GlobalAccessorCallback); if (!s_mainThreadInitialized) { @@ -312,10 +370,19 @@ void Runtime::Init(JNIEnv *_env, jstring filesPath, jstring nativeLibsDir, Performance::createPerformance(env, global); + napi_util::napi_set_function(env, global, "queueMicrotask", QueueMicrotaskCallback); + m_arrayBufferHelper.CreateConvertFunctions(env, global, m_objectManager); m_loopTimer->Init(env); + // Per-runtime task queue bound to this thread's looper. Child workers post + // their outbound messages/errors/cleanup onto their parent runtime's queue. + // Looper.prepare() has already run for worker threads (initWorkerRuntime), + // so ALooper_forThread() returns the looper that runWorkerLoop() will pump. + m_looperTasks = std::make_shared(); + m_looperTasks->Initialize(ALooper_forThread()); + s_mainThreadInitialized = true; napi_close_handle_scope(env, handleScope); @@ -377,6 +444,9 @@ std::string Runtime::ReadFileText(const std::string &filePath) { void Runtime::DestroyRuntime() { is_destroying = true; + if (m_looperTasks != nullptr) { + m_looperTasks->Terminate(); + } MetadataNode::onDisposeEnv(env); ArgConverter::onDisposeEnv(env); tns::GlobalHelpers::onDisposeEnv(env); @@ -458,11 +528,21 @@ void Runtime::RunModule(const char *moduleName) { m_module.Load(env, moduleName); } -void Runtime::RunWorker(jstring scriptFile) { - string filePath = ArgConverter::jstringToString(scriptFile); +void Runtime::RunWorker(const std::string &filePath) { m_module.LoadWorker(env, filePath); } +void Runtime::DisposeWorkerRuntime(Runtime *runtime) { + // `env` is referenced by the (engine-specific) JSEnterScope macro below. + napi_env env = runtime->env; + { + JSEnterScope + runtime->DestroyRuntime(); + } + // ~Runtime frees the underlying engine runtime (js_free_runtime under V8). + delete runtime; +} + jobject Runtime::RunScript(JNIEnv *_env, jobject obj, jstring scriptFile) { int status; auto filename = ArgConverter::jstringToString(scriptFile); @@ -498,7 +578,7 @@ napi_env Runtime::GetNapiEnv() { return env; } -napi_runtime Runtime::GetNapiRuntime() { +jsr_ns_runtime Runtime::GetNapiRuntime() { return rt; } @@ -568,7 +648,8 @@ Runtime::CreateJSInstanceNative(JNIEnv *_jEnv, jobject obj, jobject javaObject, DEBUG_WRITE("createJSInstanceNative class %s", proxyClassName.c_str()); - jsInstance = MetadataNode::CreateExtendedJSWrapper(env, m_objectManager, proxyClassName, javaObjectID); + MetadataNode *extNode = nullptr; + jsInstance = MetadataNode::CreateExtendedJSWrapper(env, m_objectManager, proxyClassName, javaObjectID, &extNode); if (napi_util::is_null_or_undefined(env, jsInstance)) { throw NativeScriptException( @@ -585,7 +666,7 @@ Runtime::CreateJSInstanceNative(JNIEnv *_jEnv, jobject obj, jobject javaObject, DEBUG_WRITE("createJSInstanceNative: implementationObject"); - m_objectManager->Link(jsInstance, javaObjectID, nullptr); + m_objectManager->Link(jsInstance, javaObjectID, nullptr, extNode); } jint Runtime::GenerateNewObjectId(JNIEnv *jEnv, jobject obj) { diff --git a/test-app/runtime/src/main/cpp/runtime/Runtime.h b/test-app/runtime/src/main/cpp/runtime/Runtime.h index 32823ed2..e1fd7f76 100644 --- a/test-app/runtime/src/main/cpp/runtime/Runtime.h +++ b/test-app/runtime/src/main/cpp/runtime/Runtime.h @@ -3,6 +3,7 @@ #include "jni.h" #include +#include #include "JniLocalRef.h" #include "MessageLoopTimer.h" #include @@ -22,6 +23,7 @@ namespace tns { class JSMethodCache; + class LooperTasks; class Runtime { public: @@ -62,7 +64,11 @@ namespace tns { void RunModule(const char *moduleName); - void RunWorker(jstring scriptFile); + void RunWorker(const std::string &filePath); + + // Tears down a worker's Runtime (engine scope + env free) and deletes + // it. Called from the native worker thread during shutdown. + static void DisposeWorkerRuntime(Runtime *runtime); jobject RunScript(JNIEnv *_env, jobject obj, jstring scriptFile); @@ -86,12 +92,20 @@ namespace tns { napi_env GetNapiEnv(); - napi_runtime GetNapiRuntime(); + jsr_ns_runtime GetNapiRuntime(); static ALooper *GetMainLooper() { return m_mainLooper; } + static JavaVM *GetJVM() { + return java_vm; + } + + std::shared_ptr GetLooperTasks() { + return m_looperTasks; + } + void Lock(); void Unlock(); @@ -148,7 +162,7 @@ namespace tns { int m_id; jobject m_runtime; - napi_runtime rt; + jsr_ns_runtime rt; napi_env env; napi_handle_scope global_scope; @@ -166,6 +180,8 @@ namespace tns { ModuleInternal m_module; + std::shared_ptr m_looperTasks; + static int GetAndroidVersion(); static int m_androidVersion; diff --git a/test-app/runtime/src/main/cpp/runtime/callbackhandlers/CallbackHandlers.cpp b/test-app/runtime/src/main/cpp/runtime/callbackhandlers/CallbackHandlers.cpp index ac74a491..15efd081 100644 --- a/test-app/runtime/src/main/cpp/runtime/callbackhandlers/CallbackHandlers.cpp +++ b/test-app/runtime/src/main/cpp/runtime/callbackhandlers/CallbackHandlers.cpp @@ -19,6 +19,7 @@ #include "ArgConverter.h" #include "JsArgConverter.h" #include "GlobalHelpers.h" +#include "WorkerWrapper.h" #include #ifdef USE_MIMALLOC @@ -62,28 +63,6 @@ void CallbackHandlers::Init(napi_env env) { "()V"); assert(ENABLE_VERBOSE_LOGGING_METHOD_ID != nullptr); - INIT_WORKER_METHOD_ID = jEnv.GetStaticMethodID(RUNTIME_CLASS, "initWorker", - "(Ljava/lang/String;Ljava/lang/String;I)V"); - - assert(INIT_WORKER_METHOD_ID != nullptr); - - SEND_MESSAGE_TO_WORKER_METHOD_ID = jEnv.GetStaticMethodID(RUNTIME_CLASS, - "sendMessageFromMainToWorker", - "(ILjava/lang/String;)V"); - assert(SEND_MESSAGE_TO_WORKER_METHOD_ID != nullptr); - - SEND_MESSAGE_TO_MAIN_METHOD_ID = jEnv.GetStaticMethodID(RUNTIME_CLASS, - "sendMessageFromWorkerToMain", - "(Ljava/lang/String;)V"); - assert(SEND_MESSAGE_TO_MAIN_METHOD_ID != nullptr); - - TERMINATE_WORKER_METHOD_ID = jEnv.GetStaticMethodID(RUNTIME_CLASS, "workerObjectTerminate", - "(I)V"); - assert(TERMINATE_WORKER_METHOD_ID != nullptr); - - WORKER_SCOPE_CLOSE_METHOD_ID = jEnv.GetStaticMethodID(RUNTIME_CLASS, "workerScopeClose", "()V"); - assert(WORKER_SCOPE_CLOSE_METHOD_ID != nullptr); - MetadataNode::Init(env); MethodCache::Init(); @@ -91,7 +70,8 @@ void CallbackHandlers::Init(napi_env env) { napi_value CallbackHandlers::CallJavaMethod(napi_env env, napi_value caller, const string &className, const string &methodName, MetadataEntry *entry, - bool isFromInterface, bool isStatic, napi_callback_info info, size_t argc, napi_value* argv) { + bool isFromInterface, bool isStatic, napi_callback_info info, size_t argc, napi_value* argv, + ObjectManager *objectManager) { JEnv jEnv; jclass clazz; @@ -213,9 +193,16 @@ napi_value CallbackHandlers::CallJavaMethod(napi_env env, napi_value caller, con DEBUG_WRITE("CallJavaMethod on class %s", methodName.c_str()); } + // The caller (MethodCallback) passes a cached ObjectManager*; only fall back + // to the locked env->runtime map lookup when invoked without one. Resolved + // before the converter so object-arg conversion can reuse it too. + if (objectManager == nullptr) { + objectManager = Runtime::GetRuntime(env)->GetObjectManager(); + } + JsArgConverter argConverter = (entry != nullptr && entry->isExtensionFunction) - ? JsArgConverter(env, caller, argv, argc, *sig, entry) - : JsArgConverter(env, argv, argc, false, *sig, entry); + ? JsArgConverter(env, caller, argv, argc, *sig, entry, (JNIEnv *) jEnv, objectManager) + : JsArgConverter(env, argv, argc, false, *sig, entry, (JNIEnv *) jEnv, objectManager); if (!argConverter.IsValid()) { @@ -227,14 +214,10 @@ napi_value CallbackHandlers::CallJavaMethod(napi_env env, napi_value caller, con jvalue *javaArgs = argConverter.ToArgs(); - auto runtime = Runtime::GetRuntime(env); - auto objectManager = runtime->GetObjectManager(); - if (!isStatic) { int objectId = -1; - callerJavaObject = objectManager->GetJavaObjectByJsObject(caller, &objectId); - isSuper = objectManager->GetIsSuper(objectId, caller); + callerJavaObject = objectManager->GetJavaObjectByJsObject(caller, &objectId, &isSuper); if (callerJavaObject.IsNull()) { stringstream ss; @@ -445,7 +428,8 @@ bool CallbackHandlers::RegisterInstance(napi_env env, napi_value jsObject, napi_value implementationObject, bool isInterface, napi_value *jsThisProxy, - const std::string &baseClassName) { + const std::string &baseClassName, + MetadataNode *node) { bool success; DEBUG_WRITE("RegisterInstance called for '%s'", fullClassName.c_str()); @@ -461,7 +445,7 @@ bool CallbackHandlers::RegisterInstance(napi_env env, napi_value jsObject, int javaObjectID = objectManager->GenerateNewObjectID(); - objectManager->Link(jsObject, javaObjectID, nullptr); + objectManager->Link(jsObject, javaObjectID, nullptr, node); // resolve constructor auto mi = MethodCache::ResolveConstructorSignature(env, argWrapper, fullClassName, @@ -508,14 +492,17 @@ bool CallbackHandlers::RegisterInstance(napi_env env, napi_value jsObject, jEnv.CallVoidMethod(runtime->GetJavaRuntime(), MAKE_INSTANCE_STRONG_ID, instance, javaObjectID); - AdjustAmountOfExternalAllocatedMemory(env); + // Reuse the runtime we already resolved instead of re-querying via env. + runtime->AdjustAmountOfExternalAllocatedMemory(); + runtime->TryCallGC(); JniLocalRef localInstance(instance); success = !localInstance.IsNull(); if (success) { - jclass instanceClass = jEnv.FindClass(fullClassName); - objectManager->SetJavaClass(jsObject, instanceClass); + // ResolveClass already cached this exact (global) jclass under + // fullClassName, so reuse it instead of a redundant FindClass lookup. + objectManager->SetJavaClass(jsObject, generatedJavaClass); *jsThisProxy = objectManager->GetOrCreateProxy(javaObjectID, jsObject); } else { DEBUG_WRITE_FORCE("RegisterInstance failed with null new instance class: %s", @@ -571,25 +558,35 @@ string CallbackHandlers::ResolveClassName(napi_env env, jclass &clazz) { } napi_value CallbackHandlers::GetArrayElement(napi_env env, napi_value array, - uint32_t index, const string &arraySignature) { - return arrayElementAccessor.GetArrayElement(env, array, index, arraySignature); + uint32_t index, const string &arraySignature, + ObjectManager *objectManager, jobject arrayObject) { + return arrayElementAccessor.GetArrayElement(env, array, index, arraySignature, + objectManager, arrayObject); } void CallbackHandlers::SetArrayElement(napi_env env, napi_value array, uint32_t index, - const string &arraySignature, napi_value value) { + const string &arraySignature, napi_value value, + ObjectManager *objectManager, jobject arrayObject) { - arrayElementAccessor.SetArrayElement(env, array, index, arraySignature, value); + arrayElementAccessor.SetArrayElement(env, array, index, arraySignature, value, + objectManager, arrayObject); } napi_value CallbackHandlers::GetJavaField(napi_env env, napi_value caller, - FieldCallbackData *fieldData) { - return fieldAccessor.GetJavaField(env, caller, fieldData); + FieldCallbackData *fieldData, + ObjectManager *objectManager, + JniLocalRef targetJavaObject) { + return fieldAccessor.GetJavaField(env, caller, fieldData, objectManager, + std::move(targetJavaObject)); } void CallbackHandlers::SetJavaField(napi_env env, napi_value target, - napi_value value, FieldCallbackData *fieldData) { - fieldAccessor.SetJavaField(env, target, value, fieldData); + napi_value value, FieldCallbackData *fieldData, + ObjectManager *objectManager, + JniLocalRef targetJavaObject) { + fieldAccessor.SetJavaField(env, target, value, fieldData, objectManager, + std::move(targetJavaObject)); } void CallbackHandlers::AdjustAmountOfExternalAllocatedMemory(napi_env env) { @@ -814,7 +811,7 @@ napi_value CallbackHandlers::TimeCallback(napi_env env, napi_callback_info info) napi_value CallbackHandlers::ReleaseNativeCounterpartCallback(napi_env env, napi_callback_info info) { - NAPI_CALLBACK_BEGIN_VARGS(); + NAPI_CALLBACK_BEGIN_VARGS_FAST(8) if (argc != 1) { napi_throw_error(env, "0", "Unexpected arguments count!"); @@ -1263,7 +1260,7 @@ void CallbackHandlers::RemoveEnvEntries(napi_env env) { napi_value CallbackHandlers::NewThreadCallback(napi_env env, napi_callback_info info) { try { - NAPI_CALLBACK_BEGIN_VARGS() + NAPI_CALLBACK_BEGIN_VARGS_FAST(8) napi_value newTarget; napi_get_new_target(env, info, &newTarget); @@ -1327,20 +1324,23 @@ napi_value CallbackHandlers::NewThreadCallback(napi_env env, napi_callback_info // Will throw if path is invalid or doesn't exist ModuleInternal::CheckFileExists(env, workerPath, currentDir); - auto workerId = nextWorkerId++; + // Resolve the JNI handles used by the worker thread bootstrap while we + // are still on the parent (main, for the first worker) thread. + WorkerWrapper::EnsureJniCached(); + + auto workerId = WorkerWrapper::NextWorkerId(); napi_value workerIdValue; napi_create_int32(env, workerId, &workerIdValue); napi_set_named_property(env, jsThis, "workerId", workerIdValue); - id2WorkerMap.emplace(workerId, napi_util::make_ref(env, jsThis)); - DEBUG_WRITE("Called Worker constructor id=%d", workerId); - JEnv jEnv; - JniLocalRef filePath(jEnv.NewStringUTF(workerPath.c_str())); - JniLocalRef dirPath(jEnv.NewStringUTF(currentDir.c_str())); - jEnv.CallStaticVoidMethod(RUNTIME_CLASS, INIT_WORKER_METHOD_ID, (jstring) filePath, - (jstring) dirPath, workerId); + // THREAD_PRIORITY_BACKGROUND (android.os.Process) == 10 + const int kThreadPriorityBackground = 10; + auto wrapper = std::make_shared(env, workerId, workerPath, currentDir, + kThreadPriorityBackground, jsThis); + WorkerWrapper::Insert(workerId, wrapper); + wrapper->Start(); napi_value stack; napi_value error; @@ -1368,7 +1368,7 @@ napi_value CallbackHandlers::NewThreadCallback(napi_env env, napi_callback_info napi_value CallbackHandlers::WorkerObjectPostMessageCallback(napi_env env, napi_callback_info info) { - NAPI_CALLBACK_BEGIN_VARGS(); + NAPI_CALLBACK_BEGIN_VARGS_FAST(2) try { if (argc != 1) { @@ -1389,18 +1389,16 @@ CallbackHandlers::WorkerObjectPostMessageCallback(napi_env env, napi_callback_in std::string msg = tns::JsonStringifyObject(env, argv[0], false); - // get worker's ID that is associated on the other side - in Java + // get worker's ID that is associated with this Worker object napi_value jsId; napi_get_named_property(env, jsThis, "workerId", &jsId); auto id = napi_util::get_int32(env, jsId); - JEnv jEnv; - - jstring jmsg = jEnv.NewStringUTF(msg.c_str()); - JniLocalRef jmsgRef(jmsg); - - jEnv.CallStaticVoidMethod(RUNTIME_CLASS, SEND_MESSAGE_TO_WORKER_METHOD_ID, id, - (jstring) jmsgRef); + auto wrapper = WorkerWrapper::GetById(id); + if (wrapper != nullptr) { + wrapper->PostMessage(std::make_shared( + worker::Message::MakeData(std::move(msg)))); + } DEBUG_WRITE( "MAIN: WorkerObjectPostMessageCallback called postMessage on Worker object(id=%d)", @@ -1419,54 +1417,6 @@ CallbackHandlers::WorkerObjectPostMessageCallback(napi_env env, napi_callback_in return nullptr; } -void CallbackHandlers::WorkerGlobalOnMessageCallback(napi_env env, jstring message) { - NapiScope scope(env); - try { - napi_value globalObject; - napi_get_global(env, &globalObject); - - napi_value callback; - napi_get_named_property(env, globalObject, "onmessage", &callback); - - if (napi_util::is_of_type(env, callback, napi_function)) { - std::string msgString = ArgConverter::jstringToString(message); - napi_value dataObject = tns::JsonParseString(env, msgString.c_str()); - - napi_value obj; - napi_create_object(env, &obj); - if (napi_util::is_of_type(env, dataObject, napi_object)) { - napi_set_named_property(env, obj, "data", dataObject); - } - - napi_value args[1] = { - obj - }; - - napi_value result; - napi_status status = napi_call_function(env, globalObject, callback, 1, args, &result); - if (status == napi_pending_exception) { - napi_value error; - napi_get_and_clear_last_exception(env, &error); - CallWorkerScopeOnErrorHandle(env, error); - } - } else { - DEBUG_WRITE( - "WORKER: WorkerGlobalOnMessageCallback couldn't fire a worker's `onmessage` callback because it isn't implemented!"); - } - } catch (NativeScriptException &ex) { - ex.ReThrowToNapi(env); - } catch (std::exception e) { - std::stringstream ss; - ss << "Error: c++ exception: " << e.what() << std::endl; - NativeScriptException nsEx(ss.str()); - nsEx.ReThrowToNapi(env); - } catch (...) { - NativeScriptException nsEx(std::string("Error: c++ exception!")); - nsEx.ReThrowToNapi(env); - } -} - - napi_value CallbackHandlers::WorkerGlobalPostMessageCallback(napi_env env, napi_callback_info info) { NAPI_CALLBACK_BEGIN(1) @@ -1489,11 +1439,11 @@ CallbackHandlers::WorkerGlobalPostMessageCallback(napi_env env, napi_callback_in napi_value objToStringify = argv[0]; std::string msg = tns::JsonStringifyObject(env, objToStringify, false); - JEnv jenv; - auto jmsg = jenv.NewStringUTF(msg.c_str()); - JniLocalRef jmsgRef(jmsg); - - jenv.CallStaticVoidMethod(RUNTIME_CLASS, SEND_MESSAGE_TO_MAIN_METHOD_ID, (jstring) jmsgRef); + auto wrapper = WorkerWrapper::FromEnv(env); + if (wrapper != nullptr) { + wrapper->PostMessageToParent(std::make_shared( + worker::Message::MakeData(std::move(msg)))); + } DEBUG_WRITE("WORKER: WorkerGlobalPostMessageCallback called."); } catch (NativeScriptException &ex) { @@ -1511,64 +1461,6 @@ CallbackHandlers::WorkerGlobalPostMessageCallback(napi_env env, napi_callback_in return nullptr; } -void CallbackHandlers::WorkerObjectOnMessageCallback(napi_env env, jint workerId, jstring message) { - NapiScope scope(env); - try { - - auto workerFound = CallbackHandlers::id2WorkerMap.find(workerId); - - if (workerFound == CallbackHandlers::id2WorkerMap.end()) { - DEBUG_WRITE( - "MAIN: WorkerObjectOnMessageCallback no worker instance was found with workerId=%d.", - workerId); - return; - } - - napi_ref workerPersistent = workerFound->second; - - napi_value worker; - napi_get_reference_value(env, workerPersistent, &worker); - - napi_value global; - napi_get_global(env, &global); - - napi_value callback; - napi_get_named_property(env, worker, "onmessage", &callback); - - if (napi_util::is_of_type(env, callback, napi_function)) { - std::string msgString = ArgConverter::jstringToString(message); - - napi_value dataObject = tns::JsonParseString(env, msgString.c_str()); - - napi_value obj; - napi_create_object(env, &obj); - napi_set_named_property(env, obj, "data", dataObject); - - napi_value args[1] = {obj}; - - napi_value result; - napi_status status = napi_call_function(env, worker, callback, 1, args, &result); - if (status != napi_ok) { - throw NativeScriptException("Error calling onmessage callback"); - } - } else { - DEBUG_WRITE( - "MAIN: WorkerObjectOnMessageCallback couldn't fire a worker(id=%d) object's `onmessage` callback because it isn't implemented.", - workerId); - } - } catch (NativeScriptException &ex) { - ex.ReThrowToNapi(env); - } catch (std::exception e) { - std::stringstream ss; - ss << "Error: c++ exception: " << e.what() << std::endl; - NativeScriptException nsEx(ss.str()); - nsEx.ReThrowToNapi(env); - } catch (...) { - NativeScriptException nsEx(std::string("Error: c++ exception!")); - nsEx.ReThrowToNapi(env); - } -} - napi_value CallbackHandlers::WorkerObjectTerminateCallback(napi_env env, napi_callback_info info) { size_t argc = 0; napi_value thiz; @@ -1600,10 +1492,10 @@ napi_value CallbackHandlers::WorkerObjectTerminateCallback(napi_env env, napi_ca napi_get_boolean(env, true, &trueValue); napi_set_named_property(env, thiz, "isTerminated", trueValue); - JEnv jenv; - jenv.CallStaticVoidMethod(RUNTIME_CLASS, TERMINATE_WORKER_METHOD_ID, id); - - CallbackHandlers::ClearWorkerPersistent(env, id); + auto wrapper = WorkerWrapper::GetById(id); + if (wrapper != nullptr) { + wrapper->Terminate(); + } } catch (NativeScriptException &ex) { ex.ReThrowToNapi(env); } catch (std::exception e) { @@ -1659,8 +1551,10 @@ napi_value CallbackHandlers::WorkerGlobalCloseCallback(napi_env env, napi_callba CallWorkerScopeOnErrorHandle(env, err); } - JEnv jenv; - jenv.CallStaticVoidMethod(RUNTIME_CLASS, WORKER_SCOPE_CLOSE_METHOD_ID); + auto wrapper = WorkerWrapper::FromEnv(env); + if (wrapper != nullptr) { + wrapper->Close(); + } } catch (NativeScriptException &ex) { ex.ReThrowToNapi(env); } catch (std::exception e) { @@ -1725,12 +1619,14 @@ void CallbackHandlers::CallWorkerScopeOnErrorHandle(napi_env env, napi_value err line = pframes[0].line; filename = pframes[0].filename; } - Runtime::GetRuntime(env)->PassUncaughtExceptionFromWorkerToMainHandler( - pmessage, - pstack, - ArgConverter::convertToJsString(env, filename), - line - ); + auto wrapper = WorkerWrapper::FromEnv(env); + if (wrapper != nullptr) { + wrapper->PassUncaughtExceptionFromWorkerToParent( + ArgConverter::ConvertToString(env, pmessage), + filename, + ArgConverter::ConvertToString(env, pstack), + line); + } } else if (!napi_util::is_null_or_undefined(env, result)) { bool handled; napi_get_value_bool(env, result, &handled); @@ -1746,101 +1642,16 @@ void CallbackHandlers::CallWorkerScopeOnErrorHandle(napi_env env, napi_value err line = frames[0].line; filename = frames[0].filename; } - Runtime::GetRuntime(env)->PassUncaughtExceptionFromWorkerToMainHandler( - message, - stack, - ArgConverter::convertToJsString(env, filename), - line - ); - - - } catch (NativeScriptException &ex) { - ex.ReThrowToNapi(env); - } catch (std::exception e) { - std::stringstream ss; - ss << "Error: c++ exception: " << e.what() << std::endl; - NativeScriptException nsEx(ss.str()); - nsEx.ReThrowToNapi(env); - } catch (...) { - NativeScriptException nsEx(std::string("Error: c++ exception!")); - nsEx.ReThrowToNapi(env); - } -} - -void CallbackHandlers::CallWorkerObjectOnErrorHandle(napi_env env, jint workerId, jstring message, - jstring stackTrace, jstring filename, - jint lineno, jstring threadName) { - NapiScope scope(env); - try { - auto workerFound = CallbackHandlers::id2WorkerMap.find(workerId); - - if (workerFound == CallbackHandlers::id2WorkerMap.end()) { - DEBUG_WRITE( - "MAIN: CallWorkerObjectOnErrorHandle no worker instance was found with workerId=%d.", - workerId); - return; - } - - napi_ref workerPersistent = workerFound->second; - - napi_value worker; - napi_get_reference_value(env, workerPersistent, &worker); - - napi_value callback; - napi_get_named_property(env, worker, "onerror", &callback); - - if (napi_util::is_of_type(env, callback, napi_function)) { - napi_value errEvent; - napi_value msgValue = ArgConverter::jstringToJsString(env, message); - napi_value codeValue; - napi_create_string_utf8(env, "",0, &codeValue); - napi_create_error(env,codeValue, msgValue, &errEvent); - napi_value stack_main_thread; - napi_get_named_property(env, worker, "__stack__", &stack_main_thread); - std::string main_stack = napi_util::get_string_value(env, stack_main_thread); - - std::string curr_stack = ArgConverter::jstringToString(stackTrace); - - std::string full_stack = curr_stack + "\n" + main_stack.substr(main_stack.find_first_of("\n") + 1) ; - - napi_value full_stack_value; - napi_create_string_utf8(env, full_stack.c_str(), full_stack.size(), &full_stack_value); - - napi_set_named_property(env, errEvent, "stack", full_stack_value); - - napi_value args[1] = {errEvent}; - - napi_value result; - napi_status status = napi_call_function(env, worker, callback, 1, args, &result); - if (status != napi_ok) { - napi_value exception; - napi_get_and_clear_last_exception(env, &exception); - if (!napi_util::is_null_or_undefined(env, exception)) { - throw NativeScriptException(env, exception, - "Error calling onerror on Worker Object"); - } else { - throw NativeScriptException("Error calling onerror on Worker Object"); - } - } - - bool handled; - napi_get_value_bool(env, result, &handled); - - if (handled) { - return; - } + auto wrapper = WorkerWrapper::FromEnv(env); + if (wrapper != nullptr) { + wrapper->PassUncaughtExceptionFromWorkerToParent( + ArgConverter::ConvertToString(env, message), + filename, + ArgConverter::ConvertToString(env, stack), + line); } - // Exception wasn't handled, or is critical -> Throw exception - std::string strMessage = ArgConverter::jstringToString(message); - std::string strFilename = ArgConverter::jstringToString(filename); - std::string strThreadname = ArgConverter::jstringToString(threadName); - std::string strStackTrace = ArgConverter::jstringToString(stackTrace); - DEBUG_WRITE( - "Unhandled exception in '%s' thread. file: %s, line %d, message: %s\nStackTrace: %s", - strThreadname.c_str(), strFilename.c_str(), lineno, strMessage.c_str(), - strStackTrace.c_str()); } catch (NativeScriptException &ex) { ex.ReThrowToNapi(env); } catch (std::exception e) { @@ -1854,43 +1665,6 @@ void CallbackHandlers::CallWorkerObjectOnErrorHandle(napi_env env, jint workerId } } -void CallbackHandlers::ClearWorkerPersistent(napi_env env, int workerId) { - NapiScope scope(env); - DEBUG_WRITE("ClearWorkerPersistent called for workerId=%d", workerId); - - auto workerFound = CallbackHandlers::id2WorkerMap.find(workerId); - - if (workerFound == CallbackHandlers::id2WorkerMap.end()) { - DEBUG_WRITE( - "MAIN | WORKER: ClearWorkerPersistent no worker instance was found with workerId=%d ! The worker may already be terminated.", - workerId); - return; - } - - napi_ref workerPersistent = workerFound->second; - napi_delete_reference(env, workerPersistent); - - id2WorkerMap.erase(workerId); -} - -void CallbackHandlers::TerminateWorkerThread(napi_env env) { - JSEnterScope - try { - Runtime::GetRuntime(env)->DestroyRuntime(); - } catch (NativeScriptException &e) { - e.ReThrowToJava(nullptr); - } catch (std::exception e) { - std::stringstream ss; - ss << "Error: c++ exception: " << e.what() << std::endl; - NativeScriptException nsEx(ss.str()); - nsEx.ReThrowToJava(nullptr); - } catch (...) { - NativeScriptException nsEx(std::string("Error: c++ exception!")); - nsEx.ReThrowToJava(nullptr); - } - -} - robin_hood::unordered_map CallbackHandlers::cache_; robin_hood::unordered_map CallbackHandlers::jclass_to_runtimeId_cache; @@ -1899,10 +1673,8 @@ robin_hood::unordered_map C std::atomic_int64_t CallbackHandlers::count_ = {0}; std::atomic_uint64_t CallbackHandlers::frameCallbackCount_ = {0}; -int CallbackHandlers::nextWorkerId = 0; int CallbackHandlers::lastCallId = -1; napi_value CallbackHandlers::lastCallValue = nullptr; -robin_hood::unordered_map CallbackHandlers::id2WorkerMap; short CallbackHandlers::MAX_JAVA_STRING_ARRAY_LENGTH = 100; jclass CallbackHandlers::RUNTIME_CLASS = nullptr; @@ -1913,11 +1685,6 @@ jmethodID CallbackHandlers::MAKE_INSTANCE_STRONG_ID = nullptr; jmethodID CallbackHandlers::GET_TYPE_METADATA = nullptr; jmethodID CallbackHandlers::ENABLE_VERBOSE_LOGGING_METHOD_ID = nullptr; jmethodID CallbackHandlers::DISABLE_VERBOSE_LOGGING_METHOD_ID = nullptr; -jmethodID CallbackHandlers::INIT_WORKER_METHOD_ID = nullptr; -jmethodID CallbackHandlers::SEND_MESSAGE_TO_MAIN_METHOD_ID = nullptr; -jmethodID CallbackHandlers::SEND_MESSAGE_TO_WORKER_METHOD_ID = nullptr; -jmethodID CallbackHandlers::TERMINATE_WORKER_METHOD_ID = nullptr; -jmethodID CallbackHandlers::WORKER_SCOPE_CLOSE_METHOD_ID = nullptr; NumericCasts CallbackHandlers::castFunctions; diff --git a/test-app/runtime/src/main/cpp/runtime/callbackhandlers/CallbackHandlers.h b/test-app/runtime/src/main/cpp/runtime/callbackhandlers/CallbackHandlers.h index 4d7e4d1d..39f4f5c0 100644 --- a/test-app/runtime/src/main/cpp/runtime/callbackhandlers/CallbackHandlers.h +++ b/test-app/runtime/src/main/cpp/runtime/callbackhandlers/CallbackHandlers.h @@ -22,14 +22,6 @@ namespace tns { class CallbackHandlers { public: - /* - * Stores persistent handles of all 'Worker' objects initialized on the main thread - * Note: No isolates different than that of the main thread should access this map - */ - static robin_hood::unordered_map id2WorkerMap; - - static int nextWorkerId; - static void Init(napi_env env); static napi_value @@ -41,7 +33,8 @@ namespace tns { napi_value implementationObject, bool isInterface, napi_value *jsThisProxy, - const std::string &baseClassName = std::string()); + const std::string &baseClassName = std::string(), + MetadataNode *node = nullptr); static jclass ResolveClass(napi_env env, const std::string &baseClassName, const std::string &fullClassName, @@ -52,28 +45,34 @@ namespace tns { static napi_value GetArrayElement(napi_env env, napi_value array, uint32_t index, - const std::string &arraySignature); + const std::string &arraySignature, + ObjectManager *objectManager = nullptr, jobject arrayObject = nullptr); static void SetArrayElement(napi_env env, napi_value array, uint32_t index, - const std::string &arraySignature, napi_value value); + const std::string &arraySignature, napi_value value, + ObjectManager *objectManager = nullptr, jobject arrayObject = nullptr); static int GetArrayLength(napi_env env, napi_value arr); static napi_value CallJavaMethod(napi_env env, napi_value caller, const std::string &className, const std::string &methodName, MetadataEntry *entry, bool isFromInterface, - bool isStatic, napi_callback_info info, size_t argc, napi_value* argv); + bool isStatic, napi_callback_info info, size_t argc, napi_value* argv, + ObjectManager *objectManager = nullptr); static napi_value CallJSMethod(napi_env env, JNIEnv *jEnv, napi_value jsObject,jclass claz, const std::string &methodName,int javaObjectId, jobjectArray args); static napi_value GetJavaField(napi_env env, napi_value caller, - FieldCallbackData *fieldData); + FieldCallbackData *fieldData, ObjectManager *objectManager = nullptr, + JniLocalRef targetJavaObject = JniLocalRef()); static void SetJavaField(napi_env env, napi_value target, - napi_value value, FieldCallbackData *fieldData); + napi_value value, FieldCallbackData *fieldData, + ObjectManager *objectManager = nullptr, + JniLocalRef targetJavaObject = JniLocalRef()); static napi_value RunOnMainThreadCallback(napi_env env, napi_callback_info info); @@ -130,13 +129,6 @@ namespace tns { */ static napi_value WorkerObjectPostMessageCallback(napi_env env, napi_callback_info info); - /* - * main -> worker messaging - * Fired when worker object has "postMessage" and the worker has implemented "onMessage" handler - * In case "onMessage" handler isn't implemented no exception is thrown - */ - static void WorkerGlobalOnMessageCallback(napi_env env, jstring message); - /* * worker -> main thread messaging * Fired when a Worker script's "postMessage" is called @@ -144,14 +136,8 @@ namespace tns { static napi_value WorkerGlobalPostMessageCallback(napi_env env, napi_callback_info info); /* - * worker -> main messaging - * Fired when worker has sent a message to main and the worker object has implemented "onMessage" handler - * In case "onMessage" handler isn't implemented no exception is thrown - */ - static void WorkerObjectOnMessageCallback(napi_env env, jint workerId, jstring message); - - /* - * Fired when a Worker instance's terminate is called (immediately stops execution of the thread) + * Fired when a Worker instance's terminate is called (cooperatively + * stops the worker thread's looper) */ static napi_value WorkerObjectTerminateCallback(napi_env env, napi_callback_info info); @@ -160,34 +146,14 @@ namespace tns { */ static napi_value WorkerGlobalCloseCallback(napi_env env, napi_callback_info info); - /* - * Clears the persistent Worker object handle associated with a workerId - * Occurs when calling a worker object's `terminate` or a worker thread's global scope `close` - */ - static void ClearWorkerPersistent(napi_env env, int workerId); - - /* - * Terminates the currently executing Isolate. No scripts can be executed after this call - */ - static void TerminateWorkerThread(napi_env env); - /* * Is called when an unhandled exception is thrown inside the worker * Will execute 'onerror' if one is provided inside the Worker Scope - * Will make the exception "bubble up" through to main, to be handled by the Worker Object + * Will make the exception "bubble up" through to the parent, to be handled by the Worker Object * if 'onerror' isn't implemented or returns false */ static void CallWorkerScopeOnErrorHandle(napi_env env, napi_value tc); - /* - * Is called when an unhandled exception bubbles up from the worker scope to the main thread Worker Object - * Will execute `onerror` if one is implemented for the Worker Object instance - * Will throw a NativeScript Exception if 'onerror' isn't implemented or returns false - */ - static void CallWorkerObjectOnErrorHandle(napi_env env, jint workerId, jstring message, - jstring stackTrace, jstring filename, jint lineno, - jstring threadName); - static napi_value PostFrameCallback(napi_env env, napi_callback_info info); static napi_value RemoveFrameCallback(napi_env env, napi_callback_info info); @@ -254,13 +220,6 @@ namespace tns { static jmethodID DISABLE_VERBOSE_LOGGING_METHOD_ID; - static jmethodID INIT_WORKER_METHOD_ID; - - static jmethodID SEND_MESSAGE_TO_WORKER_METHOD_ID; - static jmethodID SEND_MESSAGE_TO_MAIN_METHOD_ID; - static jmethodID TERMINATE_WORKER_METHOD_ID; - static jmethodID WORKER_SCOPE_CLOSE_METHOD_ID; - static NumericCasts castFunctions; static ArrayElementAccessor arrayElementAccessor; diff --git a/test-app/runtime/src/main/cpp/runtime/com_tns_Runtime.cpp b/test-app/runtime/src/main/cpp/runtime/com_tns_Runtime.cpp index 7cd8a6be..0015caf7 100644 --- a/test-app/runtime/src/main/cpp/runtime/com_tns_Runtime.cpp +++ b/test-app/runtime/src/main/cpp/runtime/com_tns_Runtime.cpp @@ -2,6 +2,7 @@ #include "NativeScriptException.h" #include "CallbackHandlers.h" #include +#include #ifdef __HERMES__ #include @@ -10,6 +11,52 @@ using namespace std; using namespace tns; +// Forward declarations for the natives that must be explicitly registered via +// RegisterNatives. Dynamic JNI lookup of @CriticalNative / @FastNative methods +// is unimplemented on Android 8-10 and buggy on Android 11, so for those +// versions the Java side dispatches to the auto-bound *Legacy variants instead. +// On Android 12+ (and 8+ via RegisterNatives) the optimized variants are used. +static jint generateNewObjectIdCritical_impl(jint runtimeId); +static jboolean notifyGcFast_impl(JNIEnv* env, jobject obj, jint runtimeId, jintArray object_ids); +static jint getCurrentRuntimeIdCritical_impl(); +static jint getPointerSizeCritical_impl(); +static void setManualInstrumentationModeFast_impl(JNIEnv* env, jclass clazz, jstring mode); + +static void RegisterOptimizedNatives(JNIEnv* env) { + jclass cls = env->FindClass("com/tns/Runtime"); + if (cls == nullptr) { + __android_log_print(ANDROID_LOG_ERROR, "TNS.Native", + "Failed to find com/tns/Runtime for RegisterNatives"); + return; + } + + // @CriticalNative: signatures must omit JNIEnv* / jclass. + static const JNINativeMethod criticalMethods[] = { + {const_cast("generateNewObjectIdCritical"), const_cast("(I)I"), reinterpret_cast(generateNewObjectIdCritical_impl)}, + {const_cast("getCurrentRuntimeIdCritical"), const_cast("()I"), reinterpret_cast(getCurrentRuntimeIdCritical_impl)}, + {const_cast("getPointerSizeCritical"), const_cast("()I"), reinterpret_cast(getPointerSizeCritical_impl)}, + }; + // @FastNative: standard JNI ABI (JNIEnv*, jobject/jclass, ...). + static const JNINativeMethod fastMethods[] = { + {const_cast("notifyGcFast"), const_cast("(I[I)Z"), reinterpret_cast(notifyGcFast_impl)}, + {const_cast("setManualInstrumentationModeFast"), const_cast("(Ljava/lang/String;)V"), reinterpret_cast(setManualInstrumentationModeFast_impl)}, + }; + + if (env->RegisterNatives(cls, criticalMethods, + sizeof(criticalMethods) / sizeof(criticalMethods[0])) < 0) { + __android_log_print(ANDROID_LOG_ERROR, "TNS.Native", + "RegisterNatives failed for @CriticalNative methods"); + env->ExceptionClear(); + } + if (env->RegisterNatives(cls, fastMethods, + sizeof(fastMethods) / sizeof(fastMethods[0])) < 0) { + __android_log_print(ANDROID_LOG_ERROR, "TNS.Native", + "RegisterNatives failed for @FastNative methods"); + env->ExceptionClear(); + } + env->DeleteLocalRef(cls); +} + JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { try { #ifdef __HERMES__ @@ -18,6 +65,11 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { }); #endif Runtime::Init(vm); + + JNIEnv* env = nullptr; + if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) == JNI_OK && env != nullptr) { + RegisterOptimizedNatives(env); + } } catch (NativeScriptException& e) { e.ReThrowToJava(nullptr); } catch (std::exception e) { @@ -34,7 +86,8 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { -extern "C" JNIEXPORT void Java_com_tns_Runtime_SetManualInstrumentationMode(JNIEnv* _env, jclass obj, jstring mode) { +// @FastNative ABI: standard JNI signature (registered via RegisterNatives). +static void setManualInstrumentationModeFast_impl(JNIEnv* env, jclass clazz, jstring mode) { try { Runtime::SetManualInstrumentationMode(mode); } catch (...) { @@ -43,6 +96,12 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_SetManualInstrumentationMode(JNIE } } +// Auto-bound legacy variant for Android < 8.0 / where dynamic lookup of the +// annotated method is unavailable. +extern "C" JNIEXPORT void Java_com_tns_Runtime_setManualInstrumentationModeLegacy(JNIEnv* _env, jclass clazz, jstring mode) { + setManualInstrumentationModeFast_impl(_env, clazz, mode); +} + extern "C" JNIEXPORT void Java_com_tns_Runtime_initNativeScript(JNIEnv* _env, jobject obj, jint runtimeId, jstring filesPath, jstring nativeLibDir, jboolean verboseLoggingEnabled, jboolean isDebuggable, jstring packageName, jobjectArray args, jstring callingDir, jint maxLogcatObjectSize, jboolean forceLog) { try { DEBUG_WRITE("NativeScript Initializing!"); @@ -102,29 +161,6 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_runModule(JNIEnv* _env, jobject o } } -extern "C" JNIEXPORT void Java_com_tns_Runtime_runWorker(JNIEnv* _env, jobject obj, jint runtimeId, jstring scriptFile) { - auto runtime = TryGetRuntime(runtimeId); - if (runtime == nullptr) { - return; - } - - NapiScope scope(runtime->GetNapiEnv()); - - try { - runtime->RunWorker(scriptFile); - } catch (NativeScriptException& e) { - e.ReThrowToJava(runtime->GetNapiEnv()); - } catch (std::exception e) { - stringstream ss; - ss << "Error: c++ exception: " << e.what() << endl; - NativeScriptException nsEx(ss.str()); - nsEx.ReThrowToJava(runtime->GetNapiEnv()); - } catch (...) { - NativeScriptException nsEx(std::string("Error: c++ exception!")); - nsEx.ReThrowToJava(runtime->GetNapiEnv()); - } -} - extern "C" JNIEXPORT jobject Java_com_tns_Runtime_runScript(JNIEnv* _env, jobject obj, jint runtimeId, jstring scriptFile) { jobject result = nullptr; @@ -196,13 +232,15 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_createJSInstanceNative(JNIEnv* _e } -extern "C" JNIEXPORT jint Java_com_tns_Runtime_generateNewObjectId(JNIEnv* env, jobject obj, jint runtimeId) { +// @CriticalNative ABI: no JNIEnv* / jclass. GenerateNewObjectId ignores its +// env/obj args (it just increments a counter), so this is safe with nullptrs. +static jint generateNewObjectIdCritical_impl(jint runtimeId) { auto runtime = TryGetRuntime(runtimeId); if (runtime == nullptr) { return 0; } try { - return runtime->GenerateNewObjectId(env, obj); + return runtime->GenerateNewObjectId(nullptr, nullptr); } catch (NativeScriptException& e) { e.ReThrowToJava( runtime->GetNapiEnv()); } catch (std::exception e) { @@ -218,7 +256,12 @@ extern "C" JNIEXPORT jint Java_com_tns_Runtime_generateNewObjectId(JNIEnv* env, return 0; } -extern "C" JNIEXPORT jboolean Java_com_tns_Runtime_notifyGc(JNIEnv* jEnv, jobject obj, jint runtimeId, jintArray object_ids) { +extern "C" JNIEXPORT jint Java_com_tns_Runtime_generateNewObjectIdLegacy(JNIEnv* env, jclass clazz, jint runtimeId) { + return generateNewObjectIdCritical_impl(runtimeId); +} + +// @FastNative ABI: standard JNI signature (registered via RegisterNatives). +static jboolean notifyGcFast_impl(JNIEnv* jEnv, jobject obj, jint runtimeId, jintArray object_ids) { auto runtime = TryGetRuntime(runtimeId); if (runtime == nullptr) { return JNI_FALSE; @@ -229,6 +272,10 @@ extern "C" JNIEXPORT jboolean Java_com_tns_Runtime_notifyGc(JNIEnv* jEnv, jobjec return true; } +extern "C" JNIEXPORT jboolean Java_com_tns_Runtime_notifyGcLegacy(JNIEnv* jEnv, jobject obj, jint runtimeId, jintArray object_ids) { + return notifyGcFast_impl(jEnv, obj, runtimeId, object_ids); +} + extern "C" JNIEXPORT void Java_com_tns_Runtime_lock(JNIEnv* env, jobject obj, jint runtimeId) { auto runtime = TryGetRuntime(runtimeId); if (runtime != nullptr) { @@ -265,11 +312,18 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_passExceptionToJsNative(JNIEnv* j } -extern "C" JNIEXPORT jint Java_com_tns_Runtime_getPointerSize(JNIEnv* env, jclass obj) { +// @CriticalNative ABI: no JNIEnv* / jclass. +static jint getPointerSizeCritical_impl() { return sizeof(void*); } -extern "C" JNIEXPORT jint Java_com_tns_Runtime_getCurrentRuntimeId(JNIEnv* _env, jclass obj) { +extern "C" JNIEXPORT jint Java_com_tns_Runtime_getPointerSizeLegacy(JNIEnv* env, jclass clazz) { + return getPointerSizeCritical_impl(); +} + +// @CriticalNative ABI: no JNIEnv* / jclass. Runtime::Current() is a thread-local +// C++ lookup, so no JNI is used here. +static jint getCurrentRuntimeIdCritical_impl() { auto rt = Runtime::Current(); if (rt == nullptr) { return -1; @@ -277,65 +331,8 @@ extern "C" JNIEXPORT jint Java_com_tns_Runtime_getCurrentRuntimeId(JNIEnv* _env, return rt->GetId(); } -extern "C" JNIEXPORT void Java_com_tns_Runtime_WorkerGlobalOnMessageCallback(JNIEnv* env, jclass obj, jint runtimeId, jstring msg) { - // Worker Thread runtime - auto runtime = TryGetRuntime(runtimeId); - if (runtime == nullptr) { - // TODO: Pete: Log message informing the developer of the failure - DEBUG_WRITE("WorkerGlobalOnMessageCallback: worker runtime not loaded."); - return; - } - - CallbackHandlers::WorkerGlobalOnMessageCallback(runtime->GetNapiEnv(), msg); -} - -extern "C" JNIEXPORT void Java_com_tns_Runtime_WorkerObjectOnMessageCallback(JNIEnv* env, jclass obj, jint runtimeId, jint workerId, jstring msg) { - // Main Thread runtime - auto runtime = TryGetRuntime(runtimeId); - if (runtime == nullptr) { - DEBUG_WRITE("WorkerObjectOnMessageCallback: worker runtime not loaded."); - return; - } - - CallbackHandlers::WorkerObjectOnMessageCallback(runtime->GetNapiEnv(), workerId, msg); -} - -extern "C" JNIEXPORT void Java_com_tns_Runtime_TerminateWorkerCallback(JNIEnv* env, jclass obj, jint runtimeId) { - // Worker Thread runtime - auto runtime = TryGetRuntime(runtimeId); - if (runtime == nullptr) { - DEBUG_WRITE("TerminateWorkerCallback: trying to call terminate before worker is loaded."); - return; - } - auto napiEnv = runtime->GetNapiEnv(); - CallbackHandlers::TerminateWorkerThread(napiEnv); - delete runtime; -} - -extern "C" JNIEXPORT void Java_com_tns_Runtime_ClearWorkerPersistent(JNIEnv* env, jclass obj, jint runtimeId, jint workerId) { - // Worker Thread runtime - auto runtime = TryGetRuntime(runtimeId); - if (runtime == nullptr) { - DEBUG_WRITE("ClearWorkerPersistent: trying to call before worker is loaded."); - return; - } - - CallbackHandlers::ClearWorkerPersistent(runtime->GetNapiEnv(), workerId); -} - -extern "C" JNIEXPORT void Java_com_tns_Runtime_CallWorkerObjectOnErrorHandleMain(JNIEnv* env, jclass obj, jint runtimeId, jint workerId, jstring message, jstring stackTrace, jstring filename, jint lineno, jstring threadName) { - // Main Thread runtime - auto runtime = TryGetRuntime(runtimeId); - if (runtime == nullptr) { - DEBUG_WRITE("CallWorkerObjectOnErrorHandleMain: trying to call before worker is loaded."); - return; - } - - try { - CallbackHandlers::CallWorkerObjectOnErrorHandle(runtime->GetNapiEnv(), workerId, message, stackTrace, filename, lineno, threadName); - } catch (NativeScriptException& e) { - e.ReThrowToJava(runtime->GetNapiEnv()); - } +extern "C" JNIEXPORT jint Java_com_tns_Runtime_getCurrentRuntimeIdLegacy(JNIEnv* _env, jclass clazz) { + return getCurrentRuntimeIdCritical_impl(); } extern "C" JNIEXPORT void Java_com_tns_Runtime_ResetDateTimeConfigurationCache(JNIEnv* _env, jclass obj, jint runtimeId) { diff --git a/test-app/runtime/src/main/cpp/runtime/console/Console.cpp b/test-app/runtime/src/main/cpp/runtime/console/Console.cpp index 6e10c5ec..9e32aafe 100644 --- a/test-app/runtime/src/main/cpp/runtime/console/Console.cpp +++ b/test-app/runtime/src/main/cpp/runtime/console/Console.cpp @@ -130,7 +130,7 @@ std::string buildStringFromArg(napi_env env, napi_value val) { } std::string buildLogString(napi_env env, napi_callback_info info, int startingIndex = 0) { - NAPI_CALLBACK_BEGIN_VARGS() + NAPI_CALLBACK_BEGIN_VARGS_FAST(16) std::stringstream ss; diff --git a/test-app/runtime/src/main/cpp/runtime/conversion/ArrayElementAccessor.cpp b/test-app/runtime/src/main/cpp/runtime/conversion/ArrayElementAccessor.cpp index f7cafee2..35eed0f2 100644 --- a/test-app/runtime/src/main/cpp/runtime/conversion/ArrayElementAccessor.cpp +++ b/test-app/runtime/src/main/cpp/runtime/conversion/ArrayElementAccessor.cpp @@ -8,207 +8,255 @@ using namespace std; using namespace tns; -napi_value ArrayElementAccessor::GetArrayElement(napi_env env, napi_value array, uint32_t index, const string& arraySignature) { +napi_value ArrayElementAccessor::GetArrayElement(napi_env env, napi_value array, uint32_t index, + const string& arraySignature, + ObjectManager* objectManager, jobject arrayObject) { JEnv jenv; - auto runtime = Runtime::GetRuntime(env); - auto objectManager = runtime->GetObjectManager(); - auto arr = objectManager->GetJavaObjectByJsObject(array); + if (objectManager == nullptr) { + objectManager = Runtime::GetRuntime(env)->GetObjectManager(); + } - assertNonNullNativeArray(arr); + // The caller may hand us the already-resolved Java array (single probe per + // loop instead of per element); otherwise resolve it here. + JniLocalRef localArr; + jobject arr; + if (arrayObject != nullptr) { + arr = arrayObject; + } else { + localArr = objectManager->GetJavaObjectByJsObject(array); + assertNonNullNativeArray(localArr); + arr = localArr; + } napi_value value; - jsize startIndex = index; + const jsize startIndex = index; const jsize length = 1; - const string elementSignature = arraySignature.substr(1); - jboolean isCopy = false; - - if (elementSignature == "Z") { - jbooleanArray boolArr = static_cast(arr); - jboolean boolArrValue; - jenv.GetBooleanArrayRegion(boolArr, startIndex, length, &boolArrValue); - value = ConvertToJsValue(env, objectManager, jenv, elementSignature, &boolArrValue); - } else if (elementSignature == "B") { - jbyteArray byteArr = static_cast(arr); - jbyte byteArrValue; - jenv.GetByteArrayRegion(byteArr, startIndex, length, &byteArrValue); - value = ConvertToJsValue(env, objectManager, jenv, elementSignature, &byteArrValue); - } else if (elementSignature == "C") { - jcharArray charArr = static_cast(arr); - jchar charArrValue; - jenv.GetCharArrayRegion(charArr, startIndex, length, &charArrValue); - JniLocalRef s(jenv.NewString(&charArrValue, 1)); - const char* singleChar = jenv.GetStringUTFChars(s, &isCopy); - value = ConvertToJsValue(env, objectManager, jenv, elementSignature, singleChar); - jenv.ReleaseStringUTFChars(s, singleChar); - } else if (elementSignature == "S") { - jshortArray shortArr = static_cast(arr); - jshort shortArrValue; - jenv.GetShortArrayRegion(shortArr, startIndex, length, &shortArrValue); - value = ConvertToJsValue(env, objectManager, jenv, elementSignature, &shortArrValue); - } else if (elementSignature == "I") { - jintArray intArr = static_cast(arr); - jint intArrValue; - jenv.GetIntArrayRegion(intArr, startIndex, length, &intArrValue); - value = ConvertToJsValue(env, objectManager, jenv, elementSignature, &intArrValue); - } else if (elementSignature == "J") { - jlongArray longArr = static_cast(arr); - jlong longArrValue; - jenv.GetLongArrayRegion(longArr, startIndex, length, &longArrValue); - value = ConvertToJsValue(env, objectManager, jenv, elementSignature, &longArrValue); - } else if (elementSignature == "F") { - jfloatArray floatArr = static_cast(arr); - jfloat floatArrValue; - jenv.GetFloatArrayRegion(floatArr, startIndex, length, &floatArrValue); - value = ConvertToJsValue(env, objectManager, jenv, elementSignature, &floatArrValue); - } else if (elementSignature == "D") { - jdoubleArray doubleArr = static_cast(arr); - jdouble doubleArrValue; - jenv.GetDoubleArrayRegion(doubleArr, startIndex, length, &doubleArrValue); - value = ConvertToJsValue(env, objectManager, jenv, elementSignature, &doubleArrValue); - } else { - jobject result = jenv.GetObjectArrayElement(static_cast(arr), index); - value = ConvertToJsValue(env, objectManager, jenv, elementSignature, &result); - jenv.DeleteLocalRef(result); + // Dispatch on the element-type char (no substr allocation, no string-compare + // chain). Primitive element values are created inline. + switch (arraySignature[1]) { + case 'Z': { + jboolean v; + jenv.GetBooleanArrayRegion((jbooleanArray) arr, startIndex, length, &v); + napi_get_boolean(env, v, &value); + break; + } + case 'B': { + jbyte v; + jenv.GetByteArrayRegion((jbyteArray) arr, startIndex, length, &v); + napi_create_int32(env, v, &value); + break; + } + case 'C': { + jchar v; + jenv.GetCharArrayRegion((jcharArray) arr, startIndex, length, &v); + JniLocalRef s(jenv.NewString(&v, 1)); + jboolean isCopy = false; + const char* singleChar = jenv.GetStringUTFChars(s, &isCopy); + napi_create_string_utf8(env, singleChar, 1, &value); + jenv.ReleaseStringUTFChars(s, singleChar); + break; + } + case 'S': { + jshort v; + jenv.GetShortArrayRegion((jshortArray) arr, startIndex, length, &v); + napi_create_int32(env, v, &value); + break; + } + case 'I': { + jint v; + jenv.GetIntArrayRegion((jintArray) arr, startIndex, length, &v); + napi_create_int32(env, v, &value); + break; + } + case 'J': { + jlong v; + jenv.GetLongArrayRegion((jlongArray) arr, startIndex, length, &v); + napi_create_int64(env, v, &value); + break; + } + case 'F': { + jfloat v; + jenv.GetFloatArrayRegion((jfloatArray) arr, startIndex, length, &v); + napi_create_double(env, v, &value); + break; + } + case 'D': { + jdouble v; + jenv.GetDoubleArrayRegion((jdoubleArray) arr, startIndex, length, &v); + napi_create_double(env, v, &value); + break; + } + default: { // 'L' object or '[' nested array + jobject result = jenv.GetObjectArrayElement((jobjectArray) arr, index); + value = ConvertToJsValue(env, objectManager, jenv, arraySignature.substr(1), &result); + jenv.DeleteLocalRef(result); + break; + } } return value; } -void ArrayElementAccessor::SetArrayElement(napi_env env, napi_value array, uint32_t index, const string& arraySignature, napi_value value) { +void ArrayElementAccessor::SetArrayElement(napi_env env, napi_value array, uint32_t index, + const string& arraySignature, napi_value value, + ObjectManager* objectManager, jobject arrayObject) { JEnv jenv; + if (objectManager == nullptr) { + objectManager = Runtime::GetRuntime(env)->GetObjectManager(); + } + + JniLocalRef localArr; + jobject arr; + if (arrayObject != nullptr) { + arr = arrayObject; + } else { + localArr = objectManager->GetJavaObjectByJsObject(array); + assertNonNullNativeArray(localArr); + arr = localArr; + } + + // Dispatch on the element-type char (no substr allocation, no string-compare + // chain). + switch (arraySignature[1]) { + case 'Z': { //bool + bool b; + napi_get_value_bool(env, value, &b); + jboolean v = static_cast(b); + jenv.SetBooleanArrayRegion((jbooleanArray) arr, index, 1, &v); + break; + } + case 'B': { //byte + int32_t i; + napi_get_value_int32(env, value, &i); + jbyte v = static_cast(i); + jenv.SetByteArrayRegion((jbyteArray) arr, index, 1, &v); + break; + } + case 'C': { //char + size_t str_len; + napi_get_value_string_utf8(env, value, nullptr, 0, &str_len); + string str(str_len, '\0'); + napi_get_value_string_utf8(env, value, &str[0], str_len + 1, &str_len); + JniLocalRef s(jenv.NewString(reinterpret_cast(str.c_str()), 1)); + jboolean isCopy = false; + const char* singleChar = jenv.GetStringUTFChars(s, &isCopy); + jchar v = *singleChar; + jenv.ReleaseStringUTFChars(s, singleChar); + jenv.SetCharArrayRegion((jcharArray) arr, index, 1, &v); + break; + } + case 'S': { //short + int32_t i; + napi_get_value_int32(env, value, &i); + jshort v = static_cast(i); + jenv.SetShortArrayRegion((jshortArray) arr, index, 1, &v); + break; + } + case 'I': { //int + int32_t i; + napi_get_value_int32(env, value, &i); + jint v = static_cast(i); + jenv.SetIntArrayRegion((jintArray) arr, index, 1, &v); + break; + } + case 'J': { //long + int64_t l; + napi_get_value_int64(env, value, &l); + jlong v = static_cast(l); + jenv.SetLongArrayRegion((jlongArray) arr, index, 1, &v); + break; + } + case 'F': { //float + double d; + napi_get_value_double(env, value, &d); + jfloat v = static_cast(d); + jenv.SetFloatArrayRegion((jfloatArray) arr, index, 1, &v); + break; + } + case 'D': { //double + double d; + napi_get_value_double(env, value, &d); + jdouble v = static_cast(d); + jenv.SetDoubleArrayRegion((jdoubleArray) arr, index, 1, &v); + break; + } + default: { //string or object + napi_valuetype ref_type; + napi_typeof(env, value, &ref_type); - auto runtime = Runtime::GetRuntime(env); - auto objectManager = runtime->GetObjectManager(); - - tns::JniLocalRef arr = objectManager->GetJavaObjectByJsObject(array); - - assertNonNullNativeArray(arr); - - const string elementSignature = arraySignature.substr(1); - jboolean isCopy = false; - - if (elementSignature == "Z") { //bool - bool boolElementValue; - napi_get_value_bool(env, value, &boolElementValue); - jboolean jboolElementValue = static_cast(boolElementValue); - jbooleanArray boolArr = static_cast(arr); - jenv.SetBooleanArrayRegion(boolArr, index, 1, &jboolElementValue); - } else if (elementSignature == "B") { //byte - int32_t byteElementValue; - napi_get_value_int32(env, value, &byteElementValue); - jbyte jbyteElementValue = static_cast(byteElementValue); - jbyteArray byteArr = static_cast(arr); - jenv.SetByteArrayRegion(byteArr, index, 1, &jbyteElementValue); - } else if (elementSignature == "C") { //char - size_t str_len; - napi_get_value_string_utf8(env, value, nullptr, 0, &str_len); - string str(str_len, '\0'); - napi_get_value_string_utf8(env, value, &str[0], str_len + 1, &str_len); - JniLocalRef s(jenv.NewString(reinterpret_cast(str.c_str()), 1)); - const char* singleChar = jenv.GetStringUTFChars(s, &isCopy); - jchar charElementValue = *singleChar; - jenv.ReleaseStringUTFChars(s, singleChar); - jcharArray charArr = static_cast(arr); - jenv.SetCharArrayRegion(charArr, index, 1, &charElementValue); - } else if (elementSignature == "S") { //short - int32_t shortElementValue; - napi_get_value_int32(env, value, &shortElementValue); - jshort jshortElementValue = static_cast(shortElementValue); - jshortArray shortArr = static_cast(arr); - jenv.SetShortArrayRegion(shortArr, index, 1, &jshortElementValue); - } else if (elementSignature == "I") { //int - int32_t intElementValue; - napi_get_value_int32(env, value, &intElementValue); - jint jintElementValue = static_cast(intElementValue); - jintArray intArr = static_cast(arr); - jenv.SetIntArrayRegion(intArr, index, 1, &jintElementValue); - } else if (elementSignature == "J") { //long - int64_t longElementValue; - napi_get_value_int64(env, value, &longElementValue); - jlong jlongElementValue = static_cast(longElementValue); - jlongArray longArr = static_cast(arr); - jenv.SetLongArrayRegion(longArr, index, 1, &jlongElementValue); - } else if (elementSignature == "F") { //float - double floatElementValue; - napi_get_value_double(env, value, &floatElementValue); - jfloat jfloatElementValue = static_cast(floatElementValue); - jfloatArray floatArr = static_cast(arr); - jenv.SetFloatArrayRegion(floatArr, index, 1, &jfloatElementValue); - } else if (elementSignature == "D") { //double - double doubleElementValue; - napi_get_value_double(env, value, &doubleElementValue); - jdouble jdoubleElementValue = static_cast(doubleElementValue); - jdoubleArray doubleArr = static_cast(arr); - jenv.SetDoubleArrayRegion(doubleArr, index, 1, &jdoubleElementValue); - } else { //string or object - napi_valuetype ref_type; - - napi_typeof(env, value, &ref_type); - - if (ref_type == napi_object || ref_type == napi_function || ref_type == napi_string) { - JsArgToArrayConverter argConverter(env, value, false, (int) Type::Null); - if (argConverter.IsValid()) { - jobjectArray objArr = static_cast(arr); - jobject objectElementValue = argConverter.GetConvertedArg(); - jenv.SetObjectArrayElement(objArr, index, objectElementValue); + if (ref_type == napi_object || ref_type == napi_function || ref_type == napi_string) { + JsArgToArrayConverter argConverter(env, value, false, (int) Type::Null, objectManager); + if (argConverter.IsValid()) { + jobject objectElementValue = argConverter.GetConvertedArg(); + jenv.SetObjectArrayElement((jobjectArray) arr, index, objectElementValue); + } else { + JsArgToArrayConverter::Error err = argConverter.GetError(); + throw NativeScriptException(string(err.msg)); + } } else { - JsArgToArrayConverter::Error err = argConverter.GetError(); - throw NativeScriptException(string(err.msg)); + throw NativeScriptException(string("Cannot assign primitive value to array of objects.")); } - } else { - throw NativeScriptException(string("Cannot assign primitive value to array of objects.")); + break; } } - } napi_value ArrayElementAccessor::ConvertToJsValue(napi_env env, ObjectManager* objectManager, JEnv& jenv, const string& elementSignature, const void* value) { napi_value jsValue; - jint val = *(jint*) value; - - if (elementSignature == "Z") { - napi_get_boolean(env, *(jboolean*) value, &jsValue); - } else if (elementSignature == "B") { - napi_create_int32(env, *(jbyte*) value, &jsValue); - } else if (elementSignature == "C") { - napi_create_string_utf8(env, (const char*) value, 1, &jsValue); - } else if (elementSignature == "S") { - napi_create_int32(env, *(jshort*) value, &jsValue); - } else if (elementSignature == "I") { - napi_create_int32(env, *(jint*) value, &jsValue); - } else if (elementSignature == "J") { - napi_create_int64(env, *(jlong*) value, &jsValue); - } else if (elementSignature == "F") { - napi_create_double(env, *(jfloat*) value, &jsValue); - } else if (elementSignature == "D") { - napi_create_double(env, *(jdouble*) value, &jsValue); - } else { - if (nullptr != (*(jobject*) value)) { - bool isString = elementSignature == "Ljava/lang/String;"; + switch (elementSignature[0]) { + case 'Z': + napi_get_boolean(env, *(jboolean*) value, &jsValue); + break; + case 'B': + napi_create_int32(env, *(jbyte*) value, &jsValue); + break; + case 'C': + napi_create_string_utf8(env, (const char*) value, 1, &jsValue); + break; + case 'S': + napi_create_int32(env, *(jshort*) value, &jsValue); + break; + case 'I': + napi_create_int32(env, *(jint*) value, &jsValue); + break; + case 'J': + napi_create_int64(env, *(jlong*) value, &jsValue); + break; + case 'F': + napi_create_double(env, *(jfloat*) value, &jsValue); + break; + case 'D': + napi_create_double(env, *(jdouble*) value, &jsValue); + break; + default: { + if (nullptr != (*(jobject*) value)) { + bool isString = elementSignature == "Ljava/lang/String;"; - if (isString) { - jsValue = ArgConverter::jstringToJsString(env, *(jstring *) value); - } else { - jint javaObjectID = objectManager->GetOrCreateObjectId(*(jobject*) value); - jsValue = objectManager->GetJsObjectByJavaObject(javaObjectID); - - if (napi_util::is_null_or_undefined(env, jsValue)) { - string className; - if (elementSignature[0] == '[') { - className = Util::JniClassPathToCanonicalName(elementSignature); - } else { - className = objectManager->GetClassName(*(jobject*) value); - } + if (isString) { + jsValue = ArgConverter::jstringToJsString(env, *(jstring *) value); + } else { + jint javaObjectID = objectManager->GetOrCreateObjectId(*(jobject*) value); + jsValue = objectManager->GetJsObjectByJavaObject(javaObjectID); + + if (napi_util::is_null_or_undefined(env, jsValue)) { + string className; + if (elementSignature[0] == '[') { + className = Util::JniClassPathToCanonicalName(elementSignature); + } else { + className = objectManager->GetClassName(*(jobject*) value); + } - jsValue = objectManager->CreateJSWrapper(javaObjectID, className); + jsValue = objectManager->CreateJSWrapper(javaObjectID, className); + } } + } else { + napi_get_null(env, &jsValue); } - } else { - napi_get_null(env, &jsValue); + break; } } diff --git a/test-app/runtime/src/main/cpp/runtime/conversion/ArrayElementAccessor.h b/test-app/runtime/src/main/cpp/runtime/conversion/ArrayElementAccessor.h index a17a687f..c0474f6a 100644 --- a/test-app/runtime/src/main/cpp/runtime/conversion/ArrayElementAccessor.h +++ b/test-app/runtime/src/main/cpp/runtime/conversion/ArrayElementAccessor.h @@ -11,9 +11,19 @@ namespace tns { class ArrayElementAccessor { public: - napi_value GetArrayElement(napi_env env, napi_value array, uint32_t index, const std::string& arraySignature); + // `objectManager` and `arrayObject` may be supplied pre-resolved by the + // caller (e.g. the host indexed interceptor or an array-loop helper) to + // avoid a locked env->runtime lookup and re-resolving the Java array on + // every element. Both fall back to resolving internally when omitted. + napi_value GetArrayElement(napi_env env, napi_value array, uint32_t index, + const std::string& arraySignature, + ObjectManager* objectManager = nullptr, + jobject arrayObject = nullptr); - void SetArrayElement(napi_env env, napi_value array, uint32_t index, const std::string& arraySignature, napi_value value); + void SetArrayElement(napi_env env, napi_value array, uint32_t index, + const std::string& arraySignature, napi_value value, + ObjectManager* objectManager = nullptr, + jobject arrayObject = nullptr); private: napi_value ConvertToJsValue(napi_env env, ObjectManager* objectManager, JEnv& jEnv, const std::string& elementSignature, const void* value); diff --git a/test-app/runtime/src/main/cpp/runtime/conversion/ArrayHelper.cpp b/test-app/runtime/src/main/cpp/runtime/conversion/ArrayHelper.cpp index 41577484..3d32b233 100644 --- a/test-app/runtime/src/main/cpp/runtime/conversion/ArrayHelper.cpp +++ b/test-app/runtime/src/main/cpp/runtime/conversion/ArrayHelper.cpp @@ -48,7 +48,7 @@ napi_value ArrayHelper::CreateJavaArrayCallback(napi_env env, napi_callback_info } napi_value ArrayHelper::CreateJavaArray(napi_env env, napi_callback_info info) { - NAPI_CALLBACK_BEGIN_VARGS() + NAPI_CALLBACK_BEGIN_VARGS_FAST(8) if (argc != 2) { Throw(env, "Expect two parameters."); diff --git a/test-app/runtime/src/main/cpp/runtime/conversion/JsArgConverter.cpp b/test-app/runtime/src/main/cpp/runtime/conversion/JsArgConverter.cpp index ec025b17..32b33fb2 100644 --- a/test-app/runtime/src/main/cpp/runtime/conversion/JsArgConverter.cpp +++ b/test-app/runtime/src/main/cpp/runtime/conversion/JsArgConverter.cpp @@ -11,8 +11,10 @@ using namespace std; using namespace tns; JsArgConverter::JsArgConverter(napi_env env, napi_value caller, napi_value *args, size_t argc, - const std::string &methodSignature, MetadataEntry *entry) - : m_env(env), m_isValid(true), m_methodSignature(methodSignature), m_error(Error()) { + const std::string &methodSignature, MetadataEntry *entry, JNIEnv *jniEnv, + ObjectManager *objectManager) + : m_env(env), m_jniEnv(jniEnv), m_objectManager(objectManager), m_isValid(true), + m_methodSignature(methodSignature), m_error(Error()) { int napiProvidedArgumentsLength = argc; m_argsLen = 1 + napiProvidedArgumentsLength; @@ -46,8 +48,9 @@ JsArgConverter::JsArgConverter(napi_env env, napi_value caller, napi_value *args JsArgConverter::JsArgConverter(napi_env env, napi_value *args, size_t argc, bool hasImplementationObject, const std::string &methodSignature, - MetadataEntry *entry) - : m_env(env), m_isValid(true), m_methodSignature(methodSignature), m_error(Error()) { + MetadataEntry *entry, JNIEnv *jniEnv, ObjectManager *objectManager) + : m_env(env), m_jniEnv(jniEnv), m_objectManager(objectManager), m_isValid(true), + m_methodSignature(methodSignature), m_error(Error()) { m_argsLen = !hasImplementationObject ? argc : argc - 1; if (m_argsLen > 0) { @@ -114,7 +117,7 @@ bool JsArgConverter::ConvertArg(napi_env env, napi_value arg, int index) { char buff[1024]; - const auto &typeSignature = m_tokens.at(index); + const auto &typeSignature = m_tokens[index]; if (arg == nullptr) { SetConvertedObject(index, nullptr); @@ -166,10 +169,11 @@ bool JsArgConverter::ConvertArg(napi_env env, napi_value arg, int index) { JniLocalRef obj; - auto runtime = Runtime::GetRuntime(m_env); - auto objectManager = runtime->GetObjectManager(); + auto objectManager = m_objectManager != nullptr + ? m_objectManager + : Runtime::GetRuntime(m_env)->GetObjectManager(); - JEnv jEnv; + JEnv jEnv = GetJEnv(); switch (castType) { case CastType::Char: @@ -357,7 +361,7 @@ bool JsArgConverter::ConvertJavaScriptNumber(napi_env env, napi_value jsValue, i jvalue value = {0}; - const auto &typeSignature = m_tokens.at(index); + const auto &typeSignature = m_tokens[index]; const char typePrefix = typeSignature[0]; @@ -437,7 +441,7 @@ bool JsArgConverter::ConvertJavaScriptNumber(napi_env env, napi_value jsValue, i bool JsArgConverter::ConvertJavaScriptBoolean(napi_env env, napi_value jsValue, int index) { bool success; - const auto &typeSignature = m_tokens.at(index); + const auto &typeSignature = m_tokens[index]; if (typeSignature == "Z") { bool argValue; @@ -469,7 +473,7 @@ bool JsArgConverter::ConvertJavaScriptArray(napi_env env, napi_value jsArr, int const jsize arrLength = jsLen; - const auto &arraySignature = m_tokens.at(index); + const auto &arraySignature = m_tokens[index]; std::string elementType = arraySignature.substr(1); @@ -478,7 +482,7 @@ bool JsArgConverter::ConvertJavaScriptArray(napi_env env, napi_value jsArr, int jclass elementClass; std::string strippedClassName; - JEnv jenv; + JEnv jenv = GetJEnv(); switch (elementTypePrefix) { case 'Z': { arr = jenv.NewBooleanArray(arrLength); @@ -594,7 +598,10 @@ bool JsArgConverter::ConvertJavaScriptArray(napi_env env, napi_value jsArr, int for (uint32_t i = 0; i < arrLength; i++) { napi_value element; napi_get_element(env, jsArr, i, &element); - JsArgToArrayConverter c(env, element, false, (int) Type::Null); + JsArgToArrayConverter c(env, element, false, (int) Type::Null, + m_objectManager != nullptr + ? m_objectManager + : Runtime::GetRuntime(env)->GetObjectManager()); jobject o = c.GetConvertedArg(); jenv.SetObjectArrayElement((jobjectArray) arr, (int) i, o); } @@ -616,7 +623,7 @@ template bool JsArgConverter::ConvertFromCastFunctionObject(T value, int index) { bool success = false; - const auto &typeSignature = m_tokens.at(index); + const auto &typeSignature = m_tokens[index]; const char typeSignaturePrefix = typeSignature[0]; @@ -677,7 +684,7 @@ JsArgConverter::Error JsArgConverter::GetError() const { JsArgConverter::~JsArgConverter() { if (m_argsLen > 0) { - JEnv env; + JEnv env = GetJEnv(); for (int i = 0; i < m_args_refs_size; i++) { int index = m_args_refs[i]; if (index != -1) { diff --git a/test-app/runtime/src/main/cpp/runtime/conversion/JsArgConverter.h b/test-app/runtime/src/main/cpp/runtime/conversion/JsArgConverter.h index 33ce2049..d8fe7bd9 100644 --- a/test-app/runtime/src/main/cpp/runtime/conversion/JsArgConverter.h +++ b/test-app/runtime/src/main/cpp/runtime/conversion/JsArgConverter.h @@ -21,9 +21,9 @@ namespace tns { class JsArgConverter { public: - JsArgConverter(napi_env env, napi_value caller, napi_value* args, size_t argc, const std::string& methodSignature, MetadataEntry* entry); + JsArgConverter(napi_env env, napi_value caller, napi_value* args, size_t argc, const std::string& methodSignature, MetadataEntry* entry, JNIEnv* jniEnv = nullptr, ObjectManager* objectManager = nullptr); - JsArgConverter(napi_env env, napi_value* args, size_t argc, bool hasImplementationObject, const std::string& methodSignature, MetadataEntry* entry); + JsArgConverter(napi_env env, napi_value* args, size_t argc, bool hasImplementationObject, const std::string& methodSignature, MetadataEntry* entry, JNIEnv* jniEnv = nullptr, ObjectManager* objectManager = nullptr); JsArgConverter(napi_env env, napi_value* args, size_t argc, const std::string& methodSignature); @@ -81,6 +81,19 @@ namespace tns { napi_env m_env; + // Current thread's JNIEnv* threaded down from the caller (avoids + // re-querying the JavaVM via GetEnv); nullptr => construct locally. + JNIEnv* m_jniEnv = nullptr; + + // Returns a JEnv reusing the threaded JNIEnv* when available. + inline JEnv GetJEnv() const { + return m_jniEnv != nullptr ? JEnv(m_jniEnv, JEnv::Adopt::Trusted) : JEnv(); + } + + // Cached ObjectManager threaded from the caller (avoids a locked + // env->runtime lookup per object-typed argument). + ObjectManager* m_objectManager = nullptr; + int m_argsLen; bool m_isValid; diff --git a/test-app/runtime/src/main/cpp/runtime/conversion/JsArgToArrayConverter.cpp b/test-app/runtime/src/main/cpp/runtime/conversion/JsArgToArrayConverter.cpp index f71940a2..b8f118aa 100644 --- a/test-app/runtime/src/main/cpp/runtime/conversion/JsArgToArrayConverter.cpp +++ b/test-app/runtime/src/main/cpp/runtime/conversion/JsArgToArrayConverter.cpp @@ -12,12 +12,14 @@ using namespace std; using namespace tns; JsArgToArrayConverter::JsArgToArrayConverter(napi_env env, napi_value arg, - bool isImplementationObject, int classReturnType) + bool isImplementationObject, int classReturnType, + ObjectManager* objectManager) : m_arr(nullptr), m_argsAsObject(nullptr), m_argsLen(0), m_isValid(false), m_error(Error()), m_return_type(classReturnType) { + m_objectManager = objectManager; if (!isImplementationObject) { m_argsLen = 1; - m_argsAsObject = new jobject[m_argsLen]; + m_argsAsObject = (m_argsLen <= INLINE_CAPACITY) ? m_inlineArgs : new jobject[m_argsLen]; memset(m_argsAsObject, 0, m_argsLen * sizeof(jobject)); m_isValid = ConvertArg(env, arg, 0); @@ -33,7 +35,7 @@ JsArgToArrayConverter::JsArgToArrayConverter(napi_env env, size_t argc, napi_val bool success = true; if (m_argsLen > 0) { - m_argsAsObject = new jobject[m_argsLen]; + m_argsAsObject = (m_argsLen <= INLINE_CAPACITY) ? m_inlineArgs : new jobject[m_argsLen]; memset(m_argsAsObject, 0, m_argsLen * sizeof(jobject)); for (int i = 0; i < m_argsLen; i++) { @@ -50,7 +52,8 @@ JsArgToArrayConverter::JsArgToArrayConverter(napi_env env, size_t argc, napi_val bool JsArgToArrayConverter::ConvertArg(napi_env env, napi_value arg, int index) { bool success = false; - stringstream s; + // Error text is built only on failure (avoids a per-call stringstream). + std::string errMsg; JEnv jEnv; @@ -131,8 +134,9 @@ bool JsArgToArrayConverter::ConvertArg(napi_env env, napi_value arg, int index) jobject javaObject; JniLocalRef obj; - auto runtime = Runtime::GetRuntime(env); - auto objectManager = runtime->GetObjectManager(); + auto objectManager = m_objectManager != nullptr + ? m_objectManager + : Runtime::GetRuntime(env)->GetObjectManager(); switch (castType) { case CastType::Char: @@ -265,7 +269,8 @@ bool JsArgToArrayConverter::ConvertArg(napi_env env, napi_value arg, int index) napi_get_value_external(env, privateValue, &data); auto node = reinterpret_cast(data); if (node == nullptr) { - s << "Cannot get type of the null argument at index " << index; + errMsg = "Cannot get type of the null argument at index " + + std::to_string(index); success = false; break; } @@ -336,9 +341,11 @@ bool JsArgToArrayConverter::ConvertArg(napi_env env, napi_value arg, int index) napi_value objStr; napi_coerce_to_string(env, jsObj, &objStr); const char *objStrValue = napi_util::get_string_value(env, objStr); + stringstream s; s << "Cannot marshal JavaScript argument " << objStrValue << " at index " << index << " to Java type."; + errMsg = s.str(); } } break; @@ -347,13 +354,14 @@ bool JsArgToArrayConverter::ConvertArg(napi_env env, napi_value arg, int index) throw NativeScriptException("Unsupported cast type"); } } else { - s << "Cannot marshal JavaScript argument at index " << index << " to Java type."; + errMsg = "Cannot marshal JavaScript argument at index " + std::to_string(index) + + " to Java type."; success = false; } if (!success) { m_error.index = index; - m_error.msg = s.str(); + m_error.msg = std::move(errMsg); } return success; @@ -422,7 +430,9 @@ JsArgToArrayConverter::~JsArgToArrayConverter() { env.DeleteLocalRef(m_argsAsObject[index]); } - delete[] m_argsAsObject; + if (m_argsAsObject != m_inlineArgs) { + delete[] m_argsAsObject; + } } } diff --git a/test-app/runtime/src/main/cpp/runtime/conversion/JsArgToArrayConverter.h b/test-app/runtime/src/main/cpp/runtime/conversion/JsArgToArrayConverter.h index 1d0c3759..987dd39c 100644 --- a/test-app/runtime/src/main/cpp/runtime/conversion/JsArgToArrayConverter.h +++ b/test-app/runtime/src/main/cpp/runtime/conversion/JsArgToArrayConverter.h @@ -8,11 +8,16 @@ #include namespace tns { +class ObjectManager; + class JsArgToArrayConverter { public: JsArgToArrayConverter(napi_env env, size_t argc, napi_value* argv, bool hasImplementationObject); - JsArgToArrayConverter(napi_env env, napi_value arg, bool isImplementationObject, int classReturnType); + // `objectManager` may be supplied pre-resolved (avoids a locked + // env->runtime lookup); falls back to resolving internally when omitted. + JsArgToArrayConverter(napi_env env, napi_value arg, bool isImplementationObject, int classReturnType, + ObjectManager* objectManager = nullptr); ~JsArgToArrayConverter(); @@ -54,6 +59,14 @@ class JsArgToArrayConverter { jobject* m_argsAsObject; + // Inline storage for the common small-arity case (esp. the single-arg + // path used per object-array element); heap only when larger. + static const int INLINE_CAPACITY = 8; + jobject m_inlineArgs[INLINE_CAPACITY]; + + // Cached ObjectManager threaded from the caller. + ObjectManager* m_objectManager = nullptr; + jobjectArray m_arr; short MAX_JAVA_PARAMS_COUNT = 256; diff --git a/test-app/runtime/src/main/cpp/runtime/exceptions/NativeScriptException.cpp b/test-app/runtime/src/main/cpp/runtime/exceptions/NativeScriptException.cpp index df11c490..566e02c7 100644 --- a/test-app/runtime/src/main/cpp/runtime/exceptions/NativeScriptException.cpp +++ b/test-app/runtime/src/main/cpp/runtime/exceptions/NativeScriptException.cpp @@ -3,6 +3,7 @@ #include "ArgConverter.h" #include "NativeScriptAssert.h" #include "Runtime.h" +#include "ObjectManager.h" #include using namespace std; @@ -72,11 +73,9 @@ void NativeScriptException::ReThrowToJava(napi_env env) { JEnv jEnv; if (!m_javaException.IsNull()) { - std::string excClassName; - if (env) { - auto objectManager = Runtime::GetRuntime(env)->GetObjectManager(); - excClassName = objectManager->GetClassName((jobject)m_javaException); - } + // Static lookup avoids needing the runtime/ObjectManager here, which may + // be unavailable while an exception is being rethrown to Java. + std::string excClassName = ObjectManager::GetClassName((jobject)m_javaException); if (excClassName == "com/tns/NativeScriptException") { ex = m_javaException; @@ -99,8 +98,7 @@ void NativeScriptException::ReThrowToJava(napi_env env) { if (ex == nullptr) { ex = static_cast(jEnv.NewObject(NATIVESCRIPTEXCEPTION_CLASS, NATIVESCRIPTEXCEPTION_JSVALUE_CTOR_ID, (jstring)msg, (jstring)stackTrace, reinterpret_cast(m_javascriptException))); } else { - auto objectManager = Runtime::GetRuntime(env)->GetObjectManager(); - auto excClassName = objectManager->GetClassName(ex); + auto excClassName = ObjectManager::GetClassName(ex); if (excClassName != "com/tns/NativeScriptException") { ex = static_cast(jEnv.NewObject(NATIVESCRIPTEXCEPTION_CLASS, NATIVESCRIPTEXCEPTION_THROWABLE_CTOR_ID, (jstring)msg, (jstring)stackTrace, ex)); } @@ -172,9 +170,7 @@ napi_value NativeScriptException::WrapJavaToJsException(napi_env env) { JEnv jenv; - auto objectManager = Runtime::GetRuntime(env)->GetObjectManager(); - - string excClassName = objectManager->GetClassName((jobject)m_javaException); + string excClassName = ObjectManager::GetClassName((jobject)m_javaException); if (excClassName == "com/tns/NativeScriptException") { jfieldID fieldID = jenv.GetFieldID(jenv.GetObjectClass(m_javaException), "jsValueAddress", "J"); jlong addr = jenv.GetLongField(m_javaException, fieldID); diff --git a/test-app/runtime/src/main/cpp/runtime/exceptions/NativeScriptException.h b/test-app/runtime/src/main/cpp/runtime/exceptions/NativeScriptException.h index e7f82e22..9d4aa268 100644 --- a/test-app/runtime/src/main/cpp/runtime/exceptions/NativeScriptException.h +++ b/test-app/runtime/src/main/cpp/runtime/exceptions/NativeScriptException.h @@ -32,6 +32,9 @@ class NativeScriptException { void ReThrowToNapi(napi_env env); void ReThrowToJava(napi_env env); + // The stored message, for logging uncaught native exceptions. + const char* what() const noexcept { return m_message.c_str(); } + static void Init(); /* diff --git a/test-app/runtime/src/main/cpp/runtime/inspector/JsV8InspectorClient.cpp b/test-app/runtime/src/main/cpp/runtime/inspector/JsV8InspectorClient.cpp index 3e96e03d..01243626 100644 --- a/test-app/runtime/src/main/cpp/runtime/inspector/JsV8InspectorClient.cpp +++ b/test-app/runtime/src/main/cpp/runtime/inspector/JsV8InspectorClient.cpp @@ -1,6 +1,8 @@ #ifdef __V8__ #include "JsV8InspectorClient.h" #include +#include +#include #include #include #include @@ -13,8 +15,19 @@ #include "NativeScriptAssert.h" #include "ArgConverter.h" +#include "Constants.h" +#include "File.h" #include "Util.h" #include "Utils.h" +#include "jsr.h" + +#ifdef APPLICATION_IN_DEBUG +#include "WorkerInspectorClient.h" +#include "WorkerWrapper.h" +#endif + +#include "ada/ada.h" +#include "third_party/json.hpp" using namespace std; using namespace tns; @@ -23,6 +36,8 @@ using namespace v8; using namespace v8_inspector; using namespace inspector; +using json = nlohmann::json; + // Utility functions for converting between inspector StringView and UTF8 string @@ -45,6 +60,158 @@ static inline std::string stringViewToString(v8::Isolate* isolate, const v8_insp return *result; } +namespace { + +// Scheme advertised to the frontend for source maps the runtime can serve. +// Chrome DevTools never loads `file:` (or `data:`/`devtools:`) resources +// through the target -- PageResourceLoader routes those to the frontend host +// machine, which cannot see files on the device. Any other scheme is fetched +// with Network.loadNetworkResource, which we answer from disk. +constexpr const char* kSourceMapScheme = "nsruntime://"; + +std::string JsonDump(const json& value) { + // replace invalid UTF-8 instead of throwing across the JNI boundary + return value.dump(-1, ' ', false, json::error_handler_t::replace); +} + +std::string FinishResponse(json& response, const std::string& sessionId) { + if (!sessionId.empty()) { + response["sessionId"] = sessionId; + } + return JsonDump(response); +} + +#ifdef APPLICATION_IN_DEBUG +// Target.attachedToTarget event announcing a worker as a child target. +std::string BuildWorkerAttachedEvent(WorkerInspectorClient* client) { + json attached = {{"method", "Target.attachedToTarget"}, + {"params", + {{"sessionId", client->SessionId()}, + {"targetInfo", + {{"targetId", client->TargetId()}, + {"type", "worker"}, + {"title", client->Url()}, + {"url", client->Url()}, + {"attached", true}, + {"canAccessOpener", false}}}, + {"waitingForDebugger", false}}}}; + return JsonDump(attached); +} +#endif + +std::string Base64Encode(const char* data, size_t length) { + static const char* kAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + std::string encoded; + encoded.reserve(((length + 2) / 3) * 4); + size_t i = 0; + for (; i + 2 < length; i += 3) { + uint32_t chunk = (static_cast(data[i]) << 16) | + (static_cast(data[i + 1]) << 8) | + static_cast(data[i + 2]); + encoded.push_back(kAlphabet[(chunk >> 18) & 0x3F]); + encoded.push_back(kAlphabet[(chunk >> 12) & 0x3F]); + encoded.push_back(kAlphabet[(chunk >> 6) & 0x3F]); + encoded.push_back(kAlphabet[chunk & 0x3F]); + } + if (i < length) { + uint32_t chunk = static_cast(data[i]) << 16; + bool hasSecond = i + 1 < length; + if (hasSecond) { + chunk |= static_cast(data[i + 1]) << 8; + } + encoded.push_back(kAlphabet[(chunk >> 18) & 0x3F]); + encoded.push_back(kAlphabet[(chunk >> 12) & 0x3F]); + encoded.push_back(hasSecond ? kAlphabet[(chunk >> 6) & 0x3F] : '='); + encoded.push_back('='); + } + return encoded; +} + +// Opt-out via nativescript.config.ts (serialized into the bundled +// package.json): `android: { disableSourceMapURLRewrite: true }`, or the same +// key at the top level. +bool ShouldRewriteSourceMapURLs() { + static bool disabled = []() { + int length = 0; + auto* data = static_cast(File::ReadBinary(Constants::APP_ROOT_FOLDER_PATH + "package.json", length)); + if (data == nullptr) { + return false; + } + std::string content(reinterpret_cast(data), length); + delete[] data; + + auto parsed = json::parse(content, nullptr, false); + if (parsed.is_discarded() || !parsed.is_object()) { + return false; + } + + const json* value = nullptr; + if (parsed.contains("android") && parsed["android"].contains("disableSourceMapURLRewrite")) { + value = &parsed["android"]["disableSourceMapURLRewrite"]; + } else if (parsed.contains("disableSourceMapURLRewrite")) { + value = &parsed["disableSourceMapURLRewrite"]; + } + return value != nullptr && value->is_boolean() && value->get(); + }(); + return !disabled; +} + +// Rewrites the sourceMapURL of outgoing Debugger.scriptParsed / +// Debugger.scriptFailedToParse events from a file url (or a url relative to +// the script's file url) to an absolute nsruntime:// url, so DevTools +// requests the map through the target instead of the frontend host. +std::string MaybeRewriteSourceMapURL(const std::string& message) { + if (message.find("\"Debugger.scriptParsed\"") == std::string::npos && + message.find("\"Debugger.scriptFailedToParse\"") == std::string::npos) { + return message; + } + + if (!ShouldRewriteSourceMapURLs()) { + return message; + } + + auto parsed = json::parse(message, nullptr, false); + if (parsed.is_discarded() || !parsed.contains("params") || !parsed["params"].is_object()) { + return message; + } + + auto& params = parsed["params"]; + std::string sourceMapURL = params.value("sourceMapURL", ""); + if (sourceMapURL.empty() || sourceMapURL.rfind("data:", 0) == 0 || + sourceMapURL.rfind("http:", 0) == 0 || sourceMapURL.rfind("https:", 0) == 0 || + sourceMapURL.rfind(kSourceMapScheme, 0) == 0) { + return message; + } + + std::string path; + if (sourceMapURL.rfind("file://", 0) == 0) { + path = sourceMapURL.substr(strlen("file://")); + } else if (sourceMapURL[0] == '/') { + path = sourceMapURL; + } else { + // Relative to the script url, e.g. "bundle.js.map". + std::string scriptUrl = params.value("url", ""); + if (scriptUrl.rfind("file://", 0) != 0) { + return message; + } + std::string scriptPath = scriptUrl.substr(strlen("file://")); + auto lastSlash = scriptPath.rfind('/'); + if (lastSlash == std::string::npos) { + return message; + } + path = scriptPath.substr(0, lastSlash + 1) + sourceMapURL; + } + + if (path.empty()) { + return message; + } + + params["sourceMapURL"] = kSourceMapScheme + path; + return JsonDump(parsed); +} + +} // namespace + JsV8InspectorClient::JsV8InspectorClient(napi_env _env) : env(_env), inspector_(nullptr), @@ -71,6 +238,7 @@ JsV8InspectorClient::JsV8InspectorClient(napi_env _env) void JsV8InspectorClient::connect(jobject connection) { JEnv env; + std::lock_guard lock(connectionMutex_); connection_ = env.NewGlobalRef(connection); isConnected_ = true; } @@ -94,8 +262,38 @@ void JsV8InspectorClient::createInspectorSession() { } void JsV8InspectorClient::disconnect() { - if (connection_ == nullptr) { - return; + { + // Streams only have meaning to the frontend that opened them; drop any + // the old connection never read to the end (or never IO.close-d). + std::lock_guard lock(resourceStreamsMutex_); + resourceStreams_.clear(); + } + +#ifdef APPLICATION_IN_DEBUG + // Reset worker sessions first and without the main-isolate Locker: if the + // main isolate is paused, its nested loop owns the Locker and this thread + // blocks below — workers must still get a clean slate (resume if paused, + // fresh session) so the reconnecting frontend can re-attach to them. + { + std::lock_guard lock(workerTargetsMutex_); + autoAttach_ = false; + for (auto& entry : workerTargets_) { + entry.second.announced = false; + entry.second.client->PushMessage(WorkerInspectorClient::kResetSessionMessage); + } + } +#endif + + { + std::lock_guard lock(connectionMutex_); + if (connection_ == nullptr) { + return; + } + + JEnv env; + env.DeleteGlobalRef(connection_); + connection_ = nullptr; + isConnected_ = false; } v8::Locker locker(env->isolate); @@ -105,11 +303,6 @@ void JsV8InspectorClient::disconnect() { session_->resume(); session_.reset(); - JEnv env; - env.DeleteGlobalRef(connection_); - connection_ = nullptr; - isConnected_ = false; - createInspectorSession(); } @@ -208,6 +401,7 @@ void JsV8InspectorClient::runMessageLoopOnPause(int context_group_id) { terminated_ = false; running_nested_loop_ = true; + isPausedNestedLoop_.store(true, std::memory_order_release); while (!terminated_) { JniLocalRef msg(jEnv.CallStaticObjectMethod(inspectorClass_, getInspectorMessageMethod_, connection_)); if (!msg.IsNull()) { @@ -218,6 +412,7 @@ void JsV8InspectorClient::runMessageLoopOnPause(int context_group_id) { while (v8::platform::PumpMessageLoop(JSR::platform.get(), env->isolate)) { } } + isPausedNestedLoop_.store(false, std::memory_order_release); terminated_ = false; running_nested_loop_ = false; } @@ -239,21 +434,403 @@ void JsV8InspectorClient::doDispatchMessage(const std::string& message) { session_->dispatchProtocolMessage(message_view); } +// Chrome DevTools fetches source maps through the target: it sends +// Network.loadNetworkResource for the resolved sourceMappingURL and reads the +// returned stream with IO.read/IO.close. Neither domain is implemented by +// V8's inspector, so they are served here, on the websocket read thread -- +// the main thread may be blocked in the pause message loop or busy running +// JS. The Target domain and worker-session routing live here for the same +// reason: messages received while the main isolate is paused are dispatched +// by doDispatchMessage straight into the V8 session, so dispatchMessage's +// method handling never runs, and a worker must stay debuggable while the +// main isolate is paused (and vice versa). None of this touches V8 except +// the thread-safe RequestInterrupt. +bool JsV8InspectorClient::handleMessageOnSocketThread(const std::string& message, std::string& response) { + auto parsed = json::parse(message, nullptr, false); + if (parsed.is_discarded() || !parsed.is_object()) { + return false; + } + + std::string method = parsed.contains("method") && parsed["method"].is_string() + ? parsed["method"].get() + : ""; + long long msgId = parsed.contains("id") && parsed["id"].is_number() + ? parsed["id"].get() + : -1; + std::string sessionId = parsed.contains("sessionId") && parsed["sessionId"].is_string() + ? parsed["sessionId"].get() + : ""; + + // Network/IO first: they serve any session (sessionId echoed), including + // worker source maps. + if (method == "Network.loadNetworkResource") { + std::string url; + if (parsed.contains("params") && parsed["params"].contains("url") && parsed["params"]["url"].is_string()) { + url = parsed["params"]["url"].get(); + } + response = HandleLoadNetworkResource(msgId, url, sessionId); + return true; + } + + if (method == "IO.read" || method == "IO.close") { + std::string handle; + int size = 0; + if (parsed.contains("params")) { + const auto& params = parsed["params"]; + if (params.contains("handle") && params["handle"].is_string()) { + handle = params["handle"].get(); + } + if (params.contains("size") && params["size"].is_number_integer()) { + size = params["size"].get(); + } + } + response = method == "IO.read" + ? HandleIORead(msgId, handle, size, sessionId) + : HandleIOClose(msgId, handle, sessionId); + return true; + } + +#ifdef APPLICATION_IN_DEBUG + // DevTools discovers worker targets through the Target domain: its + // ChildTargetManager sends Target.setAutoAttach {flatten: true} right + // after connecting, and from then on expects Target.attachedToTarget / + // Target.detachedFromTarget events. + if (method == "Target.setAutoAttach") { + bool autoAttach = parsed.contains("params") && parsed["params"].contains("autoAttach") && + parsed["params"]["autoAttach"].is_boolean() && + parsed["params"]["autoAttach"].get(); + if (sessionId.empty()) { + { + std::lock_guard lock(workerTargetsMutex_); + autoAttach_ = autoAttach; + } + // The ack must reach the frontend before any attachedToTarget + // events, so it is sent here instead of through `response` (which + // the socket only writes after this method returns). + json ack = {{"id", msgId}, {"result", json::object()}}; + this->SendToFrontend(JsonDump(ack)); + if (autoAttach) { + this->AnnounceWorkerTargets(); + } + } else { + // Workers have no child targets of their own; just ack. + json ack = {{"id", msgId}, {"result", json::object()}}; + this->SendToFrontend(FinishResponse(ack, sessionId)); + } + return true; + } + + if (method == "Target.setDiscoverTargets" || method == "Target.setRemoteLocations" || + method == "Target.detachFromTarget") { + json ack = {{"id", msgId}, {"result", json::object()}}; + response = FinishResponse(ack, sessionId); + return true; + } + + // Flat-session protocol: a top-level sessionId addresses a worker target. + if (!sessionId.empty()) { + this->RouteToWorker(sessionId, method, msgId, message); + return true; + } +#endif + + // Debugger.pause needs to interrupt V8 even if the main thread is busy + // executing JS; RequestInterrupt fires at the next safe bytecode boundary. + // The message still flows through the dispatch queue so V8 answers the + // request id. Skip it while paused in the nested message loop: no JS is + // running, so the interrupt would only fire after the user resumes, + // causing a spurious re-pause. + if (method == "Debugger.pause" && !isPausedNestedLoop_.load(std::memory_order_acquire)) { + env->isolate->RequestInterrupt( + [](v8::Isolate* isolate, void* data) { + auto* client = static_cast(data); + if (client->session_ != nullptr) { + client->session_->schedulePauseOnNextStatement({}, {}); + } + }, + this); + } + + return false; +} + +#ifdef APPLICATION_IN_DEBUG +void JsV8InspectorClient::RouteToWorker(const std::string& sessionId, const std::string& method, + long long msgId, const std::string& message) { + // Built under the lock, sent after releasing it: a blocking socket write + // must not stall worker register/unregister on other threads. + std::string errorPayload; + { + std::lock_guard lock(workerTargetsMutex_); + auto it = workerTargets_.find(sessionId); + if (it == workerTargets_.end()) { + // The worker died (or never existed): answer commands so the + // frontend does not wait forever. + if (msgId >= 0) { + json error = {{"id", msgId}, + {"sessionId", sessionId}, + {"error", {{"code", -32001}, {"message", "Session not found"}}}}; + errorPayload = JsonDump(error); + } + } else { + // The lock keeps the client alive against a concurrent + // UnregisterWorkerTarget + delete on the worker thread; both calls + // below are non-blocking (queue push / RequestInterrupt), so they + // never hold the lock across a socket write. + WorkerInspectorClient* client = it->second.client; + + // Debugger.pause must interrupt a busy worker; skip it while the + // worker sits in its nested pause loop (no JS running - the + // interrupt would only fire after resume, causing a spurious + // re-pause). The message is still pushed so V8 answers the id. + if (method == "Debugger.pause" && !client->IsRunningPauseLoop()) { + client->RequestPauseInterrupt(); + } + + client->PushMessage(message); + } + } + + if (!errorPayload.empty()) { + this->SendToFrontend(errorPayload); + } +} + +void JsV8InspectorClient::RegisterWorkerTarget(int workerId, WorkerInspectorClient* client) { + std::string attachedPayload; + { + std::lock_guard lock(workerTargetsMutex_); + WorkerTarget target{workerId, client, false}; + + if (isConnected_ && autoAttach_) { + target.announced = true; + attachedPayload = BuildWorkerAttachedEvent(client); + } + + workerTargets_.emplace(client->SessionId(), target); + } + + if (!attachedPayload.empty()) { + this->SendToFrontend(attachedPayload); + } +} + +void JsV8InspectorClient::UnregisterWorkerTarget(int workerId) { + std::string detachedPayload; + { + std::lock_guard lock(workerTargetsMutex_); + for (auto it = workerTargets_.begin(); it != workerTargets_.end(); ++it) { + if (it->second.workerId != workerId) { + continue; + } + + if (it->second.announced && isConnected_) { + json detached = {{"method", "Target.detachedFromTarget"}, + {"params", + {{"sessionId", it->second.client->SessionId()}, + {"targetId", it->second.client->TargetId()}}}}; + detachedPayload = JsonDump(detached); + } + + workerTargets_.erase(it); + break; + } + } + + if (!detachedPayload.empty()) { + this->SendToFrontend(detachedPayload); + } +} + +void JsV8InspectorClient::AnnounceWorkerTargets() { + std::vector pending; + { + std::lock_guard lock(workerTargetsMutex_); + for (auto& entry : workerTargets_) { + WorkerTarget& target = entry.second; + if (target.announced) { + continue; + } + target.announced = true; + pending.push_back(BuildWorkerAttachedEvent(target.client)); + } + } + + for (const auto& payload : pending) { + this->SendToFrontend(payload); + } +} + +void JsV8InspectorClient::SchedulePauseInWorker(int workerId) { + // Runs on the worker's own thread from a V8 interrupt; re-resolved through + // the registry so a late interrupt after the worker died is a no-op. + std::lock_guard lock(workerTargetsMutex_); + for (auto& entry : workerTargets_) { + if (entry.second.workerId == workerId) { + entry.second.client->SchedulePauseFromInterrupt(); + return; + } + } +} +#endif + +std::string JsV8InspectorClient::HandleLoadNetworkResource(long long msgId, const std::string& url, const std::string& sessionId) { + std::string path; + if (url.rfind(kSourceMapScheme, 0) == 0) { + path = url.substr(strlen(kSourceMapScheme)); + } else if (url.rfind("file://", 0) == 0) { + path = url.substr(strlen("file://")); + } else { + // Reply with a protocol error (not success:false) so DevTools falls + // back to loading the resource from the frontend host, which is the + // pre-existing behavior for http(s) urls. + json error = { + {"id", msgId}, + {"error", {{"code", -32000}, {"message", "Unsupported URL scheme"}}} + }; + return FinishResponse(error, sessionId); + } + + std::string content; + bool loaded = false; + + if (!path.empty()) { + std::vector candidates; + auto addCandidate = [&candidates](const std::string& candidate) { + if (!candidate.empty() && + std::find(candidates.begin(), candidates.end(), candidate) == candidates.end()) { + candidates.push_back(candidate); + } + }; + auto addVariants = [&addCandidate](const std::string& p) { + addCandidate(p); + if (p[0] != '/') { + addCandidate(Constants::APP_ROOT_FOLDER_PATH + p); + } + // /data/data/ and /data/user/0/ alias the same files; + // urls may use either spelling depending on who built them. + constexpr const char* kDataData = "/data/data/"; + constexpr const char* kDataUser0 = "/data/user/0/"; + if (p.rfind(kDataData, 0) == 0) { + addCandidate(kDataUser0 + p.substr(strlen(kDataData))); + } else if (p.rfind(kDataUser0, 0) == 0) { + addCandidate(kDataData + p.substr(strlen(kDataUser0))); + } + }; + + addVariants(path); + // fall back to percent-decoded variants for urls the frontend encoded + std::string decoded = ada::unicode::percent_decode(path, path.find('%')); + if (decoded != path) { + addVariants(decoded); + } + + for (const auto& candidate : candidates) { + int length = 0; + auto* data = static_cast(File::ReadBinary(candidate, length)); + if (data != nullptr) { + content.assign(reinterpret_cast(data), length); + delete[] data; + loaded = true; + break; + } + } + } + + json resource; + if (loaded) { + std::string handle; + { + std::lock_guard lock(resourceStreamsMutex_); + handle = "ns-network-resource-" + std::to_string(++lastStreamId_); + resourceStreams_[handle] = {std::move(content), 0}; + } + resource = {{"success", true}, {"httpStatusCode", 200}, {"stream", handle}}; + } else { + resource = {{"success", false}, + {"netError", -6}, + {"netErrorName", "net::ERR_FILE_NOT_FOUND"}, + {"httpStatusCode", 404}}; + } + + json response = {{"id", msgId}, {"result", {{"resource", resource}}}}; + return FinishResponse(response, sessionId); +} + +std::string JsV8InspectorClient::HandleIORead(long long msgId, const std::string& handle, int size, const std::string& sessionId) { + std::lock_guard lock(resourceStreamsMutex_); + auto it = resourceStreams_.find(handle); + if (it == resourceStreams_.end()) { + json error = { + {"id", msgId}, + {"error", {{"code", -32602}, {"message", "Invalid stream handle"}}} + }; + return FinishResponse(error, sessionId); + } + + ResourceStream& stream = it->second; + constexpr size_t kDefaultChunkSize = 1024 * 1024; + size_t chunkSize = size > 0 ? static_cast(size) : kDefaultChunkSize; + size_t remaining = stream.data.size() - stream.offset; + chunkSize = std::min(chunkSize, remaining); + + json result; + if (chunkSize == 0) { + // DevTools ignores any data sent alongside eof, so only signal it once + // the whole stream has been delivered. + result = {{"data", ""}, {"eof", true}, {"base64Encoded", false}}; + } else { + // Base64 keeps arbitrary file bytes intact through the JSON transport. + std::string encoded = Base64Encode(stream.data.data() + stream.offset, chunkSize); + stream.offset += chunkSize; + result = {{"data", encoded}, {"eof", false}, {"base64Encoded", true}}; + } + + json response = {{"id", msgId}, {"result", result}}; + return FinishResponse(response, sessionId); +} + +std::string JsV8InspectorClient::HandleIOClose(long long msgId, const std::string& handle, const std::string& sessionId) { + { + std::lock_guard lock(resourceStreamsMutex_); + resourceStreams_.erase(handle); + } + json response = {{"id", msgId}, {"result", json::object()}}; + return FinishResponse(response, sessionId); +} + void JsV8InspectorClient::sendResponse(int callId, std::unique_ptr message) { sendNotification(std::move(message)); } void JsV8InspectorClient::sendNotification(std::unique_ptr message) { - if (connection_ == nullptr) { - return; - } + this->SendToFrontend(stringViewToString(env->isolate, message->string())); +} - const std::string msg = stringViewToString(env->isolate, message->string()); +void JsV8InspectorClient::SendToFrontend(const std::string& message) { + JEnv jenv; + JniLocalRef connection; + { + std::lock_guard lock(connectionMutex_); + if (connection_ == nullptr) { + return; + } + // A local ref keeps the websocket reachable after disconnect() drops + // the global ref; the (synchronized, possibly blocking) socket write + // must not run under the mutex or it would block disconnect(). + connection = JniLocalRef(jenv.NewLocalRef(connection_)); + } - JEnv env; - // TODO: Pete: Check if we can use a wide (utf 16) string here - JniLocalRef str(env.NewStringUTF(msg.c_str())); - env.CallStaticVoidMethod(inspectorClass_, sendMethod_, connection_, (jstring) str); + const std::string msg = MaybeRewriteSourceMapURL(message); + try { + // TODO: Pete: Check if we can use a wide (utf 16) string here + JniLocalRef str(jenv.NewStringUTF(msg.c_str())); + jenv.CallStaticVoidMethod(inspectorClass_, sendMethod_, (jobject) connection, (jstring) str); + } catch (NativeScriptException& e) { + // The socket died mid-send; the frontend is gone anyway. This must not + // unwind into V8 inspector internals or a worker's pause loop. + jenv.ExceptionClear(); + } } void JsV8InspectorClient::flushProtocolNotifications() { @@ -271,7 +848,11 @@ void JsV8InspectorClient::init() { inspector_ = V8Inspector::create(env->isolate, this); - inspector_->contextCreated(v8_inspector::V8ContextInfo(context, JsV8InspectorClient::contextGroupId, {})); + // Name the context: the DevTools console context selector labels entries + // with the context's name; workers are labeled with their script url. + static const std::string mainContextName = "main"; + inspector_->contextCreated(v8_inspector::V8ContextInfo( + context, JsV8InspectorClient::contextGroupId, stringToStringView(mainContextName))); context_.Reset(env->isolate, context); @@ -288,34 +869,48 @@ void JsV8InspectorClient::init() { } JsV8InspectorClient* JsV8InspectorClient::GetInstance() { - if (instance == nullptr) { - instance = new JsV8InspectorClient(Runtime::GetRuntime(0)->GetNapiEnv()); + JsV8InspectorClient* client = instance.load(std::memory_order_acquire); + if (client != nullptr) { + return client; + } + + // handleMessageOnSocketThread also calls this from the socket thread, so a + // concurrent first call is possible: construct, then publish with a CAS and + // discard our copy if another thread won the race. + auto* created = new JsV8InspectorClient(Runtime::GetRuntime(0)->GetNapiEnv()); + JsV8InspectorClient* expected = nullptr; + if (!instance.compare_exchange_strong(expected, created, std::memory_order_acq_rel, + std::memory_order_acquire)) { + delete created; + return expected; } - return instance; + return created; +} + +JsV8InspectorClient* JsV8InspectorClient::GetInstanceIfCreated() { + return instance.load(std::memory_order_acquire); } void JsV8InspectorClient::inspectorSendEventCallback(const FunctionCallbackInfo& args) { - if ((instance == nullptr) || (instance->connection_ == nullptr)) { + JsV8InspectorClient* client = GetInstanceIfCreated(); + if (client == nullptr || !client->isConnected_) { return; } - Isolate* isolate = args.GetIsolate(); Local arg = args[0].As(); std::string message = tns::ConvertToString(arg); - JEnv env; - // TODO: Pete: Check if we can use a wide (utf 16) string here - JniLocalRef str(env.NewStringUTF(message.c_str())); - env.CallStaticVoidMethod(instance->inspectorClass_, instance->sendMethod_, instance->connection_, (jstring) str); + client->SendToFrontend(message); // TODO: ios uses this method, but doesn't work on android // so I'm just sending directly to the socket (which seems to work) - instance->dispatchMessage(message); + client->dispatchMessage(message); } void JsV8InspectorClient::sendToFrontEndCallback(const v8::FunctionCallbackInfo& args) { - if ((instance == nullptr) || (instance->connection_ == nullptr)) { + JsV8InspectorClient* client = GetInstanceIfCreated(); + if (client == nullptr) { return; } @@ -331,9 +926,18 @@ void JsV8InspectorClient::sendToFrontEndCallback(const v8::FunctionCallbackInfo< } JEnv env; + JniLocalRef connection; + { + std::lock_guard lock(client->connectionMutex_); + if (client->connection_ == nullptr) { + return; + } + connection = JniLocalRef(env.NewLocalRef(client->connection_)); + } + JniLocalRef str(env.NewStringUTF(message.c_str())); JniLocalRef lev(env.NewStringUTF(level.c_str())); - env.CallStaticVoidMethod(instance->inspectorClass_, instance->sendToDevToolsConsoleMethod_, instance->connection_, (jstring) str, (jstring)lev); + env.CallStaticVoidMethod(client->inspectorClass_, client->sendToDevToolsConsoleMethod_, (jobject) connection, (jstring) str, (jstring)lev); } } catch (NativeScriptException& e) { napi_env env = Runtime::GetRuntime(0)->GetNapiEnv(); @@ -352,33 +956,48 @@ void JsV8InspectorClient::sendToFrontEndCallback(const v8::FunctionCallbackInfo< } void JsV8InspectorClient::consoleLogCallback(napi_env env, ConsoleAPIType method, const std::vector>& args) { - if (!inspectorIsConnected()) { +#ifdef APPLICATION_IN_DEBUG + // Worker isolates route to their own inspector (we're on the worker's + // thread here). Checked first so worker logging never lazily constructs + // the root client. + WorkerWrapper* worker = WorkerWrapper::FromEnv(env); + if (worker != nullptr) { + worker->ConsoleLog(method, args); + return; + } +#endif + + JsV8InspectorClient* client = GetInstanceIfCreated(); + if (client == nullptr || client->inspector_ == nullptr) { return; } // Note, here we access private V8 API - auto* impl = reinterpret_cast(instance->inspector_.get()); - auto* session = reinterpret_cast(instance->session_.get()); + auto* impl = reinterpret_cast(client->inspector_.get()); std::unique_ptr stack = impl->debugger()->captureStackTrace(false); - v8::Local context = instance->context_.Get(instance->env->isolate); + v8::Local context = client->context_.Get(client->env->isolate); const int contextId = V8ContextInfo::executionContextId(context); #ifdef __V8_13__ v8::MemorySpan> argsSpan((v8::Local *) args.data(), args.size()); std::unique_ptr msg = v8_inspector::V8ConsoleMessage::createForConsoleAPI( - context, contextId, contextGroupId, impl, instance->currentTimeMS(), + context, contextId, contextGroupId, impl, client->currentTimeMS(), method, argsSpan, String16{}, std::move(stack)); #else std::unique_ptr msg = v8_inspector::V8ConsoleMessage::createForConsoleAPI( - context, contextId, contextGroupId, impl, instance->currentTimeMS(), + context, contextId, contextGroupId, impl, client->currentTimeMS(), method, args, String16{}, std::move(stack)); #endif - session->runtimeAgent()->messageAdded(msg.get()); + // Going through the message storage both reports to the session when the + // frontend has enabled the Runtime agent AND keeps the message for replay + // on Runtime.enable, so anything logged before the frontend attaches + // shows up as console history. + impl->ensureConsoleMessageStorage(contextGroupId)->addMessage(std::move(msg)); } void JsV8InspectorClient::registerDomainDispatcherCallback(const FunctionCallbackInfo& args) { @@ -459,7 +1078,7 @@ void JsV8InspectorClient::InspectorIsConnectedGetterCallback(v8::LocalisConnected_); } -JsV8InspectorClient* JsV8InspectorClient::instance = nullptr; +std::atomic JsV8InspectorClient::instance{nullptr}; bool JsV8InspectorClient::CallDomainHandlerFunction(Local context, Local domainMethodFunc, const Local& arg, Local& domainDebugger, Local& result) { diff --git a/test-app/runtime/src/main/cpp/runtime/inspector/JsV8InspectorClient.h b/test-app/runtime/src/main/cpp/runtime/inspector/JsV8InspectorClient.h index 42090625..d5ab3b7d 100644 --- a/test-app/runtime/src/main/cpp/runtime/inspector/JsV8InspectorClient.h +++ b/test-app/runtime/src/main/cpp/runtime/inspector/JsV8InspectorClient.h @@ -3,6 +3,9 @@ #ifdef __V8__ +#include +#include +#include #include #include #include @@ -16,16 +19,44 @@ using namespace v8_inspector; namespace tns { +#ifdef APPLICATION_IN_DEBUG +class WorkerInspectorClient; +#endif + class JsV8InspectorClient : V8InspectorClient, v8_inspector::V8Inspector::Channel { public: static JsV8InspectorClient* GetInstance(); + // Non-constructing variant for worker threads: returns nullptr until a + // main-thread entry point has created the client. + static JsV8InspectorClient* GetInstanceIfCreated(); + void init(); void connect(jobject connection); void scheduleBreak(); void disconnect(); void dispatchMessage(const std::string& message); + // Any thread. Rewrites source map urls and writes to the frontend + // socket; serializes against connect/disconnect. V8-free (safe to call + // from a worker thread with the main isolate unlocked). + void SendToFrontend(const std::string& message); + + // Runs on the websocket read thread. Returns true when the message was + // handled there (response, possibly empty when replies were already + // sent or none is needed, goes back to the socket); false routes the + // message through the normal main-thread dispatch queue. + bool handleMessageOnSocketThread(const std::string& message, std::string& response); + +#ifdef APPLICATION_IN_DEBUG + // Worker target management (Target domain, flat-session protocol). + // Register/Unregister run on the worker's own thread; SchedulePauseInWorker + // runs on the worker thread from a V8 interrupt. + void RegisterWorkerTarget(int workerId, WorkerInspectorClient* client); + void UnregisterWorkerTarget(int workerId); + void SchedulePauseInWorker(int workerId); +#endif + void registerModules(); // Overrides of V8Inspector::Channel @@ -60,9 +91,51 @@ class JsV8InspectorClient : V8InspectorClient, v8_inspector::V8Inspector::Channe static void InspectorIsConnectedGetterCallback(v8::Local property, const v8::PropertyCallbackInfo& info); - static JsV8InspectorClient* instance; + static std::atomic instance; static constexpr int contextGroupId = 1; + // Streams backing Network.loadNetworkResource responses, read by the + // frontend through IO.read/IO.close (how Chrome DevTools fetches source + // maps from the target). Accessed from the websocket read thread. + struct ResourceStream { + std::string data; + size_t offset = 0; + }; + + // Source map delivery to Chrome DevTools (Network.loadNetworkResource + + // IO domain). V8's inspector doesn't implement these embedder domains. + std::string HandleLoadNetworkResource(long long msgId, const std::string& url, const std::string& sessionId); + std::string HandleIORead(long long msgId, const std::string& handle, int size, const std::string& sessionId); + std::string HandleIOClose(long long msgId, const std::string& handle, const std::string& sessionId); + + std::map resourceStreams_; + std::mutex resourceStreamsMutex_; + int lastStreamId_ = 0; + std::atomic isPausedNestedLoop_{false}; + +#ifdef APPLICATION_IN_DEBUG + // Live worker inspectors, keyed by their flat-protocol sessionId + // ("NS_WORKER_"). Entries are added/removed from worker threads and + // read from the socket thread. + struct WorkerTarget { + int workerId; + WorkerInspectorClient* client; + bool announced = false; + }; + + void RouteToWorker(const std::string& sessionId, const std::string& method, + long long msgId, const std::string& message); + void AnnounceWorkerTargets(); + + std::map workerTargets_; + std::mutex workerTargetsMutex_; + bool autoAttach_ = false; // guarded by workerTargetsMutex_ +#endif + + // Lock order: workerTargetsMutex_ -> connectionMutex_ (registry walks + // send while holding the registry lock); never the other way around. + std::mutex connectionMutex_; + std::unique_ptr tracing_agent_; napi_env env; std::unique_ptr inspector_; @@ -75,7 +148,10 @@ class JsV8InspectorClient : V8InspectorClient, v8_inspector::V8Inspector::Channe jobject connection_; bool running_nested_loop_ : 1; bool terminated_ : 1; - bool isConnected_ : 1; + // Read from worker threads (target announcements); must not share a + // memory location with the bitfields above, which the main thread + // writes. + std::atomic isConnected_; // {N} specific helpers diff --git a/test-app/runtime/src/main/cpp/runtime/inspector/WorkerInspectorClient.cpp b/test-app/runtime/src/main/cpp/runtime/inspector/WorkerInspectorClient.cpp new file mode 100644 index 00000000..23e879c9 --- /dev/null +++ b/test-app/runtime/src/main/cpp/runtime/inspector/WorkerInspectorClient.cpp @@ -0,0 +1,354 @@ +#if defined(__V8__) && defined(APPLICATION_IN_DEBUG) + +#include "WorkerInspectorClient.h" + +#include +#include + +#include + +#include +#include +#include +#include + +#include "JsV8InspectorClient.h" +#include "Runtime.h" +#include "jsr.h" + +using namespace v8; +using namespace v8_inspector; + +namespace tns { + +namespace { + +StringView Make8BitStringView(const std::string& value) { + return StringView(reinterpret_cast(value.data()), value.size()); +} + +// Pure C++ (no V8 handles): legal from the Channel callbacks regardless of +// what scopes the inspector entered before calling them. +std::string ToUtf8String(const StringView& view) { + return v8_inspector::toString16(view).utf8(); +} + +} // namespace + +WorkerInspectorClient::WorkerInspectorClient(int workerId, napi_env env, ALooper* workerLooper, + const std::string& url) + : workerId_(workerId), + sessionId_("NS_WORKER_" + std::to_string(workerId)), + targetId_("ns-worker-" + std::to_string(workerId)), + url_(url), + env_(env), + isolate_(env->isolate), + workerLooper_(workerLooper) { + // Wakes the worker looper when CDP messages arrive on the socket thread; + // same mechanism as the worker's message inbox (ConcurrentQueue). + eventFd_ = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); + if (eventFd_ != -1 && workerLooper_ != nullptr && + ALooper_addFd(workerLooper_, eventFd_, ALOOPER_POLL_CALLBACK, ALOOPER_EVENT_INPUT, + WorkerInspectorClient::InspectorMessagesCallback, this) == 1) { + ALooper_acquire(workerLooper_); + } else { + if (eventFd_ != -1) { + close(eventFd_); + eventFd_ = -1; + } + workerLooper_ = nullptr; + } + + v8::Locker locker(isolate_); + Isolate::Scope isolate_scope(isolate_); + HandleScope handle_scope(isolate_); + Local context = env_->context(); + + inspector_ = V8Inspector::create(isolate_, this); + // Name the context after the worker script: the DevTools console context + // selector labels entries with the context's name (or its origin as a + // fallback) — with neither set the dropdown rows are blank and + // unselectable. + V8ContextInfo contextInfo(context, contextGroupId, Make8BitStringView(url_)); + contextInfo.origin = Make8BitStringView(url_); + inspector_->contextCreated(contextInfo); + context_.Reset(isolate_, context); +#ifdef __V8_10__ + session_ = inspector_->connect(contextGroupId, this, {}); +#else + session_ = inspector_->connect(contextGroupId, this, {}, + V8Inspector::ClientTrustLevel::kFullyTrusted); +#endif +} + +WorkerInspectorClient::~WorkerInspectorClient() { + dying_ = true; + + if (eventFd_ != -1) { + // Runs on the worker thread, so unregistering from its own looper is + // safe (same rule as ConcurrentQueue::Terminate). + ALooper_removeFd(workerLooper_, eventFd_); + close(eventFd_); + eventFd_ = -1; + ALooper_release(workerLooper_); + } + + v8::Locker locker(isolate_); + Isolate::Scope isolate_scope(isolate_); + HandleScope handle_scope(isolate_); + if (session_ != nullptr) { + session_->resume(); + session_.reset(); + } + inspector_.reset(); + context_.Reset(); +} + +int WorkerInspectorClient::InspectorMessagesCallback(int fd, int events, void* data) { + // Clear the eventfd counter first or the level-triggered looper spins. + uint64_t value; + read(fd, &value, sizeof(value)); + + static_cast(data)->DrainIncoming(); + return 1; +} + +void WorkerInspectorClient::PushMessage(const std::string& message) { + if (dying_) { + return; + } + + { + std::lock_guard lock(incomingMutex_); + incoming_.push(message); + } + + if (eventFd_ != -1) { + // Wakes an idle worker pumping its looper. While paused the looper is + // not pumping — the condition variable below wakes the nested pause + // loop instead, and the still-readable fd fires one (possibly empty) + // drain after resume. + uint64_t value = 1; + write(eventFd_, &value, sizeof(value)); + } + messageArrived_.notify_all(); +} + +std::string WorkerInspectorClient::PopMessage() { + std::lock_guard lock(incomingMutex_); + if (incoming_.empty()) { + return ""; + } + std::string message = incoming_.front(); + incoming_.pop(); + return message; +} + +void WorkerInspectorClient::DrainIncoming() { + std::string message; + while (!dying_ && !(message = this->PopMessage()).empty()) { + this->DispatchOne(message); + } + this->MaybeResetSession(); +} + +void WorkerInspectorClient::DispatchOne(const std::string& message) { + if (message == kResetSessionMessage) { + this->HandleResetRequest(); + return; + } + + if (session_ == nullptr) { + return; + } + + v8::Locker locker(isolate_); + Isolate::Scope isolate_scope(isolate_); + HandleScope handle_scope(isolate_); + session_->dispatchProtocolMessage(Make8BitStringView(message)); + isolate_->PerformMicrotaskCheckpoint(); +} + +void WorkerInspectorClient::HandleResetRequest() { + if (runningPauseLoop_.load(std::memory_order_acquire)) { + // We're inside session_->dispatchProtocolMessage somewhere up the stack — + // resume now (which exits the nested pause loop) and swap the session + // only once that stack has fully unwound, from DrainIncoming. + pendingReset_ = true; + { + v8::Locker locker(isolate_); + Isolate::Scope isolate_scope(isolate_); + HandleScope handle_scope(isolate_); + if (session_ != nullptr) { + session_->resume(); + } + } + if (eventFd_ != -1) { + uint64_t value = 1; + write(eventFd_, &value, sizeof(value)); + } + return; + } + + this->DoResetSession(); +} + +void WorkerInspectorClient::DoResetSession() { + v8::Locker locker(isolate_); + Isolate::Scope isolate_scope(isolate_); + HandleScope handle_scope(isolate_); + if (session_ != nullptr) { + session_->resume(); + session_.reset(); + } +#ifdef __V8_10__ + session_ = inspector_->connect(contextGroupId, this, {}); +#else + session_ = inspector_->connect(contextGroupId, this, {}, + V8Inspector::ClientTrustLevel::kFullyTrusted); +#endif +} + +void WorkerInspectorClient::MaybeResetSession() { + if (pendingReset_ && !runningPauseLoop_.load(std::memory_order_acquire) && !dying_) { + pendingReset_ = false; + this->DoResetSession(); + } +} + +void WorkerInspectorClient::runMessageLoopOnPause(int contextGroupId) { + if (runningPauseLoop_.load(std::memory_order_acquire) || dying_) { + return; + } + runningPauseLoop_.store(true, std::memory_order_release); + pauseTerminated_ = false; + + while (!pauseTerminated_ && !dying_) { + std::string message = this->PopMessage(); + bool shouldWait = message.empty(); + if (!shouldWait) { + this->DispatchOne(message); + } + + while (v8::platform::PumpMessageLoop(JSR::platform.get(), isolate_)) { + } + + if (shouldWait && !pauseTerminated_ && !dying_) { + std::unique_lock lock(messageArrivedMutex_); + messageArrived_.wait_for(lock, std::chrono::milliseconds(1)); + } + } + + runningPauseLoop_.store(false, std::memory_order_release); +} + +void WorkerInspectorClient::quitMessageLoopOnPause() { + pauseTerminated_ = true; +} + +void WorkerInspectorClient::NotifyTerminating() { + dying_ = true; + pauseTerminated_ = true; + messageArrived_.notify_all(); +} + +void WorkerInspectorClient::RequestPauseInterrupt() { + isolate_->RequestInterrupt( + [](Isolate* isolate, void* data) { + // Runs on the worker thread mid-JS. Teardown also happens on the + // worker thread, so the client either still exists or this resolves + // to nothing — re-resolve through the registry instead of capturing + // the pointer. + int workerId = static_cast(reinterpret_cast(data)); + JsV8InspectorClient* root = JsV8InspectorClient::GetInstanceIfCreated(); + if (root != nullptr) { + root->SchedulePauseInWorker(workerId); + } + }, + reinterpret_cast(static_cast(workerId_))); +} + +void WorkerInspectorClient::SchedulePauseFromInterrupt() { + if (session_ != nullptr) { + session_->schedulePauseOnNextStatement({}, {}); + } +} + +void WorkerInspectorClient::sendResponse(int callId, std::unique_ptr message) { + this->SendWrapped(ToUtf8String(message->string())); +} + +void WorkerInspectorClient::sendNotification(std::unique_ptr message) { + this->SendWrapped(ToUtf8String(message->string())); +} + +void WorkerInspectorClient::flushProtocolNotifications() { +} + +void WorkerInspectorClient::SendWrapped(const std::string& message) { + if (message.empty() || message[0] != '{') { + return; + } + + // Flat-session protocol: tag everything this session emits with its + // sessionId so the frontend routes it to the right child target. + std::string wrapped; + wrapped.reserve(message.size() + sessionId_.size() + 16); + wrapped += "{\"sessionId\":\""; + wrapped += sessionId_; + wrapped += "\""; + if (message.size() > 2) { + wrapped += ","; + } + wrapped.append(message, 1, std::string::npos); + + JsV8InspectorClient* root = JsV8InspectorClient::GetInstanceIfCreated(); + if (root != nullptr) { + root->SendToFrontend(wrapped); + } +} + +void WorkerInspectorClient::consoleLog(ConsoleAPIType method, + const std::vector>& args) { + if (inspector_ == nullptr) { + return; + } + + // Note, here we access private V8 API (mirrors + // JsV8InspectorClient::consoleLogCallback). + auto* impl = reinterpret_cast(inspector_.get()); + + Local stack = + StackTrace::CurrentStackTrace(isolate_, 1, StackTrace::StackTraceOptions::kDetailed); + std::unique_ptr stackImpl = impl->debugger()->createStackTrace(stack); + + Local context = context_.Get(isolate_); + const int contextId = V8ContextInfo::executionContextId(context); + +#ifdef __V8_13__ + v8::MemorySpan> argsSpan((v8::Local*) args.data(), + args.size()); + std::unique_ptr msg = V8ConsoleMessage::createForConsoleAPI( + context, contextId, contextGroupId, impl, this->currentTimeMS(), method, argsSpan, + String16{}, std::move(stackImpl)); +#else + std::unique_ptr msg = V8ConsoleMessage::createForConsoleAPI( + context, contextId, contextGroupId, impl, this->currentTimeMS(), method, args, String16{}, + std::move(stackImpl)); +#endif + + // Going through the message storage both reports to the session when the + // frontend has enabled the Runtime agent AND keeps the message for replay + // on Runtime.enable. Workers log most of their output (module top-level, + // early onmessage work) before DevTools attaches and enables the session; + // delivering straight to the runtime agent would silently drop all of it. + impl->ensureConsoleMessageStorage(contextGroupId)->addMessage(std::move(msg)); +} + +Local WorkerInspectorClient::ensureDefaultContextInGroup(int contextGroupId) { + return context_.Get(isolate_); +} + +} // namespace tns + +#endif // __V8__ && APPLICATION_IN_DEBUG diff --git a/test-app/runtime/src/main/cpp/runtime/inspector/WorkerInspectorClient.h b/test-app/runtime/src/main/cpp/runtime/inspector/WorkerInspectorClient.h new file mode 100644 index 00000000..014c6d6f --- /dev/null +++ b/test-app/runtime/src/main/cpp/runtime/inspector/WorkerInspectorClient.h @@ -0,0 +1,147 @@ +#ifndef WORKERINSPECTORCLIENT_H_ +#define WORKERINSPECTORCLIENT_H_ + +#if defined(__V8__) && defined(APPLICATION_IN_DEBUG) + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include "v8.h" +#include "v8-inspector.h" +#include "js_native_api.h" + +namespace tns { + +/* + * V8 inspector for a single worker isolate, exposed to Chrome DevTools as a + * child target ("Target.attachedToTarget") and addressed with flat-session + * CDP messages (a top-level "sessionId" field). One instance per worker, + * mirroring the iOS runtime's WorkerInspectorClient. + * + * Threading: constructed, dispatched into, and destroyed on the worker's own + * thread (V8's inspector is not thread-safe). Other threads interact only + * through PushMessage/NotifyTerminating/RequestPauseInterrupt. Incoming + * messages are queued and drained via an eventfd registered on the worker's + * ALooper (the same mechanism as the worker's message inbox); while paused, a + * nested loop on the worker thread pumps the same queue (the looper is NOT + * re-entered, so postMessage deliveries stay queued during a pause, matching + * Chrome's semantics). + * + * This is the napi (multi-engine hybrid) port: it takes the worker's napi_env + * and reaches the underlying v8::Isolate through env->isolate / env->context(), + * matching the fork's JsV8InspectorClient. The inspector itself is V8-only. + */ +class WorkerInspectorClient final : public v8_inspector::V8InspectorClient, + public v8_inspector::V8Inspector::Channel { + public: + // Worker thread, with the worker env's isolate locked and its context + // created. + WorkerInspectorClient(int workerId, napi_env env, ALooper* workerLooper, + const std::string& url); + ~WorkerInspectorClient() override; + + int WorkerId() const { + return workerId_; + } + const std::string& SessionId() const { + return sessionId_; + } + const std::string& TargetId() const { + return targetId_; + } + const std::string& Url() const { + return url_; + } + + // Any thread. Queues a CDP message (already stripped of routing concerns) + // and wakes the worker looper / a nested pause loop. + void PushMessage(const std::string& message); + + // Any thread. Unblocks a paused worker and makes it drop all inspector + // work; used by WorkerWrapper::Terminate together with the cooperative + // looper quit. + void NotifyTerminating(); + + // Any thread (with the worker isolate guaranteed alive). Schedules a pause + // at the next statement even if the worker is busy executing JS. + void RequestPauseInterrupt(); + + // Worker thread (from the interrupt requested above). + void SchedulePauseFromInterrupt(); + + // Any thread. True while the worker sits in its nested pause loop — used + // by the root client to skip the pause interrupt (it would only fire + // after resume, causing a spurious re-pause). + bool IsRunningPauseLoop() const { + return runningPauseLoop_.load(std::memory_order_acquire); + } + + // Worker thread. Mirrors JsV8InspectorClient::consoleLogCallback for this + // isolate. + void consoleLog(v8_inspector::ConsoleAPIType method, + const std::vector>& args); + + // Internal control message pushed by the root client on frontend + // reconnect; resumes the worker if paused and recreates its session. + static constexpr const char* kResetSessionMessage = "{\"__nsInternal\":\"resetSession\"}"; + + // Overrides of V8Inspector::Channel + void sendResponse(int callId, std::unique_ptr message) override; + void sendNotification(std::unique_ptr message) override; + void flushProtocolNotifications() override; + + // Overrides of V8InspectorClient + void runMessageLoopOnPause(int contextGroupId) override; + void quitMessageLoopOnPause() override; + + private: + static constexpr int contextGroupId = 1; + + static int InspectorMessagesCallback(int fd, int events, void* data); + + void DrainIncoming(); + std::string PopMessage(); + void DispatchOne(const std::string& message); + void HandleResetRequest(); + void DoResetSession(); + void MaybeResetSession(); + void SendWrapped(const std::string& message); + + v8::Local ensureDefaultContextInGroup(int contextGroupId) override; + + int workerId_; + std::string sessionId_; + std::string targetId_; + std::string url_; + napi_env env_; + v8::Isolate* isolate_; + ALooper* workerLooper_; + int eventFd_ = -1; + + std::unique_ptr inspector_; + std::unique_ptr session_; + v8::Persistent context_; + + std::queue incoming_; + std::mutex incomingMutex_; + std::mutex messageArrivedMutex_; + std::condition_variable messageArrived_; + + std::atomic dying_{false}; + std::atomic pauseTerminated_{false}; + std::atomic runningPauseLoop_{false}; // written on the worker thread only + bool pendingReset_ = false; // worker thread only +}; + +} // namespace tns + +#endif // __V8__ && APPLICATION_IN_DEBUG + +#endif /* WORKERINSPECTORCLIENT_H_ */ diff --git a/test-app/runtime/src/main/cpp/runtime/inspector/com_tns_AndroidJsV8Inspector.cpp b/test-app/runtime/src/main/cpp/runtime/inspector/com_tns_AndroidJsV8Inspector.cpp index b2ec52f7..1bc2602b 100644 --- a/test-app/runtime/src/main/cpp/runtime/inspector/com_tns_AndroidJsV8Inspector.cpp +++ b/test-app/runtime/src/main/cpp/runtime/inspector/com_tns_AndroidJsV8Inspector.cpp @@ -39,3 +39,21 @@ JNIEXPORT extern "C" void Java_com_tns_AndroidJsV8Inspector_dispatchMessage(JNIE JsV8InspectorClient::GetInstance()->dispatchMessage(message); #endif } + +JNIEXPORT extern "C" jstring Java_com_tns_AndroidJsV8Inspector_handleMessageOnSocketThread(JNIEnv* env, jobject instance, jstring jMessage) { +#ifdef APPLICATION_IN_DEBUG + try { + std::string message = tns::jstringToString(jMessage); + std::string response; + if (JsV8InspectorClient::GetInstance()->handleMessageOnSocketThread(message, response)) { + // Handled; an empty string means any replies were already sent. + return env->NewStringUTF(response.c_str()); + } + } catch (...) { + // must never propagate a native exception into the websocket thread + } +#endif + + // Not handled -> Java queues it to the main-thread dispatcher. + return nullptr; +} diff --git a/test-app/runtime/src/main/cpp/runtime/inspector/third_party/json.hpp b/test-app/runtime/src/main/cpp/runtime/inspector/third_party/json.hpp new file mode 100644 index 00000000..cd4924d9 --- /dev/null +++ b/test-app/runtime/src/main/cpp/runtime/inspector/third_party/json.hpp @@ -0,0 +1,25722 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + +/****************************************************************************\ + * Note on documentation: The source files contain links to the online * + * documentation of the public API at https://json.nlohmann.me. This URL * + * contains the most recent documentation and should also be applicable to * + * previous versions; documentation for deprecated functions is not * + * removed, but marked deprecated. See "Generate documentation" section in * + * file docs/README.md. * +\****************************************************************************/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#include // all_of, find, for_each +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO +#include // random_access_iterator_tag +#include // unique_ptr +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_DIAGNOSTIC_POSITIONS + #define JSON_DIAGNOSTIC_POSITIONS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_DIAGNOSTIC_POSITIONS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // nullptr_t +#include // exception +#if JSON_DIAGNOSTICS + #include // accumulate +#endif +#include // runtime_error +#include // to_string +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + + +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-License-Identifier: MIT + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + * SPDX-License-Identifier: CC0-1.0 + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif +#else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions (except those affecting ABI) +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// #include + + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +// if the user manually specified the used C++ version, this is skipped +#if !defined(JSON_HAS_CPP_26) && !defined(JSON_HAS_CPP_23) && !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus > 202302L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202302L) + #define JSON_HAS_CPP_26 + #define JSON_HAS_CPP_23 + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L) + #define JSON_HAS_CPP_23 + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has a syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifndef JSON_HAS_STATIC_RTTI + #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 + #define JSON_HAS_STATIC_RTTI 1 + #else + #define JSON_HAS_STATIC_RTTI 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow disabling exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow accessing some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer, \ + class BinaryType, \ + class CustomBaseClass> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1; + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT +@since version 3.11.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE +@since version 3.11.3 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT +@since version 3.11.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE +@since version 3.11.3 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + template::value, int> = 0> \ + void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +// inspired from https://stackoverflow.com/a/26745591 +// allows calling any std function as if (e.g., with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif + +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif + +#if JSON_HAS_THREE_WAY_COMPARISON + #include // partial_ordering +#endif + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 +*/ +#if JSON_HAS_THREE_WAY_COMPARISON + inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* +#else + inline bool operator<(const value_t lhs, const value_t rhs) noexcept +#endif +{ + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); +#if JSON_HAS_THREE_WAY_COMPARISON + if (l_index < order.size() && r_index < order.size()) + { + return order[l_index] <=> order[r_index]; // *NOPAD* + } + return std::partial_ordering::unordered; +#else + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +#endif +} + +// GCC selects the built-in operator< over an operator rewritten from +// a user-defined spaceship operator +// Clang, MSVC, and ICC select the rewritten candidate +// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) +#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + return std::is_lt(lhs <=> rhs); // *NOPAD* +} +#endif + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief replace all occurrences of a substring by another string + +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f + +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** + +@since version 2.0.0 +*/ +template +inline void replace_substring(StringType& s, const StringType& f, + const StringType& t) +{ + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find the first occurrence of f + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find the next occurrence of f + {} +} + +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) +{ + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +inline void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // size_t + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static JSON_INLINE_VARIABLE constexpr T value{}; +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // numeric_limits +#include // char_traits +#include // tuple +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L + #include // byte +#endif +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // random_access_iterator_tag + +// #include + +// #include + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); + +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); + +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector + + // #include + + + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN + + /*! + @brief default JSONSerializer template argument + + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; + + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> + class basic_json; + + /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document + /// @sa https://json.nlohmann.me/api/json_pointer/ + template + class json_pointer; + + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; + + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; + + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; + + NLOHMANN_JSON_NAMESPACE_END + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + +NLOHMANN_JSON_NAMESPACE_BEGIN +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ + +///////////// +// helpers // +///////////// + +// Note to maintainers: +// +// Every trait in this file expects a non-CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e., those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g., to_json(BasicJsonType&, const T&)) + +template struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; + +// used by exceptions create() member functions +// true_type for the pointer to possibly cv-qualified basic_json or std::nullptr_t +// false_type otherwise +template +struct is_basic_json_context : + std::integral_constant < bool, + is_basic_json::type>::type>::value + || std::is_same::value > +{}; + +////////////////////// +// json_ref helpers // +////////////////////// + +template +class json_ref; + +template +struct is_json_ref : std::false_type {}; + +template +struct is_json_ref> : std::true_type {}; + +////////////////////////// +// aliases for detected // +////////////////////////// + +template +using mapped_type_t = typename T::mapped_type; + +template +using key_type_t = typename T::key_type; + +template +using value_type_t = typename T::value_type; + +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + +template +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; + +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; + +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; + +///////////////// +// char_traits // +///////////////// + +// Primary template of char_traits calls std char_traits +template +struct char_traits : std::char_traits +{}; + +// Explicitly define char traits for unsigned char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = unsigned char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(std::char_traits::eof()); + } +}; + +// Explicitly define char traits for signed char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = signed char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(std::char_traits::eof()); + } +}; + +#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L +template<> +struct char_traits : std::char_traits +{ + using char_type = std::byte; + using int_type = uint64_t; + + static int_type to_int_type(char_type c) noexcept + { + return static_cast(std::to_integer(c)); + } + + static char_type to_char_type(int_type i) noexcept + { + return std::byte(static_cast(i)); + } + + static constexpr int_type eof() noexcept + { + return static_cast(std::char_traits::eof()); + } +}; +#endif + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B { }; +template +struct conjunction +: std::conditional(B::value), conjunction, B>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g., Clang 3.5 or GCC 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to use it in this library. + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + is_constructible::value && + is_constructible::value; +}; + +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; + +template +struct is_constructible_object_type_impl : std::false_type {}; + +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + static constexpr bool value = + (is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; + +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; + +template +struct is_compatible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_constructible_string_type +{ + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + + static constexpr auto value = + conjunction < + is_constructible, + is_detected_exact>::value; +}; + +template +struct is_compatible_array_type_impl : std::false_type {}; + +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < + is_detected::value&& + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> +{ + static constexpr bool value = + is_constructible>::value; +}; + +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; + +template +struct is_constructible_array_type_impl : std::false_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& +is_complete_type < +detected_t>::value >> +{ + using value_type = range_value_t; + + static constexpr bool value = + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; +}; + +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; + +template +struct is_compatible_type_impl: std::false_type {}; + +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; + +template +struct is_compatible_type + : is_compatible_type_impl {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; + +template +struct is_json_iterator_of : std::false_type {}; + +template +struct is_json_iterator_of : std::true_type {}; + +template +struct is_json_iterator_of : std::true_type +{}; + +// checks if a given type T is a template specialization of Primary +template