cscg24-wsbx

CSCG 2024 Challenge 'wsbx'
git clone https://git.sinitax.com/sinitax/cscg24-wsbx
Log | Files | Refs | sfeed.txt

comlink-4.3.1.js (11387B)


      1/**
      2 * Copyright 2019 Google Inc. All Rights Reserved.
      3 * Licensed under the Apache License, Version 2.0 (the "License");
      4 * you may not use this file except in compliance with the License.
      5 * You may obtain a copy of the License at
      6 *     http://www.apache.org/licenses/LICENSE-2.0
      7 * Unless required by applicable law or agreed to in writing, software
      8 * distributed under the License is distributed on an "AS IS" BASIS,
      9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     10 * See the License for the specific language governing permissions and
     11 * limitations under the License.
     12 */
     13const proxyMarker = Symbol("Comlink.proxy");
     14const createEndpoint = Symbol("Comlink.endpoint");
     15const releaseProxy = Symbol("Comlink.releaseProxy");
     16const throwMarker = Symbol("Comlink.thrown");
     17const isObject = (val) => (typeof val === "object" && val !== null) || typeof val === "function";
     18/**
     19 * Internal transfer handle to handle objects marked to proxy.
     20 */
     21const proxyTransferHandler = {
     22    canHandle: (val) => {
     23        console.log("checking ", typeof(val), val, isObject(val) && val[proxyMarker], Object.keys(val), Object.keys(val.__proto__));
     24        return isObject(val) && val[proxyMarker];
     25    },
     26    serialize(obj) {
     27        const { port1, port2 } = new MessageChannel();
     28        expose(obj, port1);
     29        return [port2, [port2]];
     30    },
     31    deserialize(port) {
     32        port.start();
     33        return wrap(port);
     34    },
     35};
     36/**
     37 * Internal transfer handler to handle thrown exceptions.
     38 */
     39const throwTransferHandler = {
     40    canHandle: (value) => isObject(value) && throwMarker in value,
     41    serialize({ value }) {
     42        let serialized;
     43        if (value instanceof Error) {
     44            serialized = {
     45                isError: true,
     46                value: {
     47                    message: value.message,
     48                    name: value.name,
     49                    stack: value.stack,
     50                },
     51            };
     52        }
     53        else {
     54            serialized = { isError: false, value };
     55        }
     56        return [serialized, []];
     57    },
     58    deserialize(serialized) {
     59        if (serialized.isError) {
     60            throw Object.assign(new Error(serialized.value.message), serialized.value);
     61        }
     62        throw serialized.value;
     63    },
     64};
     65/**
     66 * Allows customizing the serialization of certain values.
     67 */
     68const transferHandlers = new Map([
     69    ["proxy", proxyTransferHandler],
     70    ["throw", throwTransferHandler],
     71]);
     72function expose(obj, ep = self) {
     73    ep.addEventListener("message", function callback(ev) {
     74        if (!ev || !ev.data) {
     75            return;
     76        }
     77        console.log(ev);
     78        const { id, type, path } = Object.assign({ path: [] }, ev.data);
     79        const argumentList = (ev.data.argumentList || []).map(fromWireValue);
     80        let returnValue;
     81        try {
     82            const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj);
     83            const rawValue = path.reduce((obj, prop) => obj[prop], obj);
     84            switch (type) {
     85                case "GET" /* GET */:
     86                    {
     87                        returnValue = rawValue;
     88                    }
     89                    break;
     90                case "SET" /* SET */:
     91                    {
     92                        parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);
     93                        returnValue = true;
     94                    }
     95                    break;
     96                case "APPLY" /* APPLY */:
     97                    {
     98                        returnValue = rawValue.apply(parent, argumentList);
     99                        console.log("aplly return");
    100                        console.log(returnValue);
    101                        console.log(Object.keys(returnValue.__proto__));
    102                    }
    103                    break;
    104                case "CONSTRUCT" /* CONSTRUCT */:
    105                    {
    106                        const value = new rawValue(...argumentList);
    107                        returnValue = proxy(value);
    108                    }
    109                    break;
    110                case "ENDPOINT" /* ENDPOINT */:
    111                    {
    112                        const { port1, port2 } = new MessageChannel();
    113                        expose(obj, port2);
    114                        returnValue = transfer(port1, [port1]);
    115                    }
    116                    break;
    117                case "RELEASE" /* RELEASE */:
    118                    {
    119                        returnValue = undefined;
    120                    }
    121                    break;
    122                default:
    123                    return;
    124            }
    125        }
    126        catch (value) {
    127            returnValue = { value, [throwMarker]: 0 };
    128        }
    129        Promise.resolve(returnValue)
    130            .catch((value) => {
    131            return { value, [throwMarker]: 0 };
    132        })
    133            .then((returnValue) => {
    134            const [wireValue, transferables] = toWireValue(returnValue);
    135            ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
    136            if (type === "RELEASE" /* RELEASE */) {
    137                // detach and deactive after sending release response above.
    138                ep.removeEventListener("message", callback);
    139                closeEndPoint(ep);
    140            }
    141        });
    142    });
    143    if (ep.start) {
    144        ep.start();
    145    }
    146}
    147function isMessagePort(endpoint) {
    148    return endpoint.constructor.name === "MessagePort";
    149}
    150function closeEndPoint(endpoint) {
    151    if (isMessagePort(endpoint))
    152        endpoint.close();
    153}
    154function wrap(ep, target) {
    155    return createProxy(ep, [], target);
    156}
    157function throwIfProxyReleased(isReleased) {
    158    if (isReleased) {
    159        throw new Error("Proxy has been released and is not useable");
    160    }
    161}
    162function createProxy(ep, path = [], target = function () { }) {
    163    let isProxyReleased = false;
    164    const proxy = new Proxy(target, {
    165        get(_target, prop) {
    166            throwIfProxyReleased(isProxyReleased);
    167            if (prop === releaseProxy) {
    168                return () => {
    169                    return requestResponseMessage(ep, {
    170                        type: "RELEASE" /* RELEASE */,
    171                        path: path.map((p) => p.toString()),
    172                    }).then(() => {
    173                        closeEndPoint(ep);
    174                        isProxyReleased = true;
    175                    });
    176                };
    177            }
    178            if (prop === "then") {
    179                if (path.length === 0) {
    180                    return { then: () => proxy };
    181                }
    182                const r = requestResponseMessage(ep, {
    183                    type: "GET" /* GET */,
    184                    path: path.map((p) => p.toString()),
    185                }).then(fromWireValue);
    186                return r.then.bind(r);
    187            }
    188            return createProxy(ep, [...path, prop]);
    189        },
    190        set(_target, prop, rawValue) {
    191            throwIfProxyReleased(isProxyReleased);
    192            // FIXME: ES6 Proxy Handler `set` methods are supposed to return a
    193            // boolean. To show good will, we return true asynchronously ¯\_(ツ)_/¯
    194            const [value, transferables] = toWireValue(rawValue);
    195            return requestResponseMessage(ep, {
    196                type: "SET" /* SET */,
    197                path: [...path, prop].map((p) => p.toString()),
    198                value,
    199            }, transferables).then(fromWireValue);
    200        },
    201        apply(_target, _thisArg, rawArgumentList) {
    202            throwIfProxyReleased(isProxyReleased);
    203            const last = path[path.length - 1];
    204            if (last === createEndpoint) {
    205                return requestResponseMessage(ep, {
    206                    type: "ENDPOINT" /* ENDPOINT */,
    207                }).then(fromWireValue);
    208            }
    209            // We just pretend that `bind()` didn’t happen.
    210            if (last === "bind") {
    211                return createProxy(ep, path.slice(0, -1));
    212            }
    213            const [argumentList, transferables] = processArguments(rawArgumentList);
    214            return requestResponseMessage(ep, {
    215                type: "APPLY" /* APPLY */,
    216                path: path.map((p) => p.toString()),
    217                argumentList,
    218            }, transferables).then(fromWireValue);
    219        },
    220        construct(_target, rawArgumentList) {
    221            throwIfProxyReleased(isProxyReleased);
    222            const [argumentList, transferables] = processArguments(rawArgumentList);
    223            return requestResponseMessage(ep, {
    224                type: "CONSTRUCT" /* CONSTRUCT */,
    225                path: path.map((p) => p.toString()),
    226                argumentList,
    227            }, transferables).then(fromWireValue);
    228        },
    229    });
    230    return proxy;
    231}
    232function myFlat(arr) {
    233    return Array.prototype.concat.apply([], arr);
    234}
    235function processArguments(argumentList) {
    236    const processed = argumentList.map(toWireValue);
    237    return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];
    238}
    239const transferCache = new WeakMap();
    240function transfer(obj, transfers) {
    241    transferCache.set(obj, transfers);
    242    return obj;
    243}
    244function proxy(obj) {
    245    return Object.assign(obj, { [proxyMarker]: true });
    246}
    247function windowEndpoint(w, context = self, targetOrigin = "*") {
    248    return {
    249        postMessage: (msg, transferables) => w.postMessage(msg, targetOrigin, transferables),
    250        addEventListener: context.addEventListener.bind(context),
    251        removeEventListener: context.removeEventListener.bind(context),
    252    };
    253}
    254function toWireValue(value) {
    255    for (const [name, handler] of transferHandlers) {
    256        if (handler.canHandle(value)) {
    257            const [serializedValue, transferables] = handler.serialize(value);
    258            return [
    259                {
    260                    type: "HANDLER" /* HANDLER */,
    261                    name,
    262                    value: serializedValue,
    263                },
    264                transferables,
    265            ];
    266        }
    267    }
    268    return [
    269        {
    270            type: "RAW" /* RAW */,
    271            value,
    272        },
    273        transferCache.get(value) || [],
    274    ];
    275}
    276function fromWireValue(value) {
    277    switch (value.type) {
    278        case "HANDLER" /* HANDLER */:
    279            return transferHandlers.get(value.name).deserialize(value.value);
    280        case "RAW" /* RAW */:
    281            return value.value;
    282    }
    283}
    284function requestResponseMessage(ep, msg, transfers) {
    285    return new Promise((resolve) => {
    286        const id = generateUUID();
    287        ep.addEventListener("message", function l(ev) {
    288            if (!ev.data || !ev.data.id || ev.data.id !== id) {
    289                return;
    290            }
    291            ep.removeEventListener("message", l);
    292            resolve(ev.data);
    293        });
    294        if (ep.start) {
    295            ep.start();
    296        }
    297        ep.postMessage(Object.assign({ id }, msg), transfers);
    298    });
    299}
    300function generateUUID() {
    301    return new Array(4)
    302        .fill(0)
    303        .map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))
    304        .join("-");
    305}
    306
    307export { createEndpoint, expose, proxy, proxyMarker, releaseProxy, transfer, transferHandlers, windowEndpoint, wrap };
    308//# sourceMappingURL=comlink-4.3.1.js.map