1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-29 10:39:10 -05:00
denoland-deno/core/core.js

161 lines
4.3 KiB
JavaScript
Raw Normal View History

2021-01-10 21:59:07 -05:00
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
// Available on start due to bindings.
2020-05-12 11:09:28 -04:00
const core = window.Deno.core;
const { recv, send } = core;
let opsCache = {};
const errorMap = {};
let nextPromiseId = 1;
const promiseMap = new Map();
const RING_SIZE = 4 * 1024;
const NO_PROMISE = null; // Alias to null is faster than plain nulls
const promiseRing = new Array(RING_SIZE).fill(NO_PROMISE);
function init() {
2020-05-12 11:09:28 -04:00
recv(handleAsyncMsgFromRust);
}
function setPromise(promiseId) {
const idx = promiseId % RING_SIZE;
// Move old promise from ring to map
const oldPromise = promiseRing[idx];
if (oldPromise !== NO_PROMISE) {
const oldPromiseId = promiseId - RING_SIZE;
promiseMap.set(oldPromiseId, oldPromise);
}
// Set new promise
return promiseRing[idx] = newPromise();
}
function getPromise(promiseId) {
// Check if out of ring bounds, fallback to map
const outOfBounds = promiseId < nextPromiseId - RING_SIZE;
if (outOfBounds) {
const promise = promiseMap.get(promiseId);
promiseMap.delete(promiseId);
return promise;
}
// Otherwise take from ring
const idx = promiseId % RING_SIZE;
const promise = promiseRing[idx];
promiseRing[idx] = NO_PROMISE;
return promise;
}
function newPromise() {
let resolve, reject;
const promise = new Promise((resolve_, reject_) => {
resolve = resolve_;
reject = reject_;
});
promise.resolve = resolve;
promise.reject = reject;
return promise;
}
2019-09-30 14:59:44 -04:00
function ops() {
2020-01-02 07:48:46 -05:00
// op id 0 is a special value to retrieve the map of registered ops.
const newOpsCache = Object.fromEntries(send(0));
opsCache = Object.freeze(newOpsCache);
return opsCache;
}
function handleAsyncMsgFromRust() {
for (let i = 0; i < arguments.length; i += 2) {
opAsyncHandler(arguments[i], arguments[i + 1]);
}
}
function dispatch(opName, promiseId, control, zeroCopy) {
return send(opsCache[opName], promiseId, control, zeroCopy);
}
function registerErrorClass(errorName, className, args) {
if (typeof errorMap[errorName] !== "undefined") {
throw new TypeError(`Error class for "${errorName}" already registered`);
}
errorMap[errorName] = [className, args ?? []];
}
function getErrorClassAndArgs(errorName) {
return errorMap[errorName] ?? [undefined, []];
}
function processResponse(res) {
if (!isErr(res)) {
return res;
}
throw processErr(res);
}
// .$err_class_name is a special key that should only exist on errors
function isErr(res) {
return !!(res && res.$err_class_name);
}
function processErr(err) {
const className = err.$err_class_name;
const [ErrorClass, args] = getErrorClassAndArgs(className);
if (!ErrorClass) {
return new Error(
`Unregistered error class: "${className}"\n ${err.message}\n Classes of errors returned from ops should be registered via Deno.core.registerErrorClass().`,
);
}
return new ErrorClass(err.message, ...args);
}
function jsonOpAsync(opName, args = null, zeroCopy = null) {
const promiseId = nextPromiseId++;
const maybeError = dispatch(opName, promiseId, args, zeroCopy);
// Handle sync error (e.g: error parsing args)
if (maybeError) processResponse(maybeError);
return setPromise(promiseId);
}
function jsonOpSync(opName, args = null, zeroCopy = null) {
return processResponse(dispatch(opName, null, args, zeroCopy));
}
function opAsyncHandler(promiseId, res) {
const promise = getPromise(promiseId);
if (!isErr(res)) {
promise.resolve(res);
} else {
promise.reject(processErr(res));
}
}
function binOpSync(opName, args = null, zeroCopy = null) {
return jsonOpSync(opName, args, zeroCopy);
}
function binOpAsync(opName, args = null, zeroCopy = null) {
return jsonOpAsync(opName, args, zeroCopy);
}
function resources() {
return Object.fromEntries(jsonOpSync("op_resources"));
}
function close(rid) {
jsonOpSync("op_close", rid);
}
2020-05-12 11:09:28 -04:00
Object.assign(window.Deno.core, {
binOpAsync,
binOpSync,
jsonOpAsync,
jsonOpSync,
dispatch: send,
dispatchByName: dispatch,
2020-05-12 11:09:28 -04:00
ops,
close,
resources,
registerErrorClass,
init,
2020-05-12 11:09:28 -04:00
});
})(this);