V8 Coverage Report
Files covered Lines Remaining
. / sqlmath.mjs
100.00 %
1843 / 1843

0 / 1843
    1.      1// MIT License
    2.      1//
    3.      1// Copyright (c) 2021 Kai Zhu
    4.      1//
    5.      1// Permission is hereby granted, free of charge, to any person obtaining a copy
    6.      1// of this software and associated documentation files (the "Software"), to deal
    7.      1// in the Software without restriction, including without limitation the rights
    8.      1// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    9.      1// copies of the Software, and to permit persons to whom the Software is
   10.      1// furnished to do so, subject to the following conditions:
   11.      1//
   12.      1// The above copyright notice and this permission notice shall be included in
   13.      1// all copies or substantial portions of the Software.
   14.      1//
   15.      1// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   16.      1// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   17.      1// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   18.      1// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   19.      1// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   20.      1// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   21.      1// SOFTWARE.
   22.      1
   23.      1
   24.      1/*jslint beta, bitwise, name, node*/
   25.      1/*global FinalizationRegistry*/
   26.      1"use strict";
   27.      1
   28.      1const JSBATON_ARGC = 8;
   29.      1const JSBATON_OFFSET_ALL = 256;
   30.      1const JSBATON_OFFSET_ARGV = 128;
   31.      1const JSBATON_OFFSET_BUFV = 192;
   32.      1// const JSBATON_OFFSET_ERRMSG = 48;
   33.      1const JSBATON_OFFSET_FUNCNAME = 8;
   34.      1const JS_MAX_SAFE_INTEGER = 0x1f_ffff_ffff_ffff;
   35.      1const JS_MIN_SAFE_INTEGER = -0x1f_ffff_ffff_ffff;
   36.      1const SIZEOF_BLOB_MAX = 1_000_000_000;
   37.      1// const SIZEOF_ERRMSG = 80;
   38.      1const SIZEOF_FUNCNAME = 16;
   39.      1const SQLITE_DATATYPE_BLOB = 0x04;
   40.      1const SQLITE_DATATYPE_EXTERNALBUFFER = 0x71;
   41.      1const SQLITE_DATATYPE_FLOAT = 0x02;
   42.      1const SQLITE_DATATYPE_INTEGER = 0x01;
   43.      1const SQLITE_DATATYPE_INTEGER_0 = 0x00;
   44.      1const SQLITE_DATATYPE_INTEGER_1 = 0x21;
   45.      1const SQLITE_DATATYPE_NULL = 0x05;
   46.      1const SQLITE_DATATYPE_TEXT = 0x03;
   47.      1const SQLITE_DATATYPE_TEXT_0 = 0x13;
   48.      1const SQLITE_RESPONSETYPE_LASTBLOB = 1;
   49.      1const SQLITE_RESPONSETYPE_LASTVALUE = 2;
   50.      1
   51.      1const FILENAME_DBTMP = "/tmp/__dbtmp1"; //jslint-ignore-line
   52.      1
   53.      1const LGBM_DTYPE_FLOAT32 = 0;   /* float32 (single precision float)*/
   54.      1const LGBM_DTYPE_FLOAT64 = 1;   /* float64 (double precision float)*/
   55.      1const LGBM_DTYPE_INT32 = 2;     /* int32*/
   56.      1const LGBM_DTYPE_INT64 = 3;     /* int64*/
   57.      1const LGBM_FEATURE_IMPORTANCE_GAIN = 1; /* Gain type of feature importance*/
   58.      1const LGBM_FEATURE_IMPORTANCE_SPLIT = 0;/* Split type of feature importance*/
   59.      1const LGBM_MATRIX_TYPE_CSC = 1; /* CSC sparse matrix type*/
   60.      1const LGBM_MATRIX_TYPE_CSR = 0; /* CSR sparse matrix type*/
   61.      1const LGBM_PREDICT_CONTRIB = 3; /* Predict feature contributions (SHAP values)*/
   62.      1const LGBM_PREDICT_LEAF_INDEX = 2;      /* Predict leaf index*/
   63.      1const LGBM_PREDICT_NORMAL = 0;  /* Normal prediction w/ transform (if needed)*/
   64.      1const LGBM_PREDICT_RAW_SCORE = 1;       /* Predict raw score*/
   65.      1const SQLITE_OPEN_AUTOPROXY = 0x00000020;       /* VFS only */
   66.      1const SQLITE_OPEN_CREATE = 0x00000004;          /* Ok for sqlite3_open_v2() */
   67.      1const SQLITE_OPEN_DELETEONCLOSE = 0x00000008;   /* VFS only */
   68.      1const SQLITE_OPEN_EXCLUSIVE = 0x00000010;       /* VFS only */
   69.      1const SQLITE_OPEN_FULLMUTEX = 0x00010000;       /* Ok for sqlite3_open_v2() */
   70.      1const SQLITE_OPEN_MAIN_DB = 0x00000100;         /* VFS only */
   71.      1const SQLITE_OPEN_MAIN_JOURNAL = 0x00000800;    /* VFS only */
   72.      1const SQLITE_OPEN_MEMORY = 0x00000080;          /* Ok for sqlite3_open_v2() */
   73.      1const SQLITE_OPEN_NOFOLLOW = 0x01000000;        /* Ok for sqlite3_open_v2() */
   74.      1const SQLITE_OPEN_NOMUTEX = 0x00008000;         /* Ok for sqlite3_open_v2() */
   75.      1const SQLITE_OPEN_PRIVATECACHE = 0x00040000;    /* Ok for sqlite3_open_v2() */
   76.      1const SQLITE_OPEN_READONLY = 0x00000001;        /* Ok for sqlite3_open_v2() */
   77.      1const SQLITE_OPEN_READWRITE = 0x00000002;       /* Ok for sqlite3_open_v2() */
   78.      1const SQLITE_OPEN_SHAREDCACHE = 0x00020000;     /* Ok for sqlite3_open_v2() */
   79.      1const SQLITE_OPEN_SUBJOURNAL = 0x00002000;      /* VFS only */
   80.      1const SQLITE_OPEN_SUPER_JOURNAL = 0x00004000;   /* VFS only */
   81.      1const SQLITE_OPEN_TEMP_DB = 0x00000200;         /* VFS only */
   82.      1const SQLITE_OPEN_TEMP_JOURNAL = 0x00001000;    /* VFS only */
   83.      1const SQLITE_OPEN_TRANSIENT_DB = 0x00000400;    /* VFS only */
   84.      1const SQLITE_OPEN_URI = 0x00000040;             /* Ok for sqlite3_open_v2() */
   85.      1const SQLITE_OPEN_WAL = 0x00080000;             /* VFS only */
   86.      1
   87.      1let IS_BROWSER;
   88.      1let cModule;
   89.      1let cModulePath;
   90.      1let consoleError = console.error;
   91.      1let dbFinalizationRegistry;
   92.      1// init debugInline
   93.      1let debugInline = (function () {
   94.      3    let __consoleError = function () {
   95.      3        return;
   96.      3    };
   97.      1    function debug(...argv) {
   98.      1
   99.      1// This function will print <argv> to stderr and then return <argv>[0].
  100.      1
  101.      1        __consoleError("\n\ndebugInline");
  102.      1        __consoleError(...argv);
  103.      1        __consoleError("\n");
  104.      1        return argv[0];
  105.      1    }
  106.      1    debug(); // Coverage-hack.
  107.      1    __consoleError = console.error; //jslint-ignore-line
  108.      1    return debug;
  109.      1}());
  110.      1let moduleChildProcess;
  111.      1let moduleChildProcessSpawn;
  112.      1let moduleCrypto;
  113.      1let moduleFs;
  114.      1let moduleFsInitResolveList;
  115.      1let modulePath;
  116.      1let moduleUrl;
  117.      1let {
  118.      1    npm_config_mode_debug,
  119.      1    npm_config_mode_setup,
  120.      1    npm_config_mode_test
  121.      1} = typeof process === "object" && process?.env;
  122.      1let sqlMessageDict = {}; // dict of web-worker-callbacks
  123.      1let sqlMessageId = 0;
  124.      1let sqlWorker;
  125.      1let version = "v2025.5.31";
  126.      1
  127.     88async function assertErrorThrownAsync(asyncFunc, regexp) {
  128.     88
  129.     88// This function will assert calling <asyncFunc> throws an error.
  130.     88
  131.     88    let err;
  132.     88    try {
  133.      1        await asyncFunc();
  134.     87    } catch (errCaught) {
  135.     87        err = errCaught;
  136.     87    }
  137.     88    assertOrThrow(err, "No error thrown.");
  138.     88    assertOrThrow(
  139.     85        !regexp || new RegExp(regexp).test(err.message),
  140.     88        err
  141.     88    );
  142.     88}
  143.      1
  144.  14292function assertInt64(val) {
  145.  14292    // This function will assert <val> is within range of c99-signed-long-long.
  146.  14292    val = BigInt(val);
  147.  14292    if (!(
  148.  14285        -9_223_372_036_854_775_808n <= val && val <= 9_223_372_036_854_775_807n
  149.     14    )) {
  150.     14        throw new Error(
  151.     14            `integer ${val} outside signed-64-bit inclusive-range`
  152.     14            + " -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807"
  153.     14        );
  154.     14    }
  155.  14292}
  156.      1
  157.   4929function assertJsonEqual(aa, bb, message) {
  158.   4929
  159.   4929// This function will assert JSON.stringify(<aa>) === JSON.stringify(<bb>).
  160.   4929
  161.   4929    aa = JSON.stringify(objectDeepCopyWithKeysSorted(aa), undefined, 1);
  162.   4929    bb = JSON.stringify(objectDeepCopyWithKeysSorted(bb), undefined, 1);
  163.      3    if (aa !== bb) {
  164.      3        throw new Error(
  165.      3            "\n" + aa + "\n!==\n" + bb
  166.      3            + (
  167.      3                typeof message === "string"
  168.      3                ? " - " + message
  169.      3                : message
  170.      3                ? " - " + JSON.stringify(message)
  171.      3                : ""
  172.      3            )
  173.      3        );
  174.      3    }
  175.   4929}
  176.      1
  177.      4function assertNumericalEqual(aa, bb, message) {
  178.      4
  179.      4// This function will assert aa - bb <= Number.EPSILON.
  180.      4
  181.      4    assertOrThrow(aa, "value cannot be 0 or falsy");
  182.      2    if (!(Math.abs((aa - bb) / Math.max(aa, bb)) <= 256 * Number.EPSILON)) {
  183.      2        throw new Error(
  184.      2            JSON.stringify(aa) + " != " + JSON.stringify(bb) + (
  185.      2                message
  186.      2                ? " - " + message
  187.      2                : ""
  188.      2            )
  189.      2        );
  190.      2    }
  191.      4}
  192.      1
  193.  48083function assertOrThrow(condition, message) {
  194.  48083
  195.  48083// This function will throw <message> if <condition> is falsy.
  196.  48083
  197.     72    if (!condition) {
  198.     72        throw (
  199.     72            (!message || typeof message === "string")
  200.     72            ? new Error(String(message).slice(0, 2048))
  201.     72            : message
  202.     72        );
  203.     72    }
  204.  48083}
  205.      1
  206.     15async function childProcessSpawn2(command, args, option) {
  207.     15
  208.     15// This function will run child_process.spawn as a promise.
  209.     15
  210.     15    return await new Promise(function (resolve, reject) {
  211.     15        let bufList = [[], [], []];
  212.     15        let child;
  213.     15        let {
  214.     15            modeCapture,
  215.     15            modeDebug,
  216.     15            stdio
  217.     15        } = option;
  218.      1        if (modeDebug) {
  219.      1            consoleError(
  220.      1                `childProcessSpawn2 - ${command} ${JSON.stringify(args)}`
  221.      1            );
  222.      1        }
  223.     15        child = moduleChildProcessSpawn(
  224.     15            command,
  225.     15            args,
  226.     15            Object.assign({}, option, {
  227.     15                stdio: [
  228.     15                    "ignore",
  229.     15                    (
  230.     15                        modeCapture
  231.      1                        ? "pipe"
  232.     14                        : stdio[1]
  233.     15                    ),
  234.     15                    (
  235.     15                        modeCapture
  236.      1                        ? "pipe"
  237.     14                        : stdio[2]
  238.     15                    )
  239.     15                ]
  240.     15            })
  241.     15        );
  242.      1        if (modeCapture) {
  243.      1            [
  244.      1                child.stdin, child.stdout, child.stderr
  245.      3            ].forEach(function (pipe, ii) {
  246.      1                if (ii === 0) {
  247.      1                    return;
  248.      2                }
  249.      2                pipe.on("data", function (chunk) {
  250.      2                    bufList[ii].push(chunk);
  251.      2                    if (stdio[ii] !== "ignore") {
  252.      2                        switch (ii) {
  253.      2                        case 1:
  254.      2                            process.stdout.write(chunk);
  255.      2                            break;
  256.      2                        case 2:
  257.      2                            process.stderr.write(chunk);
  258.      2                            break;
  259.      2                        }
  260.      2                    }
  261.      2                });
  262.      2            });
  263.      1        }
  264.     15        child.on("exit", function (exitCode) {
  265.     15            let resolve0 = resolve;
  266.     15            let stderr;
  267.     15            let stdout;
  268.     15            // coverage-hack
  269.     15            if (exitCode || npm_config_mode_test) {
  270.     15                resolve = reject;
  271.     15            }
  272.     15            // coverage-hack
  273.     15            if (npm_config_mode_test) {
  274.     15                resolve = resolve0;
  275.     15            }
  276.     30            [stdout, stderr] = bufList.slice(1).map(function (buf) {
  277.     30                return (
  278.     30                    typeof modeCapture === "string"
  279.      2                    ? Buffer.concat(buf).toString(modeCapture)
  280.     28                    : Buffer.concat(buf)
  281.     30                );
  282.     30            });
  283.     15            resolve({exitCode, stderr, stdout});
  284.     15        });
  285.     15    });
  286.     15
  287.     15}
  288.      1
  289.      7async function ciBuildExt({
  290.      7    modeSkip,
  291.      7    process
  292.      7}) {
  293.      7
  294.      7// This function will build sqlmath from c.
  295.      7
  296.      7    let option;
  297.      7    option = {
  298.      7        binNodegyp: modulePath.resolve(
  299.      7            modulePath.dirname(process.execPath || ""),
  300.      7            "node_modules/npm/node_modules/node-gyp/bin/node-gyp.js"
  301.      7        ).replace("/bin/node_modules/", "/lib/node_modules/"),
  302.      7        isWin32: process.platform === "win32",
  303.      7        modeDebug: npm_config_mode_debug,
  304.      7        modeSkip,
  305.      7        process
  306.      7    };
  307.      7    await ciBuildExt2NodejsBuild(option);
  308.      7}
  309.      1
  310.      7async function ciBuildExt1NodejsConfigure({
  311.      7    binNodegyp,
  312.      7    modeDebug
  313.      7}) {
  314.      7
  315.      7// This function will setup posix/win32 env for building c-extension.
  316.      7
  317.      7    let cflagWallList = [];
  318.      7    let cflagWnoList = [];
  319.      7    String(
  320.      7        await fsReadFileUnlessTest(".ci.sh", "utf8", (`
  321.      7SQLMATH_CFLAG_WALL_LIST=" \\
  322.      7"
  323.      7SQLMATH_CFLAG_WNO_LIST=" \\
  324.      7"
  325.      7        `))
  326.      7    ).replace((
  327.      7        /(SQLMATH_CFLAG_WALL_LIST|SQLMATH_CFLAG_WNO_LIST)=" \\([\S\s]*?)"/g
  328.     14    ), function (ignore, cflagType, cflagList) {
  329.     14        cflagList = cflagList.split(/[\s\\]/).filter(noop);
  330.     14        switch (cflagType) {
  331.      7        case "SQLMATH_CFLAG_WALL_LIST":
  332.      7            cflagWallList = cflagList;
  333.      7            break;
  334.      7        case "SQLMATH_CFLAG_WNO_LIST":
  335.      7            cflagWnoList = cflagList;
  336.      7            break;
  337.     14        }
  338.     14        return "";
  339.     14    });
  340.      7    consoleError(`ciBuildExt1Nodejs - configure binding.gyp`);
  341.      7    await fsWriteFileUnlessTest("binding.gyp", JSON.stringify({
  342.      7        "target_defaults": {
  343.      7            "cflags": cflagWnoList,
  344.      7// https://github.com/nodejs/node-gyp/blob/v9.3.1/gyp/pylib/gyp/MSVSSettings.py
  345.      7            "msvs_settings": {
  346.      7                "VCCLCompilerTool": {
  347.      7                    "WarnAsError": 1,
  348.      7                    "WarningLevel": 2
  349.      7                }
  350.      7            },
  351.      7            "xcode_settings": {
  352.      7                "OTHER_CFLAGS": cflagWnoList
  353.      7            }
  354.      7        },
  355.      7        "targets": [
  356.      7            {
  357.      7                "defines": [
  358.      7                    "SRC_SQLITE_BASE_C2",
  359.      7                    "SRC_ZLIB_C2"
  360.      7                ],
  361.      7                "sources": [
  362.      7                    "sqlmath_external_sqlite.c",
  363.      7                    "sqlmath_external_zlib.c"
  364.      7                ],
  365.      7                "target_name": "SRC_SQLITE_BASE",
  366.      7                "type": "static_library"
  367.      7            },
  368.      7            {
  369.      7                "cflags": cflagWallList,
  370.      7                "defines": [
  371.      7                    "SRC_SQLMATH_BASE_C2",
  372.      7                    "SRC_SQLMATH_CUSTOM_C2"
  373.      7                ],
  374.      7                "msvs_settings": {
  375.      7                    "VCCLCompilerTool": {
  376.      7                        "WarnAsError": 1,
  377.      7                        "WarningLevel": 4
  378.      7                    }
  379.      7                },
  380.      7                "sources": [
  381.      7                    "sqlmath_base.c",
  382.      7                    "sqlmath_custom.c"
  383.      7                ],
  384.      7                "target_name": "SRC_SQLMATH_CUSTOM",
  385.      7                "type": "static_library",
  386.      7                "xcode_settings": {
  387.      7                    "OTHER_CFLAGS": cflagWallList
  388.      7                }
  389.      7            },
  390.      7            {
  391.      7                "cflags": cflagWallList,
  392.      7                "defines": [
  393.      7                    "SRC_SQLMATH_NODEJS_C2"
  394.      7                ],
  395.      7                "dependencies": [
  396.      7                    "SRC_SQLITE_BASE",
  397.      7                    "SRC_SQLMATH_CUSTOM"
  398.      7                ],
  399.      7                "msvs_settings": {
  400.      7                    "VCCLCompilerTool": {
  401.      7                        "WarnAsError": 1,
  402.      7                        "WarningLevel": 4
  403.      7                    }
  404.      7                },
  405.      7                "sources": [
  406.      7                    "sqlmath_base.c"
  407.      7                ],
  408.      7                "target_name": "binding",
  409.      7                "xcode_settings": {
  410.      7                    "OTHER_CFLAGS": cflagWallList
  411.      7                }
  412.      7            },
  413.      7            {
  414.      7                "defines": [
  415.      7                    "SRC_SQLITE_SHELL_C2"
  416.      7                ],
  417.      7                "dependencies": [
  418.      7                    "SRC_SQLITE_BASE",
  419.      7                    "SRC_SQLMATH_CUSTOM"
  420.      7                ],
  421.      7                "sources": [
  422.      7                    "sqlmath_external_sqlite.c"
  423.      7                ],
  424.      7                "target_name": "shell",
  425.      7                "type": "executable"
  426.      7            }
  427.      7        ]
  428.      7    }, undefined, 4) + "\n");
  429.      7    await childProcessSpawn2(
  430.      7        "sh",
  431.      7        [
  432.      7            "-c",
  433.      7            (`
  434.      7(set -e
  435.      7    # node "${binNodegyp}" clean
  436.      7    node "${binNodegyp}" configure
  437.      7)
  438.      7            `)
  439.      7        ],
  440.      7        {modeDebug, stdio: ["ignore", 1, 2]}
  441.      7    );
  442.      7}
  443.      1
  444.      7async function ciBuildExt2NodejsBuild({
  445.      7    binNodegyp,
  446.      7    modeDebug
  447.      7}) {
  448.      7
  449.      7// This function will archive <fileObj> into <fileLib>
  450.      7
  451.      7    if (!noop(
  452.      7        await fsExistsUnlessTest(cModulePath)
  453.      7    )) {
  454.      7        await ciBuildExt1NodejsConfigure({
  455.      7            binNodegyp,
  456.      7            modeDebug
  457.      7        });
  458.      7    }
  459.      7    consoleError(
  460.      7        `ciBuildExt2Nodejs - linking lib ${modulePath.resolve(cModulePath)}`
  461.      7    );
  462.      7    await childProcessSpawn2(
  463.      7        "sh",
  464.      7        [
  465.      7            "-c",
  466.      7            (`
  467.      7(set -e
  468.      7    # rebuild binding
  469.      7    rm -rf build/Release/obj/SRC_SQLMATH_CUSTOM/
  470.      7    node "${binNodegyp}" build --release
  471.      7    mv build/Release/binding.node "${cModulePath}"
  472.      7    if [ "${process.platform}" = "win32" ]
  473.      7    then
  474.      7        mv build/Release/shell \
  475.      7            "_sqlmath.shell_${process.platform}_${process.arch}.exe"
  476.      7    else
  477.      7        mv build/Release/shell \
  478.      7            "_sqlmath.shell_${process.platform}_${process.arch}"
  479.      7    fi
  480.      7)
  481.      7            `)
  482.      7        ],
  483.      7        {modeDebug, stdio: ["ignore", 1, 2]}
  484.      7    );
  485.      7}
  486.      1
  487.   3979async function dbCallAsync(baton, argList, mode) {
  488.   3979
  489.   3979// This function will call c-function dbXxx() with given <funcname>
  490.   3979// and return [<baton>, ...argList].
  491.   3979
  492.   3979    let db;
  493.   3979    let errStack;
  494.   3979    let funcname;
  495.   3979    let id;
  496.   3979    let result;
  497.   3979    let timeElapsed;
  498.   3979    // If argList contains <db>, then mark it as busy.
  499.   1931    if (mode === "modeDb") {
  500.   1931        // init db
  501.   1931        db = argList[0];
  502.   1931        assertOrThrow(
  503.   1931            db.busy >= 0,
  504.   1931            `dbCallAsync - invalid db.busy = ${db.busy}`
  505.   1931        );
  506.   1931        db.ii = (db.ii + 1) % db.connPool.length;
  507.   1931        db.ptr = db.connPool[db.ii][0];
  508.   1931        // increment db.busy
  509.   1931        db.busy += 1;
  510.   1931        try {
  511.   1931            return await dbCallAsync(baton, [db.ptr, ...argList.slice(1)]);
  512.   1931        } finally {
  513.   1931            // decrement db.busy
  514.   1931            db.busy -= 1;
  515.   1931            assertOrThrow(
  516.   1931                db.busy >= 0,
  517.   1931                `dbCallAsync - invalid db.busy = ${db.busy}`
  518.   1931            );
  519.   1931        }
  520.   2048    }
  521.   2048    // copy argList to avoid side-effect
  522.   2048    argList = [...argList];
  523.   2048    assertOrThrow(
  524.   2048        argList.length <= JSBATON_ARGC,
  525.   2048        `dbCallAsync - argList.length must be less than than ${JSBATON_ARGC}`
  526.   2048    );
  527.   2048    // pad argList to length JSBATON_ARGC
  528.   6375    while (argList.length < JSBATON_ARGC) {
  529.   6375        argList.push(0n);
  530.   6375    }
  531.   2048    // serialize js-value to c-value
  532.  16246    argList = argList.map(function (val, argi) {
  533.  16245        if (val === null || val === undefined) {
  534.   2048            val = 0;
  535.   2048        }
  536.  16246        switch (typeof val) {
  537.   8232        case "bigint":
  538.  10151        case "boolean":
  539.  14260        case "number":
  540.  14260            // check for min/max safe-integer
  541.  14260            assertOrThrow(
  542.  14260                (
  543.  14260                    (JS_MIN_SAFE_INTEGER <= val && val <= JS_MAX_SAFE_INTEGER)
  544.  14260                    || typeof val === "bigint"
  545.  14260                ),
  546.  14260                (
  547.  14260                    "dbCallAsync - "
  548.  14260                    + "non-bigint-integer must be within inclusive-range"
  549.  14260                    + ` ${JS_MIN_SAFE_INTEGER} to ${JS_MAX_SAFE_INTEGER}`
  550.  14260                )
  551.  14260            );
  552.  14260            val = BigInt(val);
  553.  14260            assertInt64(val);
  554.  14260            baton.setBigInt64(JSBATON_OFFSET_ARGV + argi * 8, val, true);
  555.  14260            return val;
  556.  16246        // case "object":
  557.  16246        //     break;
  558.   2048        case "string":
  559.   2048            baton = jsbatonSetValue(baton, argi, (
  560.   2048                val.endsWith("\u0000")
  561.   2048                ? val
  562.   2048                // append null-terminator to string
  563.   2048                : val + "\u0000"
  564.   2048            ));
  565.   2048            return;
  566.   2048        }
  567.   2048        assertOrThrow(
  568.   2048            !ArrayBuffer.isView(val) || val.byteOffset === 0,
  569.  16246            (
  570.  16246                "dbCallAsync - argList cannot contain arraybuffer-views"
  571.  16246                + " with non-zero byteOffset"
  572.  16246            )
  573.  16246        );
  574.   2048        if (isExternalBuffer(val)) {
  575.   2048            return val;
  576.   2048        }
  577.   2048        throw new Error(`dbCallAsync - invalid arg-type "${typeof val}"`);
  578.   2048    });
  579.   2048    // assert byteOffset === 0
  580.  18225    [baton, ...argList].forEach(function (arg) {
  581.   2048        assertOrThrow(!ArrayBuffer.isView(arg) || arg.byteOffset === 0, arg);
  582.  18225    });
  583.   2048    // extract funcname
  584.   2048    funcname = new TextDecoder().decode(
  585.   2048        new DataView(baton.buffer, JSBATON_OFFSET_FUNCNAME, SIZEOF_FUNCNAME)
  586.   2048    ).replace((/\u0000/g), "");
  587.   2048    // preserve stack-trace
  588.   2048    errStack = new Error().stack.replace((/.*$/m), "");
  589.   2048    try {
  590.   2048
  591.   2048// Dispatch to nodejs-napi.
  592.   2048
  593.   2048        if (!IS_BROWSER) {
  594.   2023            await cModule._jspromiseCreate(baton.buffer, argList, funcname);
  595.   2023            // prepend baton to argList
  596.   2023            return [baton, ...argList];
  597.   2023        }
  598.      2
  599.      2// Dispatch to web-worker.
  600.      2
  601.      2        // increment sqlMessageId
  602.      2        sqlMessageId += 1;
  603.      2        id = sqlMessageId;
  604.      2        // postMessage to web-worker
  605.      2        sqlWorker.postMessage(
  606.      2            {
  607.      2                FILENAME_DBTMP,
  608.      2                JSBATON_OFFSET_ALL,
  609.      2                JSBATON_OFFSET_BUFV,
  610.      2                argList,
  611.      2                baton,
  612.      2                funcname,
  613.      2                id
  614.      2            },
  615.      2            // transfer arraybuffer without copying
  616.      2            [baton.buffer, ...argList.filter(isExternalBuffer)]
  617.      2        );
  618.      2        // init timeElapsed
  619.      2        timeElapsed = Date.now();
  620.      2        // await result from web-worker
  621.      2        result = await new Promise(function (resolve) {
  622.      2            sqlMessageDict[id] = resolve;
  623.      2        });
  624.      2        // cleanup sqlMessageDict
  625.      2        delete sqlMessageDict[id];
  626.      2        // debug slow postMessage
  627.      2        timeElapsed = Date.now() - timeElapsed;
  628.      2        if (timeElapsed > 500 || funcname === "testTimeElapsed") {
  629.      1            consoleError(
  630.      1                "sqlMessagePost - "
  631.      1                + JSON.stringify({funcname, timeElapsed})
  632.      1                + errStack
  633.      1            );
  634.      2        }
  635.      2        assertOrThrow(!result.errmsg, result.errmsg);
  636.      2        // prepend baton to argList
  637.      2        return [result.baton, ...result.argList];
  638.     55    } catch (err) {
  639.     55        err.stack += errStack;
  640.     55        assertOrThrow(undefined, err);
  641.     55    }
  642.   3979}
  643.      1
  644.      3async function dbCloseAsync(db) {
  645.      3
  646.      3// This function will close sqlite-database-connection <db>.
  647.      3
  648.      3    // prevent segfault - do not close db if actions are pending
  649.      3    assertOrThrow(
  650.      3        db.busy === 0,
  651.      3        `dbCloseAsync - cannot close db with ${db.busy} actions pending`
  652.      3    );
  653.      3    // cleanup connPool
  654.      1    await Promise.all(db.connPool.map(async function (ptr) {
  655.      1        let val = ptr[0];
  656.      1        ptr[0] = 0n;
  657.      1        await dbCallAsync(jsbatonCreate("_dbClose"), [val, db.filename]);
  658.      1    }));
  659.      1}
  660.      1
  661.     58function dbExecAndReturnLastBlob({
  662.     58    bindList = [],
  663.     58    db,
  664.     58    sql
  665.     58}) {
  666.     58
  667.     58// This function will exec <sql> in <db>,
  668.     58// and return last-value retrieved from execution as raw blob/buffer.
  669.     58
  670.     58    return dbExecAsync({
  671.     58        bindList,
  672.     58        db,
  673.     58        responseType: "lastblob",
  674.     58        sql
  675.     58    });
  676.     58}
  677.      1
  678.    115async function dbExecAndReturnLastRow({
  679.    115    bindList = [],
  680.    115    db,
  681.    115    sql
  682.    115}) {
  683.    115
  684.    115// This function will exec <sql> in <db>,
  685.    115// and return last-row or empty-object.
  686.    115
  687.    101    let result = await dbExecAsync({bindList, db, sql});
  688.    101    result = result[result.length - 1] || [];
  689.      1    result = result[result.length - 1] || {};
  690.    115    return result;
  691.    115}
  692.      1
  693.     65async function dbExecAndReturnLastTable({
  694.     65    bindList = [],
  695.     65    db,
  696.     65    sql
  697.     65}) {
  698.     65
  699.     65// This function will exec <sql> in <db>,
  700.     65// and return last-table or empty-list.
  701.     65
  702.     65    let result = await dbExecAsync({bindList, db, sql});
  703.      1    result = result[result.length - 1] || [];
  704.     65    return result;
  705.     65}
  706.      1
  707.   1184function dbExecAndReturnLastValue({
  708.   1184    bindList = [],
  709.   1184    db,
  710.   1184    sql
  711.   1184}) {
  712.   1184
  713.   1184// This function will exec <sql> in <db>,
  714.   1184// and return last-json-value.
  715.   1184
  716.   1184    return dbExecAsync({
  717.   1184        bindList,
  718.   1184        db,
  719.   1184        responseType: "lastvalue",
  720.   1184        sql
  721.   1184    });
  722.   1184}
  723.      1
  724.   1928async function dbExecAsync({
  725.   1928    bindList = [],
  726.   1928    db,
  727.   1928    responseType,
  728.   1928    sql
  729.   1928}) {
  730.   1928
  731.   1928// This function will exec <sql> in <db> and return <result>.
  732.   1928
  733.   1928    let baton = jsbatonCreate("_dbExec");
  734.   1928    let bindByKey = !Array.isArray(bindList);
  735.   1928    let bufi = [0];
  736.   1928    let referenceList = [];
  737.   1928    let result;
  738.   1235    if (bindByKey) {
  739.   1347        Object.entries(bindList).forEach(function ([key, val]) {
  740.   1347            baton = jsbatonSetValue(baton, undefined, `:${key}\u0000`);
  741.   1347            baton = jsbatonSetValue(
  742.   1347                baton,
  743.   1347                undefined,
  744.   1347                val,
  745.   1347                bufi,
  746.   1347                referenceList
  747.   1347            );
  748.   1347        });
  749.   1235    } else {
  750.    693        bindList.forEach(function (val) {
  751.    693            baton = jsbatonSetValue(
  752.    693                baton,
  753.    693                undefined,
  754.    693                val,
  755.    693                bufi,
  756.    693                referenceList
  757.    693            );
  758.    693        });
  759.   1916    }
  760.   1916    [baton, ...result] = await dbCallAsync(
  761.   1916        baton,
  762.   1916        [
  763.   1916            // 0. db
  764.   1916            db,
  765.   1916            // 1. sql
  766.   1916            String(sql) + "\n;\nPRAGMA noop",
  767.   1916            // 2. bindList.length
  768.   1916            (
  769.   1916                bindByKey
  770.   1916                ? Object.keys(bindList).length
  771.    681                : bindList.length
  772.   1928            ),
  773.   1928            // 3. bindByKey
  774.   1928            bindByKey,
  775.   1928            // 4. responseType
  776.   1928            (
  777.   1928                responseType === "lastblob"
  778.     56                ? SQLITE_RESPONSETYPE_LASTBLOB
  779.   1860                : responseType === "lastvalue"
  780.   1860                ? SQLITE_RESPONSETYPE_LASTVALUE
  781.   1860                : 0
  782.   1928            )
  783.   1928        ],
  784.   1928        "modeDb"
  785.   1861    );
  786.   1861    result = result[0];
  787.   1861    if (!IS_BROWSER) {
  788.   1861        result = cModule._jsbatonStealCbuffer(
  789.   1861            baton.buffer,
  790.   1861            0,
  791.   1861            Number(
  792.   1861                responseType !== "arraybuffer" && responseType !== "lastblob"
  793.   1861            )
  794.   1861        );
  795.   1861    }
  796.   1861    switch (responseType) {
  797.   1861    case "arraybuffer":
  798.    110    case "lastblob":
  799.    110        return result;
  800.   1236    case "lastvalue":
  801.   1403    case "list":
  802.   1403        return jsonParseArraybuffer(result);
  803.    348    default:
  804.    374        return jsonParseArraybuffer(result).map(function (table) {
  805.    374            let colList = table.shift();
  806.  13942            return table.map(function (row) {
  807.  13942                let dict = {};
  808.  40235                colList.forEach(function (key, ii) {
  809.  40235                    dict[key] = row[ii];
  810.  40235                });
  811.  13942                return dict;
  812.  13942            });
  813.    374        });
  814.   1928    }
  815.   1928}
  816.      1
  817.     18async function dbFileLoadAsync({
  818.     18    db,
  819.     18    dbData,
  820.     18    filename,
  821.     18    modeNoop,
  822.     18    modeSave = 0
  823.     18}) {
  824.     18
  825.     18// This function will load <filename> to <db>.
  826.     18
  827.     18    let filename2;
  828.     15    async function _dbFileLoad() {
  829.     15        dbData = await dbCallAsync(
  830.     15            jsbatonCreate("_dbFileLoad"),
  831.     15            [
  832.     15                // 0. sqlite3 * pInMemory
  833.     15                db,
  834.     15                // 1. char *zFilename
  835.     15                filename,
  836.     15                // 2. const int isSave
  837.     15                modeSave,
  838.     15                // 3. undefined
  839.     15                undefined,
  840.     15                // 4. dbData - same position as dbOpenAsync
  841.     15                dbData
  842.     15            ],
  843.     15            "modeDb"
  844.     15        );
  845.     15    }
  846.      1    if (modeNoop) {
  847.      1        return;
  848.     17    }
  849.     17    if (IS_BROWSER) {
  850.      1        filename = FILENAME_DBTMP;
  851.     17    }
  852.     17    assertOrThrow(
  853.     17        typeof filename === "string" && filename,
  854.     18        `invalid filename ${filename}`
  855.     18    );
  856.     18    // Save to tmpfile and then atomically-rename to actual-filename.
  857.     15    if (moduleFs && modeSave) {
  858.     13        filename2 = filename;
  859.     13        filename = modulePath.join(
  860.     13            modulePath.dirname(filename),
  861.     13            `.dbFileSaveAsync.${moduleCrypto.randomUUID()}`
  862.     13        );
  863.     13        try {
  864.     13            await _dbFileLoad();
  865.     13            await moduleFs.promises.rename(filename, filename2);
  866.     13        } finally {
  867.     13            await moduleFs.promises.unlink(filename).catch(noop);
  868.     13        }
  869.     13    } else {
  870.      2        await _dbFileLoad();
  871.     15    }
  872.     15    return dbData[1 + 0];
  873.     15}
  874.      1
  875.     14async function dbFileSaveAsync({
  876.     14    db,
  877.     14    dbData,
  878.     14    filename,
  879.     14    modeNoop
  880.     14}) {
  881.     14
  882.     14// This function will save <db> to <filename>.
  883.     14
  884.     14    return await dbFileLoadAsync({
  885.     14        db,
  886.     14        dbData,
  887.     14        filename,
  888.     14        modeNoop,
  889.     14        modeSave: 1
  890.     14    });
  891.     14}
  892.      1
  893.     56async function dbNoopAsync(...argList) {
  894.     56
  895.     56// This function will do nothing except return <argList>.
  896.     56
  897.     56    return await dbCallAsync(jsbatonCreate("_dbNoop"), argList);
  898.     56}
  899.      1
  900.     32async function dbOpenAsync({
  901.     32    afterFinalization,
  902.     32    dbData,
  903.     32    filename,
  904.     32    flags,
  905.     32    threadCount = 1
  906.     32}) {
  907.     32
  908.     32// This function will open and return sqlite-database-connection <db>.
  909.     32
  910.     32// int sqlite3_open_v2(
  911.     32//   const char *filename,   /* Database filename (UTF-8) */
  912.     32//   sqlite3 **ppDb,         /* OUT: SQLite db handle */
  913.     32//   int flags,              /* Flags */
  914.     32//   const char *zVfs        /* Name of VFS module to use */
  915.     32// );
  916.     32    let connPool;
  917.     32    let db = {busy: 0, filename, ii: 0};
  918.     32    let fileLgbm;
  919.     32    assertOrThrow(typeof filename === "string", `invalid filename ${filename}`);
  920.     32    assertOrThrow(
  921.      1        !dbData || isExternalBuffer(dbData),
  922.     32        "dbData must be ArrayBuffer"
  923.     32    );
  924.     32    connPool = await Promise.all(Array.from(new Array(
  925.     32        threadCount
  926.     31    ), async function () {
  927.     31        let [ptr] = await dbCallAsync(
  928.     31            jsbatonCreate("_dbOpen"),
  929.     31            [
  930.     31                // 0. const char *filename,   Database filename (UTF-8)
  931.     31                filename,
  932.     31                // 1. sqlite3 **ppDb,         OUT: SQLite db handle
  933.     31                undefined,
  934.     31                // 2. int flags,              Flags
  935.     31                flags ?? (
  936.     31                    SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI
  937.     31                ),
  938.     31                // 3. const char *zVfs        Name of VFS module to use
  939.     31                undefined,
  940.     31                // 4. wasm-only - arraybuffer of raw sqlite-database
  941.     31                dbData
  942.     31            ]
  943.     31        );
  944.     31        ptr = [ptr.getBigInt64(JSBATON_OFFSET_ARGV + 0, true)];
  945.     31        dbFinalizationRegistry.register(db, {afterFinalization, ptr});
  946.     31        return ptr;
  947.     31    }));
  948.     31    db.connPool = connPool;
  949.     31    // init lightgbm
  950.     31    if (!IS_BROWSER) {
  951.     31        fileLgbm = process.platform;
  952.     31        fileLgbm = fileLgbm.replace("darwin", "lib_lightgbm.dylib");
  953.     31        fileLgbm = fileLgbm.replace("win32", "lib_lightgbm.dll");
  954.     31        fileLgbm = fileLgbm.replace(process.platform, "lib_lightgbm.so");
  955.     31        fileLgbm = `${import.meta.dirname}/sqlmath/${fileLgbm}`;
  956.     31        await moduleFs.promises.access(fileLgbm).then(async function () {
  957.     31            await dbExecAsync({
  958.     31                db,
  959.     31                sql: `SELECT lgbm_dlopen('${fileLgbm}');`
  960.     31            });
  961.     31        }).catch(noop);
  962.     31    }
  963.     31    return db;
  964.     31}
  965.      1
  966.     47async function dbTableImportAsync({
  967.     47    db,
  968.     47    filename,
  969.     47    headerMissing,
  970.     47    mode,
  971.     47    tableName,
  972.     47    textData
  973.     47}) {
  974.     47// this function will create table from imported csv/json <textData>
  975.     47    let colList;
  976.     47    let rowList;
  977.     47    let rowidList;
  978.     47    let tmp;
  979.     42    if (filename) {
  980.     42        textData = await moduleFs.promises.readFile(filename, "utf8");
  981.     42    }
  982.     47    switch (mode) {
  983.      2    case "csv":
  984.      2        rowList = jsonRowListFromCsv({
  985.      2            csv: textData
  986.      2        });
  987.      2        break;
  988.     43    case "tsv":
  989.     43        rowList = [];
  990.  99001        textData.trimEnd().replace((/.+/g), function (line) {
  991.  99001            rowList.push(line.split("\t"));
  992.  99001        });
  993.     43        break;
  994.     47    // case "json":
  995.      2    default:
  996.      2        rowList = JSON.parse(textData);
  997.     47    }
  998.      1    if (!(typeof rowList === "object" && rowList)) {
  999.      1        rowList = [];
 1000.      1    }
 1001.     47    // normalize rowList to list
 1002.      1    if (!Array.isArray(rowList)) {
 1003.      1        rowidList = [];
 1004.      2        rowList = Object.entries(rowList).map(function ([
 1005.      2            key, val
 1006.      2        ]) {
 1007.      2            rowidList.push(key);
 1008.      2            return val;
 1009.      2        });
 1010.      1    }
 1011.     47    // headerMissing
 1012.     42    if (headerMissing && (rowList.length > 0 && Array.isArray(rowList[0]))) {
 1013.    714        rowList.unshift(Array.from(rowList[0]).map(function (ignore, ii) {
 1014.    714            return String(ii + 1);
 1015.    714        }));
 1016.     42    }
 1017.     47    // normalize rowList[ii] to list
 1018.      1    if (rowList.length === 0) {
 1019.      1        rowList.push([
 1020.      1            "undefined"
 1021.      1        ]);
 1022.      1    }
 1023.      1    if (!Array.isArray(rowList[0])) {
 1024.      1        colList = Array.from(
 1025.      1            new Set(
 1026.      2                rowList.map(function (obj) {
 1027.      2                    return Object.keys(obj);
 1028.      2                }).flat()
 1029.      1            )
 1030.      1        );
 1031.      2        rowList = rowList.map(function (obj) {
 1032.      4            return colList.map(function (key) {
 1033.      4                return obj[key];
 1034.      4            });
 1035.      2        });
 1036.      1        rowList.unshift(colList);
 1037.      1    }
 1038.     47    // init colList
 1039.     47    colList = rowList.shift();
 1040.     47    // preserve rowid
 1041.      1    if (rowidList) {
 1042.      1        colList.unshift("rowid");
 1043.      2        rowList.forEach(function (row, ii) {
 1044.      2            row.unshift(rowidList[ii]);
 1045.      2        });
 1046.      1    }
 1047.     47    // normalize colList
 1048.     47    tmp = new Set();
 1049.    723    colList = colList.map(function (colName) {
 1050.    723        let colName2;
 1051.    723        let duplicate = 0;
 1052.    723        colName = colName.trim();
 1053.    723        colName = colName.replace((/\W/g), "_");
 1054.    723        colName = colName.replace((/^[^A-Z_a-z]|^$/gm), "_$&");
 1055.    724        while (true) {
 1056.    724            duplicate += 1;
 1057.    724            colName2 = (
 1058.    724                duplicate === 1
 1059.    724                ? colName
 1060.    724                : colName + "_" + duplicate
 1061.    724            );
 1062.    724            if (!tmp.has(colName2)) {
 1063.    724                tmp.add(colName2);
 1064.    724                return colName2;
 1065.    724            }
 1066.    724        }
 1067.    723    });
 1068.     47    // create dbtable from rowList
 1069.     47    await dbExecAsync({
 1070.     47        bindList: {
 1071.     47            rowList: JSON.stringify(rowList)
 1072.     47        },
 1073.     47        db,
 1074.     47        sql: (
 1075.     47            rowList.length === 0
 1076.      3            ? `CREATE TABLE ${tableName} (${colList.join(",")});`
 1077.     44            : (
 1078.     44                `CREATE TABLE ${tableName} AS SELECT `
 1079.    719                + colList.map(function (colName, ii) {
 1080.    719                    return "value->>" + ii + " AS " + colName;
 1081.    719                }).join(",")
 1082.     44                + " FROM JSON_EACH($rowList);"
 1083.     44            )
 1084.     47        )
 1085.     47    });
 1086.     47}
 1087.      1
 1088.      2async function fsCopyFileUnlessTest(file1, file2, mode) {
 1089.      2
 1090.      2// This function will copy <file1> to <file2> unless <npm_config_mode_test> = 1.
 1091.      2
 1092.      1    if (npm_config_mode_test && mode !== "force") {
 1093.      1        return;
 1094.      1    }
 1095.      1    await moduleFs.promises.copyFile(file1, file2, mode | 0);
 1096.      1}
 1097.      1
 1098.     10async function fsExistsUnlessTest(file, mode) {
 1099.     10
 1100.     10// This function will test if <file> exists unless <npm_config_mode_test> = 1.
 1101.     10
 1102.      8    if (npm_config_mode_test && mode !== "force") {
 1103.      8        return false;
 1104.      8    }
 1105.      2    try {
 1106.      2        await moduleFs.promises.access(file);
 1107.      1        return true;
 1108.      1    } catch (ignore) {
 1109.      1        return false;
 1110.      1    }
 1111.     10}
 1112.      1
 1113.     22async function fsReadFileUnlessTest(file, mode, defaultData) {
 1114.     22
 1115.     22// This function will read <data> from <file> unless <npm_config_mode_test> = 1.
 1116.     22
 1117.      8    if (npm_config_mode_test && mode !== "force") {
 1118.      8        return defaultData;
 1119.     14    }
 1120.     14    return await moduleFs.promises.readFile(
 1121.     14        file,
 1122.     14        mode && mode.replace("force", "utf8")
 1123.     22    );
 1124.     22}
 1125.      1
 1126.     10async function fsWriteFileUnlessTest(file, data, mode) {
 1127.     10
 1128.     10// This function will write <data> to <file> unless <npm_config_mode_test> = 1.
 1129.     10
 1130.      9    if (npm_config_mode_test && mode !== "force") {
 1131.      9        return;
 1132.      9    }
 1133.      1    await moduleFs.promises.writeFile(file, data);
 1134.      1}
 1135.      1
 1136.     31function isExternalBuffer(buf) {
 1137.     31
 1138.     31// This function will check if <buf> is ArrayBuffer.
 1139.     31
 1140.     17    return buf && buf.constructor === ArrayBuffer;
 1141.     31}
 1142.      1
 1143.   2060function jsbatonCreate(funcname) {
 1144.   2060
 1145.   2060// This function will create buffer <baton>.
 1146.   2060
 1147.   2060    let baton = new DataView(new ArrayBuffer(JSBATON_OFFSET_ALL));
 1148.   2060    // init nallc, nused
 1149.   2060    baton.setInt32(4, JSBATON_OFFSET_ALL, true);
 1150.   2060    // copy funcname into baton
 1151.   2060    new Uint8Array(
 1152.   2060        baton.buffer,
 1153.   2060        baton.byteOffset + JSBATON_OFFSET_FUNCNAME,
 1154.   2060        SIZEOF_FUNCNAME - 1
 1155.   2060    ).set(new TextEncoder().encode(funcname));
 1156.   2060    return baton;
 1157.   2060}
 1158.      1
 1159.     24function jsbatonGetInt64(baton, argi) {
 1160.     24
 1161.     24// This function will return int64-value from <baton> at <argi>.
 1162.     24
 1163.     24    return baton.getBigInt64(JSBATON_OFFSET_ARGV + argi * 8, true);
 1164.     24}
 1165.      1
 1166.      9function jsbatonGetString(baton, argi) {
 1167.      9
 1168.      9// This function will return string-value from <baton> at <argi>.
 1169.      9
 1170.      9    let offset = baton.getInt32(JSBATON_OFFSET_ARGV + argi * 8, true);
 1171.      9    return new TextDecoder().decode(new Uint8Array(
 1172.      9        baton.buffer,
 1173.      9        baton.byteOffset + offset + 1 + 4,
 1174.      9        // remove null-terminator from string
 1175.      9        baton.getInt32(offset + 1, true) - 1
 1176.      9    ));
 1177.      9}
 1178.      1
 1179.   5182function jsbatonSetValue(baton, argi, val, bufi, referenceList) {
 1180.   5182
 1181.   5182// This function will set <val> to buffer <baton>.
 1182.   5182
 1183.   5182    let nn;
 1184.   5182    let nused;
 1185.   5182    let tmp;
 1186.   5182    let vsize;
 1187.   5182    let vtype;
 1188.   5182/*
 1189.   5182#define SQLITE_DATATYPE_BLOB            0x04
 1190.   5182#define SQLITE_DATATYPE_EXTERNALBUFFER          0x71
 1191.   5182#define SQLITE_DATATYPE_FLOAT           0x02
 1192.   5182#define SQLITE_DATATYPE_INTEGER         0x01
 1193.   5182#define SQLITE_DATATYPE_INTEGER_0       0x00
 1194.   5182#define SQLITE_DATATYPE_INTEGER_1       0x21
 1195.   5182#define SQLITE_DATATYPE_NULL            0x05
 1196.   5182#define SQLITE_DATATYPE_TEXT            0x03
 1197.   5182#define SQLITE_DATATYPE_TEXT_0          0x13
 1198.   5182    //  1. 0.bigint
 1199.   5182    //  2. 0.boolean
 1200.   5182    //  3. 0.function
 1201.   5182    //  4. 0.number
 1202.   5182    //  5. 0.object
 1203.   5182    //  6. 0.string
 1204.   5182    //  7. 0.symbol
 1205.   5182    //  8. 0.undefined
 1206.   5182    //  9. 1.bigint
 1207.   5182    // 10. 1.boolean
 1208.   5182    // 11. 1.function
 1209.   5182    // 12. 1.number
 1210.   5182    // 13. 1.object
 1211.   5182    // 14. 1.string
 1212.   5182    // 15. 1.symbol
 1213.   5182    // 16. 1.undefined
 1214.   5182    // 17. 1.buffer
 1215.   5182    // 18. 1.externalbuffer
 1216.   5182*/
 1217.   5182    // 10. 1.boolean
 1218.   5158    if (val === 1 || val === 1n) {
 1219.     30        val = true;
 1220.     30    }
 1221.   5182    switch (
 1222.   5182        val
 1223.   4801        ? "1." + typeof(val)
 1224.    381        : "0." + typeof(val)
 1225.   5182    ) {
 1226.   5182    //  1. 0.bigint
 1227.     24    case "0.bigint":
 1228.   5182    //  2. 0.boolean
 1229.     30    case "0.boolean":
 1230.   5182    //  4. 0.number
 1231.    250    case "0.number":
 1232.    250        if (Number.isNaN(val)) {
 1233.    250            vtype = SQLITE_DATATYPE_NULL;
 1234.    250            vsize = 0;
 1235.    250            break;
 1236.    250        }
 1237.    250        vtype = SQLITE_DATATYPE_INTEGER_0;
 1238.    250        vsize = 0;
 1239.    250        break;
 1240.   5182    //  3. 0.function
 1241.   5182    // case "0.function":
 1242.   5182    //  5. 0.object
 1243.     98    case "0.object":
 1244.   5182    //  7. 0.symbol
 1245.     98    case "0.symbol":
 1246.   5182    //  8. 0.undefined
 1247.    105    case "0.undefined":
 1248.   5182    // 11. 1.function
 1249.    119    case "1.function":
 1250.   5182    // 15. 1.symbol
 1251.    125    case "1.symbol":
 1252.    125    // 16. 1.undefined
 1253.    125    // case "1.undefined":
 1254.    125        vtype = SQLITE_DATATYPE_NULL;
 1255.    125        vsize = 0;
 1256.    125        break;
 1257.   5182    //  6. 0.string
 1258.     26    case "0.string":
 1259.     26        vtype = SQLITE_DATATYPE_TEXT_0;
 1260.     26        vsize = 0;
 1261.     26        break;
 1262.   5182    //  9. 1.bigint
 1263.     42    case "1.bigint":
 1264.     42        vtype = SQLITE_DATATYPE_INTEGER;
 1265.     42        vsize = 8;
 1266.     42        break;
 1267.   5182    // 10. 1.boolean
 1268.     36    case "1.boolean":
 1269.     36        vtype = SQLITE_DATATYPE_INTEGER_1;
 1270.     36        vsize = 0;
 1271.     36        break;
 1272.   5182    // 12. 1.number
 1273.    561    case "1.number":
 1274.    561        vtype = SQLITE_DATATYPE_FLOAT;
 1275.    561        vsize = 8;
 1276.    561        break;
 1277.   5182    // 14. 1.string
 1278.   4060    case "1.string":
 1279.   4060        val = new TextEncoder().encode(val);
 1280.   4060        vtype = SQLITE_DATATYPE_TEXT;
 1281.   4060        vsize = 4 + val.byteLength;
 1282.   4060        break;
 1283.   5182    // 13. 1.object
 1284.     82    default:
 1285.     82        // 18. 1.externalbuffer
 1286.     82        if (val.constructor === ArrayBuffer) {
 1287.     82            assertOrThrow(
 1288.     82                !IS_BROWSER,
 1289.     82                "external ArrayBuffer cannot be passed directly to wasm"
 1290.     82            );
 1291.     82            vtype = SQLITE_DATATYPE_EXTERNALBUFFER;
 1292.     82            vsize = 4;
 1293.     82            break;
 1294.     82        }
 1295.     82        // 17. 1.buffer
 1296.     82        if (ArrayBuffer.isView(val)) {
 1297.     82            if (val.byteLength === 0) {
 1298.     82                vtype = SQLITE_DATATYPE_NULL;
 1299.     82                vsize = 0;
 1300.     82                break;
 1301.     82            }
 1302.     82            vtype = SQLITE_DATATYPE_BLOB;
 1303.     82            vsize = 4 + val.byteLength;
 1304.     82            break;
 1305.     82        }
 1306.     82        // 13. 1.object
 1307.     82        val = new TextEncoder().encode(
 1308.     82            typeof val.toJSON === "function"
 1309.     82            ? val.toJSON()
 1310.     82            : JSON.stringify(val)
 1311.     82        );
 1312.     82        vtype = SQLITE_DATATYPE_TEXT;
 1313.     82        vsize = 4 + val.byteLength;
 1314.   5182    }
 1315.   5182    nused = baton.getInt32(4, true);
 1316.   5182    nn = nused + 1 + vsize;
 1317.   5182    assertOrThrow(
 1318.   5182        nn <= 0xffff_ffff,
 1319.   5182        "jsbaton cannot exceed 0x7fff_ffff / 2,147,483,647 bytes"
 1320.   5182    );
 1321.   5182    // exponentially grow baton as needed
 1322.   2164    if (baton.byteLength < nn) {
 1323.   2164        tmp = baton;
 1324.   2164        baton = new DataView(new ArrayBuffer(
 1325.   2164            Math.min(2 ** Math.ceil(Math.log2(nn)), 0x7fff_ffff)
 1326.   2164        ));
 1327.   2164        // update nallc
 1328.   2164        baton.setInt32(0, baton.byteLength, true);
 1329.   2164        // copy old-baton into new-baton
 1330.   2164        new Uint8Array(baton.buffer, baton.byteOffset, nused).set(
 1331.   2164            new Uint8Array(tmp.buffer, tmp.byteOffset, nused)
 1332.   2164        );
 1333.   2164    }
 1334.   5182    // push vtype - 1-byte
 1335.   5182    baton.setUint8(nused, vtype);
 1336.   5182    // update nused
 1337.   5182    baton.setInt32(4, nused + 1 + vsize, true);
 1338.   5182    // handle blob-value
 1339.   5182    switch (vtype) {
 1340.     30    case SQLITE_DATATYPE_BLOB:
 1341.   4118    case SQLITE_DATATYPE_TEXT:
 1342.   4118        // set argv[ii] to blob/text location
 1343.   4118        if (argi !== undefined) {
 1344.   4118            baton.setInt32(JSBATON_OFFSET_ARGV + argi * 8, nused, true);
 1345.   4118        }
 1346.   4118        vsize -= 4;
 1347.   4118        assertOrThrow(
 1348.   4118            0 <= vsize && vsize <= SIZEOF_BLOB_MAX,
 1349.   4118            (
 1350.   4118                "sqlite-blob byte-length must be within inclusive-range"
 1351.   4118                + ` 0 to ${SIZEOF_BLOB_MAX}`
 1352.   4118            )
 1353.   4118        );
 1354.   4118        // push vsize - 4-byte
 1355.   4118        baton.setInt32(nused + 1, vsize, true);
 1356.   4118        // push SQLITE-BLOB/TEXT - vsize-byte
 1357.   4118        new Uint8Array(
 1358.   4118            baton.buffer,
 1359.   4118            baton.byteOffset + nused + 1 + 4,
 1360.   4118            vsize
 1361.   4118        ).set(new Uint8Array(val.buffer, val.byteOffset, vsize));
 1362.   4118        break;
 1363.     12    case SQLITE_DATATYPE_EXTERNALBUFFER:
 1364.     12        vsize = val.byteLength;
 1365.     12        assertOrThrow(
 1366.     12            0 <= vsize && vsize <= SIZEOF_BLOB_MAX,
 1367.     12            (
 1368.     12                "sqlite-blob byte-length must be within inclusive-range"
 1369.     12                + ` 0 to ${SIZEOF_BLOB_MAX}`
 1370.     12            )
 1371.     12        );
 1372.     12        assertOrThrow(
 1373.     12            bufi[0] < JSBATON_ARGC,
 1374.     12            `cannot pass more than ${JSBATON_ARGC} arraybuffers`
 1375.     12        );
 1376.     12        // push externalbuffer - 4-byte
 1377.     12        baton.setInt32(nused + 1, bufi[0], true);
 1378.     12        // set buffer
 1379.     12        cModule._jsbatonSetArraybuffer(baton.buffer, bufi[0], val);
 1380.     12        // increment bufi
 1381.     12        bufi[0] += 1;
 1382.     12        // add buffer to reference_list to prevent gc during db_call.
 1383.     12        referenceList.push(val);
 1384.     12        break;
 1385.    561    case SQLITE_DATATYPE_FLOAT:
 1386.    561        // push SQLITE-REAL - 8-byte
 1387.    561        baton.setFloat64(nused + 1, val, true);
 1388.    561        break;
 1389.     42    case SQLITE_DATATYPE_INTEGER:
 1390.     42        assertInt64(val);
 1391.     42        // push SQLITE-INTEGER - 8-byte
 1392.     42        baton.setBigInt64(nused + 1, val, true);
 1393.     42        break;
 1394.   5170    }
 1395.   5170    return baton;
 1396.   5170}
 1397.      1
 1398.   1752function jsonParseArraybuffer(buf) {
 1399.   1752
 1400.   1752// This function will JSON.parse arraybuffer <buf>.
 1401.   1752
 1402.   1752    return JSON.parse(
 1403.   1752        (
 1404.   1752            IS_BROWSER
 1405.      1            ? new TextDecoder().decode(buf)
 1406.   1751            : buf
 1407.   1752        )
 1408.      1        || "null"
 1409.   1752    );
 1410.   1752}
 1411.      1
 1412.      2function jsonRowListFromCsv({
 1413.      2    csv
 1414.      2}) {
 1415.      2// this function will convert <csv>-text to json list-of-list
 1416.      2//
 1417.      2// https://tools.ietf.org/html/rfc4180#section-2
 1418.      2// Definition of the CSV Format
 1419.      2// While there are various specifications and implementations for the
 1420.      2// CSV format (for ex. [4], [5], [6] and [7]), there is no formal
 1421.      2// specification in existence, which allows for a wide variety of
 1422.      2// interpretations of CSV files.  This section documents the format that
 1423.      2// seems to be followed by most implementations:
 1424.      2//
 1425.      2// 1.  Each record is located on a separate line, delimited by a line
 1426.      2//     break (CRLF).  For example:
 1427.      2//     aaa,bbb,ccc CRLF
 1428.      2//     zzz,yyy,xxx CRLF
 1429.      2//
 1430.      2// 2.  The last record in the file may or may not have an ending line
 1431.      2//     break.  For example:
 1432.      2//     aaa,bbb,ccc CRLF
 1433.      2//     zzz,yyy,xxx
 1434.      2//
 1435.      2// 3.  There maybe an optional header line appearing as the first line
 1436.      2//     of the file with the same format as normal record lines.  This
 1437.      2//     header will contain names corresponding to the fields in the file
 1438.      2//     and should contain the same number of fields as the records in
 1439.      2//     the rest of the file (the presence or absence of the header line
 1440.      2//     should be indicated via the optional "header" parameter of this
 1441.      2//     MIME type).  For example:
 1442.      2//     field_name,field_name,field_name CRLF
 1443.      2//     aaa,bbb,ccc CRLF
 1444.      2//     zzz,yyy,xxx CRLF
 1445.      2//
 1446.      2// 4.  Within the header and each record, there may be one or more
 1447.      2//     fields, separated by commas.  Each line should contain the same
 1448.      2//     number of fields throughout the file.  Spaces are considered part
 1449.      2//     of a field and should not be ignored.  The last field in the
 1450.      2//     record must not be followed by a comma.  For example:
 1451.      2//     aaa,bbb,ccc
 1452.      2//
 1453.      2// 5.  Each field may or may not be enclosed in double quotes (however
 1454.      2//     some programs, such as Microsoft Excel, do not use double quotes
 1455.      2//     at all).  If fields are not enclosed with double quotes, then
 1456.      2//     double quotes may not appear inside the fields.  For example:
 1457.      2//     "aaa","bbb","ccc" CRLF
 1458.      2//     zzz,yyy,xxx
 1459.      2//
 1460.      2// 6.  Fields containing line breaks (CRLF), double quotes, and commas
 1461.      2//     should be enclosed in double-quotes.  For example:
 1462.      2//     "aaa","b CRLF
 1463.      2//     bb","ccc" CRLF
 1464.      2//     zzz,yyy,xxx
 1465.      2//
 1466.      2// 7.  If double-quotes are used to enclose fields, then a double-quote
 1467.      2//     appearing inside a field must be escaped by preceding it with
 1468.      2//     another double quote.  For example:
 1469.      2//     "aaa","b""bb","ccc"
 1470.      2    let match;
 1471.      2    let quote;
 1472.      2    let rgx;
 1473.      2    let row;
 1474.      2    let rowList;
 1475.      2    let val;
 1476.      2    // normalize "\r\n" to "\n"
 1477.      2    csv = csv.trimEnd().replace((
 1478.      2        /\r\n?/gu
 1479.      2    ), "\n") + "\n";
 1480.      2    rgx = (
 1481.      2        /(.*?)(""|"|,|\n)/gu
 1482.      2    );
 1483.      2    rowList = [];
 1484.      2    // reset row
 1485.      2    row = [];
 1486.      2    val = "";
 1487.     28    while (true) {
 1488.     28        match = rgx.exec(csv);
 1489.     28        if (!match) {
 1490.     28// 2.  The last record in the file may or may not have an ending line
 1491.     28//     break.  For example:
 1492.     28//     aaa,bbb,ccc CRLF
 1493.     28//     zzz,yyy,xxx
 1494.     28            if (!row.length) {
 1495.     28                break;
 1496.     28            }
 1497.     28            // // if eof missing crlf, then mock it
 1498.     28            // rgx.lastIndex = csv.length;
 1499.     28            // match = [
 1500.     28            //     "\n", "", "\n"
 1501.     28            // ];
 1502.     28        }
 1503.     28        // build val
 1504.     28        val += match[1];
 1505.     28        if (match[2] === "\"") {
 1506.     28// 5.  Each field may or may not be enclosed in double quotes (however
 1507.     28//     some programs, such as Microsoft Excel, do not use double quotes
 1508.     28//     at all).  If fields are not enclosed with double quotes, then
 1509.     28//     double quotes may not appear inside the fields.  For example:
 1510.     28//     "aaa","bbb","ccc" CRLF
 1511.     28//     zzz,yyy,xxx
 1512.     28            quote = !quote;
 1513.     28        } else if (quote) {
 1514.     28// 7.  If double-quotes are used to enclose fields, then a double-quote
 1515.     28//     appearing inside a field must be escaped by preceding it with
 1516.     28//     another double quote.  For example:
 1517.     28//     "aaa","b""bb","ccc"
 1518.     28            if (match[2] === "\"\"") {
 1519.     28                val += "\"";
 1520.     28// 6.  Fields containing line breaks (CRLF), double quotes, and commas
 1521.     28//     should be enclosed in double-quotes.  For example:
 1522.     28//     "aaa","b CRLF
 1523.     28//     bb","ccc" CRLF
 1524.     28//     zzz,yyy,xxx
 1525.     28            } else {
 1526.     28                val += match[2];
 1527.     28            }
 1528.     28        } else if (match[2] === ",") {
 1529.     28// 4.  Within the header and each record, there may be one or more
 1530.     28//     fields, separated by commas.  Each line should contain the same
 1531.     28//     number of fields throughout the file.  Spaces are considered part
 1532.     28//     of a field and should not be ignored.  The last field in the
 1533.     28//     record must not be followed by a comma.  For example:
 1534.     28//     aaa,bbb,ccc
 1535.     28            // delimit val
 1536.     28            row.push(val);
 1537.     28            val = "";
 1538.     28        } else if (match[2] === "\n") {
 1539.     28// 1.  Each record is located on a separate line, delimited by a line
 1540.     28//     break (CRLF).  For example:
 1541.     28//     aaa,bbb,ccc CRLF
 1542.     28//     zzz,yyy,xxx CRLF
 1543.     28            // delimit val
 1544.     28            row.push(val);
 1545.     28            val = "";
 1546.     28            // append row
 1547.     28            rowList.push(row);
 1548.     28            // reset row
 1549.     28            row = [];
 1550.     28        }
 1551.     28    }
 1552.      2    // // append val
 1553.      2    // if (val) {
 1554.      2    //     row.push(val);
 1555.      2    // }
 1556.      2    // // append row
 1557.      2    // if (row.length) {
 1558.      2    //     rowList.push(row);
 1559.      2    // }
 1560.      2    return rowList;
 1561.      2}
 1562.      1
 1563.      1function listOrEmptyList(list) {
 1564.      1
 1565.      1// This function will return <list> or empty-list if falsy.
 1566.      1
 1567.      1    return list || [];
 1568.      1}
 1569.      1
 1570.      8async function moduleFsInit() {
 1571.      8
 1572.      8// This function will import nodejs builtin-modules if they have not yet been
 1573.      8// imported.
 1574.      8
 1575.      8// State 3 - Modules already imported.
 1576.      8
 1577.      6    if (moduleFs !== undefined) {
 1578.      6        return;
 1579.      6    }
 1580.      2
 1581.      2// State 2 - Wait while modules are importing.
 1582.      2
 1583.      2    if (moduleFsInitResolveList !== undefined) {
 1584.      1        return new Promise(function (resolve) {
 1585.      1            moduleFsInitResolveList.push(resolve);
 1586.      1        });
 1587.      1    }
 1588.      1
 1589.      1// State 1 - Start importing modules.
 1590.      1
 1591.      1    moduleFsInitResolveList = [];
 1592.      1    [
 1593.      1        moduleChildProcess,
 1594.      1        moduleCrypto,
 1595.      1        moduleFs,
 1596.      1        modulePath,
 1597.      1        moduleUrl
 1598.      1    ] = await Promise.all([
 1599.      1        import("child_process"),
 1600.      1        import("crypto"),
 1601.      1        import("fs"),
 1602.      1        import("path"),
 1603.      1        import("url")
 1604.      1    ]);
 1605.      1    while (moduleFsInitResolveList.length > 0) {
 1606.      1        moduleFsInitResolveList.shift()();
 1607.      1    }
 1608.      8}
 1609.      1
 1610.    264function noop(val) {
 1611.    264
 1612.    264// This function will do nothing except return <val>.
 1613.    264
 1614.    264    return val;
 1615.    264}
 1616.      1
 1617.  42580function objectDeepCopyWithKeysSorted(obj) {
 1618.  42580
 1619.  42580// This function will recursively deep-copy <obj> with keys sorted.
 1620.  42580
 1621.  42580    let sorted;
 1622.  28132    if (typeof obj !== "object" || !obj) {
 1623.  28132        return obj;
 1624.  28132    }
 1625.  14448
 1626.  14448// Recursively deep-copy list with child-keys sorted.
 1627.  14448
 1628.  14448    if (Array.isArray(obj)) {
 1629.   2202        return obj.map(objectDeepCopyWithKeysSorted);
 1630.  12246    }
 1631.  12246
 1632.  12246// Recursively deep-copy obj with keys sorted.
 1633.  12246
 1634.  12246    sorted = Object.create(null);
 1635.  13522    Object.keys(obj).sort().forEach(function (key) {
 1636.  13522        sorted[key] = objectDeepCopyWithKeysSorted(obj[key]);
 1637.  13522    });
 1638.  12246    return sorted;
 1639.  12246}
 1640.      1
 1641.      3async function sqlmathInit() {
 1642.      3
 1643.      3// This function will init sqlmath.
 1644.      3
 1645.      3    let moduleModule;
 1646.      3    dbFinalizationRegistry = (
 1647.      3        dbFinalizationRegistry
 1648.     28    ) || new FinalizationRegistry(function ({afterFinalization, ptr}) {
 1649.     28
 1650.     28// This function will auto-close any open sqlite3-db-pointer,
 1651.     28// after its js-wrapper has been garbage-collected.
 1652.     28
 1653.     28        dbCallAsync(jsbatonCreate("_dbClose"), [ptr[0]]);
 1654.      1        if (afterFinalization) {
 1655.      1            afterFinalization();
 1656.      1        }
 1657.     28    });
 1658.      3
 1659.      3// Feature-detect nodejs.
 1660.      3
 1661.      3    if (
 1662.      3        typeof process !== "object"
 1663.      3        || typeof process?.versions?.node !== "string"
 1664.      3        || cModule
 1665.      1    ) {
 1666.      1        return;
 1667.      2    }
 1668.      2
 1669.      2// Init moduleFs.
 1670.      2
 1671.      2    await moduleFsInit();
 1672.      2    moduleFsInit(); // coverage-hack
 1673.      2    moduleChildProcessSpawn = moduleChildProcess.spawn;
 1674.      2
 1675.      2// Init moduleFs.
 1676.      2
 1677.      2    await moduleFsInit();
 1678.      2    moduleFsInit(); // coverage-hack
 1679.      2    moduleChildProcessSpawn = moduleChildProcess.spawn;
 1680.      2    cModulePath = moduleUrl.fileURLToPath(import.meta.url).replace(
 1681.      2        (/\bsqlmath\.mjs$/),
 1682.      2        `_sqlmath.napi6_${process.platform}_${process.arch}.node`
 1683.      2    );
 1684.      2
 1685.      2// Import napi c-addon.
 1686.      2
 1687.      2    if (!npm_config_mode_setup) {
 1688.      2        moduleModule = await import("module");
 1689.      2        if (!cModule) {
 1690.      2            cModule = moduleModule.createRequire(cModulePath);
 1691.      2            cModule = cModule(cModulePath);
 1692.      2        }
 1693.      2    }
 1694.      2    if (npm_config_mode_test) {
 1695.      2
 1696.      2// Mock consoleError.
 1697.      2
 1698.      2        consoleError = noop;
 1699.      2
 1700.      2// Mock moduleChildProcessSpawn.
 1701.      2
 1702.     15        moduleChildProcessSpawn = function () {
 1703.     15            let child = {
 1704.     15                end: noop,
 1705.     17                on: function (onType, resolve) {
 1706.     17                    switch (onType) {
 1707.      2                    case "data":
 1708.      2                        resolve(Buffer.alloc(0));
 1709.      2                        return;
 1710.     15                    default:
 1711.     15                        resolve(0);
 1712.     17                    }
 1713.     17                },
 1714.     15                setEncoding: noop,
 1715.     15                write: noop
 1716.     15            };
 1717.     15            child.stderr = child;
 1718.     15            child.stdin = child;
 1719.     15            child.stdout = child;
 1720.     15            return child;
 1721.     15        };
 1722.      2    }
 1723.      3}
 1724.      1
 1725.      1function sqlmathWebworkerInit({
 1726.      1    db,
 1727.      1    modeTest
 1728.      1}) {
 1729.      1
 1730.      1// This function will init sqlmath web-worker.
 1731.      1
 1732.      1// Feature-detect browser.
 1733.      1
 1734.      1    let Worker = globalThis.Worker;
 1735.      1    IS_BROWSER = true;
 1736.      1    if (modeTest) {
 1737.      1        Worker = function () {
 1738.      1            return;
 1739.      1        };
 1740.      1    }
 1741.      1    sqlWorker = new Worker("sqlmath_wasm.js");
 1742.      2    sqlWorker.onmessage = function ({
 1743.      2        data
 1744.      2    }) {
 1745.      2        sqlMessageDict[data.id](data);
 1746.      2    };
 1747.      1    if (modeTest) {
 1748.      2        sqlWorker.postMessage = function (data) {
 1749.      2            setTimeout(function () {
 1750.      2                sqlWorker.onmessage({data});
 1751.      2            });
 1752.      2        };
 1753.      1        // test dbCallAsync handling-behavior
 1754.      1        dbCallAsync(jsbatonCreate("testTimeElapsed"), [true]);
 1755.      1        // test dbFileLoadAsync handling-behavior
 1756.      1        dbFileLoadAsync({db, filename: "aa", modeTest});
 1757.      1        // test jsonParseArraybuffer handling-behavior
 1758.      1        jsonParseArraybuffer(new TextEncoder().encode("0"));
 1759.      1        // revert IS_BROWSER
 1760.      1        IS_BROWSER = undefined;
 1761.      1    }
 1762.      1}
 1763.      1
 1764.      1function waitAsync(timeout) {
 1765.      1
 1766.      1// This function will wait <timeout> ms.
 1767.      1
 1768.      1    return new Promise(function (resolve) {
 1769.      1        setTimeout(resolve, timeout * !npm_config_mode_test);
 1770.      1    });
 1771.      1}
 1772.      1
 1773.      1sqlmathInit(); // coverage-hack
 1774.      1await sqlmathInit();
 1775.      1sqlmathInit(); // coverage-hack
 1776.      1
 1777.      1export {
 1778.      1    LGBM_DTYPE_FLOAT32,
 1779.      1    LGBM_DTYPE_FLOAT64,
 1780.      1    LGBM_DTYPE_INT32,
 1781.      1    LGBM_DTYPE_INT64,
 1782.      1    LGBM_FEATURE_IMPORTANCE_GAIN,
 1783.      1    LGBM_FEATURE_IMPORTANCE_SPLIT,
 1784.      1    LGBM_MATRIX_TYPE_CSC,
 1785.      1    LGBM_MATRIX_TYPE_CSR,
 1786.      1    LGBM_PREDICT_CONTRIB,
 1787.      1    LGBM_PREDICT_LEAF_INDEX,
 1788.      1    LGBM_PREDICT_NORMAL,
 1789.      1    LGBM_PREDICT_RAW_SCORE,
 1790.      1    SQLITE_OPEN_AUTOPROXY,
 1791.      1    SQLITE_OPEN_CREATE,
 1792.      1    SQLITE_OPEN_DELETEONCLOSE,
 1793.      1    SQLITE_OPEN_EXCLUSIVE,
 1794.      1    SQLITE_OPEN_FULLMUTEX,
 1795.      1    SQLITE_OPEN_MAIN_DB,
 1796.      1    SQLITE_OPEN_MAIN_JOURNAL,
 1797.      1    SQLITE_OPEN_MEMORY,
 1798.      1    SQLITE_OPEN_NOFOLLOW,
 1799.      1    SQLITE_OPEN_NOMUTEX,
 1800.      1    SQLITE_OPEN_PRIVATECACHE,
 1801.      1    SQLITE_OPEN_READONLY,
 1802.      1    SQLITE_OPEN_READWRITE,
 1803.      1    SQLITE_OPEN_SHAREDCACHE,
 1804.      1    SQLITE_OPEN_SUBJOURNAL,
 1805.      1    SQLITE_OPEN_SUPER_JOURNAL,
 1806.      1    SQLITE_OPEN_TEMP_DB,
 1807.      1    SQLITE_OPEN_TEMP_JOURNAL,
 1808.      1    SQLITE_OPEN_TRANSIENT_DB,
 1809.      1    SQLITE_OPEN_URI,
 1810.      1    SQLITE_OPEN_WAL,
 1811.      1    assertErrorThrownAsync,
 1812.      1    assertInt64,
 1813.      1    assertJsonEqual,
 1814.      1    assertNumericalEqual,
 1815.      1    assertOrThrow,
 1816.      1    childProcessSpawn2,
 1817.      1    ciBuildExt,
 1818.      1    dbCloseAsync,
 1819.      1    dbExecAndReturnLastBlob,
 1820.      1    dbExecAndReturnLastRow,
 1821.      1    dbExecAndReturnLastTable,
 1822.      1    dbExecAndReturnLastValue,
 1823.      1    dbExecAsync,
 1824.      1    dbFileLoadAsync,
 1825.      1    dbFileSaveAsync,
 1826.      1    dbNoopAsync,
 1827.      1    dbOpenAsync,
 1828.      1    dbTableImportAsync,
 1829.      1    debugInline,
 1830.      1    fsCopyFileUnlessTest,
 1831.      1    fsExistsUnlessTest,
 1832.      1    fsReadFileUnlessTest,
 1833.      1    fsWriteFileUnlessTest,
 1834.      1    jsbatonGetInt64,
 1835.      1    jsbatonGetString,
 1836.      1    listOrEmptyList,
 1837.      1    noop,
 1838.      1    objectDeepCopyWithKeysSorted,
 1839.      1    sqlmathWebworkerInit,
 1840.      1    version,
 1841.      1    waitAsync
 1842.      1};
 1843.      1