wasm-rquickjs 0.2.2

Tool for wrapping JavaScript modules as WebAssembly components using the QuickJS engine
Documentation
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
import { validateFunction, validateString, validateUint32 } from "__wasm_rquickjs_builtin/internal/validators";
import { normalizeEncoding, slowCases } from "__wasm_rquickjs_builtin/internal/normalize_encoding";
export { normalizeEncoding, slowCases };

export const customInspectSymbol = Symbol.for("nodejs.util.inspect.custom");
export const kEnumerableProperty = Object.create(null);
kEnumerableProperty.enumerable = true;

export function once(callback) {
    let called = false;
    return function (...args) {
        if (called) return;
        called = true;
        Reflect.apply(callback, this, args);
    };
}

export function createDeferredPromise() {
    let resolve;
    let reject;
    const promise = new Promise((res, rej) => {
        resolve = res;
        reject = rej;
    });

    return { promise, resolve, reject };
}

let sleepState = null;

function getSleepState() {
    if (sleepState !== null) {
        return sleepState;
    }

    if (typeof SharedArrayBuffer === "function" &&
        typeof Atomics === "object" &&
        Atomics !== null &&
        typeof Atomics.wait === "function") {
        sleepState = new Int32Array(new SharedArrayBuffer(4));
    }

    return sleepState;
}

export function sleep(msec) {
    validateUint32(msec, "msec");

    if (msec === 0) {
        return;
    }

    const state = getSleepState();
    if (state !== null) {
        Atomics.wait(state, 0, 0, msec);
        return;
    }

    // Fallback for runtimes without SharedArrayBuffer/Atomics.wait support.
    const start = Date.now();
    while (Date.now() - start < msec) {
        // Intentional busy wait.
    }
}

// Keep a list of deprecation codes that have been warned on so we only warn on
// each one once.
const codesWarned = new Set();
const experimentalWarnings = new Set();

export function emitExperimentalWarning(feature) {
    validateString(feature, "feature");

    if (experimentalWarnings.has(feature)) {
        return;
    }
    experimentalWarnings.add(feature);

    process.emitWarning(
        `${feature} is an experimental feature and might change at any time`,
        "ExperimentalWarning",
    );
}

// Mark that a method should not be used.
// Returns a modified function which warns once by default.
// If --no-deprecation is set, then it is a no-op.
export function deprecate(fn, msg, code) {
    // TODO(kt3k): Uncomment this
    // if (process.noDeprecation === true) {
    //  return fn;
    // }

    if (code !== undefined) {
        validateString(code, "code");
    }

    let warned = false;
    function deprecated(...args) {
        if (!warned) {
            warned = true;
            if (code !== undefined) {
                if (!codesWarned.has(code)) {
                    process.emitWarning(msg, "DeprecationWarning", code, deprecated);
                    codesWarned.add(code);
                }
            } else {
                process.emitWarning(msg, "DeprecationWarning", deprecated);
            }
        }
        if (new.target) {
            return Reflect.construct(fn, args, new.target);
        }
        return Reflect.apply(fn, this, args);
    }

    // The wrapper will keep the same prototype as fn to maintain prototype chain
    Object.setPrototypeOf(deprecated, fn);
    if (fn.prototype) {
        // Setting this (rather than using Object.setPrototype, as above) ensures
        // that calling the unwrapped constructor gives an instanceof the wrapped
        // constructor.
        deprecated.prototype = fn.prototype;
    }

    return deprecated;
}

// In addition to being accessible through util.promisify.custom,
// this symbol is registered globally and can be accessed in any environment as
// Symbol.for('nodejs.util.promisify.custom').
export const kCustomPromisifiedSymbol = Symbol.for("nodejs.util.promisify.custom");
// This is an internal Node symbol used by functions returning multiple
// arguments, e.g. ['bytesRead', 'buffer'] for fs.read().
const kCustomPromisifyArgsSymbol = Symbol.for(
    "nodejs.util.promisify.customArgs",
);

export const customPromisifyArgs = kCustomPromisifyArgsSymbol;

export function promisify(
    original,
) {
    validateFunction(original, "original");
    if (original[kCustomPromisifiedSymbol]) {
        const fn = original[kCustomPromisifiedSymbol];

        validateFunction(fn, "util.promisify.custom");

        return Object.defineProperty(fn, kCustomPromisifiedSymbol, {
            value: fn,
            enumerable: false,
            writable: false,
            configurable: true,
        });
    }

    // Names to create an object from in case the callback receives multiple
    // arguments, e.g. ['bytesRead', 'buffer'] for fs.read.
    const argumentNames = original[kCustomPromisifyArgsSymbol];
    function fn(...args) {
        return new Promise((resolve, reject) => {
            args.push((err, ...values) => {
                if (err) {
                    return reject(err);
                }
                if (argumentNames !== undefined && values.length > 1) {
                    const obj = {};
                    for (let i = 0; i < argumentNames.length; i++) {
                        obj[argumentNames[i]] = values[i];
                    }
                    resolve(obj);
                } else {
                    resolve(values[0]);
                }
            });
            try {
                Reflect.apply(original, this, args);
            } catch (err) {
                return reject(err);
            }
        });
    }

    Object.setPrototypeOf(fn, Object.getPrototypeOf(original));

    Object.defineProperty(fn, kCustomPromisifiedSymbol, {
        value: fn,
        enumerable: false,
        writable: false,
        configurable: true,
    });
    return Object.defineProperties(
        fn,
        Object.getOwnPropertyDescriptors(original),
    );
}

promisify.custom = kCustomPromisifiedSymbol;

const colorRegExp = /\u001b\[\d\d?m/g; // eslint-disable-line no-control-regex

export function removeColors(str) {
    return String.prototype.replace(str, colorRegExp, '');
}

export function isError(e) {
    // An error could be an instance of Error while not being a native error
    // or could be from a different realm and not be instance of Error but still
    // be a native error.
    return e instanceof Error ||
        (e !== null && typeof e === 'object' && Object.prototype.toString.call(e) === '[object Error]');
}

export const kEmptyObject = Object.freeze(Object.create(null));

export function lazyDOMException(msg, name) {
    let e = new Error(msg)
    e.name = name;
    return e;
}

export function filterDuplicateStrings(items, low) {
    const map = new SafeMap();
    for (let i = 0; i < items.length; i++) {
        const item = items[i];
        const key = String.prototype.toLowerCase.call(item);
        if (low) {
            map.set(key, key);
        } else {
            map.set(key, item);
        }
    }
    return Array.prototype.sort.call(Array.from(map.values()));
}

export function cachedResult(fn) {
    let result;
    return () => {
        if (result === undefined)
            result = fn();
        return Array.prototype.slice.call(result);
    };
}

export default {
    createDeferredPromise,
    customInspectSymbol,
    kEnumerableProperty,
    normalizeEncoding,
    sleep,
    once,
    deprecate,
    emitExperimentalWarning,
    promisify,
    removeColors,
    isError,
    kEmptyObject,
    cachedResult,
    filterDuplicateStrings
};