2023-01-02 16:00:42 -05:00
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2021-02-04 17:18:32 -05:00
"use strict" ;
2019-03-26 08:22:07 -04:00
2020-03-28 13:03:49 -04:00
( ( window ) => {
2021-07-02 06:18:30 -04:00
const {
Array ,
ArrayPrototypeFill ,
2021-10-10 11:20:30 -04:00
ArrayPrototypeMap ,
2023-03-05 17:18:13 -05:00
ArrayPrototypePush ,
Error ,
2021-10-07 12:39:27 -04:00
ErrorCaptureStackTrace ,
2023-03-05 17:18:13 -05:00
MapPrototypeDelete ,
2021-07-02 06:18:30 -04:00
MapPrototypeGet ,
2022-08-01 11:17:55 -04:00
MapPrototypeHas ,
2021-07-02 06:18:30 -04:00
MapPrototypeSet ,
2023-03-05 17:18:13 -05:00
ObjectAssign ,
2023-05-21 16:23:28 -04:00
ObjectDefineProperty ,
2023-03-05 17:18:13 -05:00
ObjectFreeze ,
ObjectFromEntries ,
2023-04-30 04:50:24 -04:00
ObjectKeys ,
2023-03-05 17:18:13 -05:00
Promise ,
2023-04-30 04:50:24 -04:00
PromiseReject ,
PromiseResolve ,
2021-07-02 06:18:30 -04:00
PromisePrototypeThen ,
2023-06-06 05:01:28 -04:00
Proxy ,
2023-03-05 17:18:13 -05:00
RangeError ,
ReferenceError ,
2023-04-19 10:22:41 -04:00
ReflectHas ,
2023-04-30 04:50:24 -04:00
ReflectApply ,
2023-03-13 06:24:31 -04:00
SafeArrayIterator ,
2023-04-14 16:23:28 -04:00
SafeMap ,
2023-01-26 06:26:42 -05:00
SafePromisePrototypeFinally ,
2022-02-16 13:53:17 -05:00
StringPrototypeSlice ,
2023-03-05 17:18:13 -05:00
StringPrototypeSplit ,
2021-11-25 13:49:09 -05:00
SymbolFor ,
2023-03-05 17:18:13 -05:00
SyntaxError ,
TypeError ,
URIError ,
2023-05-01 09:30:02 -04:00
setQueueMicrotask ,
2021-07-02 06:18:30 -04:00
} = window . _ _bootstrap . primordials ;
2023-04-30 04:50:24 -04:00
const { ops , asyncOps } = window . Deno . core ;
2021-07-02 06:18:30 -04:00
2023-03-05 17:18:13 -05:00
const build = {
target : "unknown" ,
arch : "unknown" ,
os : "unknown" ,
vendor : "unknown" ,
env : undefined ,
} ;
function setBuildInfo ( target ) {
const { 0 : arch , 1 : vendor , 2 : os , 3 : env } = StringPrototypeSplit (
target ,
"-" ,
4 ,
) ;
build . target = target ;
build . arch = arch ;
build . vendor = vendor ;
build . os = os ;
build . env = env ;
ObjectFreeze ( build ) ;
}
2021-05-03 11:30:41 -04:00
const errorMap = { } ;
// Builtin v8 / JS errors
registerErrorClass ( "Error" , Error ) ;
registerErrorClass ( "RangeError" , RangeError ) ;
registerErrorClass ( "ReferenceError" , ReferenceError ) ;
registerErrorClass ( "SyntaxError" , SyntaxError ) ;
registerErrorClass ( "TypeError" , TypeError ) ;
registerErrorClass ( "URIError" , URIError ) ;
2021-03-31 10:37:38 -04:00
let nextPromiseId = 1 ;
2023-04-14 16:23:28 -04:00
const promiseMap = new SafeMap ( ) ;
2021-04-07 08:38:54 -04:00
const RING _SIZE = 4 * 1024 ;
const NO _PROMISE = null ; // Alias to null is faster than plain nulls
2021-07-02 06:18:30 -04:00
const promiseRing = ArrayPrototypeFill ( new Array ( RING _SIZE ) , NO _PROMISE ) ;
2021-11-25 13:49:09 -05:00
// TODO(bartlomieju): it future use `v8::Private` so it's not visible
// to users. Currently missing bindings.
const promiseIdSymbol = SymbolFor ( "Deno.core.internalPromiseId" ) ;
2019-04-24 21:43:06 -04:00
2022-02-16 13:53:17 -05:00
let opCallTracingEnabled = false ;
2023-04-14 16:23:28 -04:00
const opCallTraces = new SafeMap ( ) ;
2022-02-16 13:53:17 -05:00
function enableOpCallTracing ( ) {
opCallTracingEnabled = true ;
}
2022-02-25 10:14:46 -05:00
function isOpCallTracingEnabled ( ) {
return opCallTracingEnabled ;
}
2023-04-30 04:50:24 -04:00
function movePromise ( 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 ;
MapPrototypeSet ( promiseMap , oldPromiseId , oldPromise ) ;
}
return promiseRing [ idx ] = NO _PROMISE ;
}
2021-04-07 08:38:54 -04:00
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 ;
2021-07-02 06:18:30 -04:00
MapPrototypeSet ( promiseMap , oldPromiseId , oldPromise ) ;
2021-04-07 08:38:54 -04:00
}
// 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 ) {
2021-07-02 06:18:30 -04:00
const promise = MapPrototypeGet ( promiseMap , promiseId ) ;
MapPrototypeDelete ( promiseMap , promiseId ) ;
2021-04-07 08:38:54 -04:00
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 ;
}
2022-03-11 11:18:49 -05:00
function hasPromise ( promiseId ) {
// Check if out of ring bounds, fallback to map
const outOfBounds = promiseId < nextPromiseId - RING _SIZE ;
if ( outOfBounds ) {
return MapPrototypeHas ( promiseMap , promiseId ) ;
}
// Otherwise check it in ring
const idx = promiseId % RING _SIZE ;
return promiseRing [ idx ] != NO _PROMISE ;
}
2023-04-13 20:41:32 -04:00
const macrotaskCallbacks = [ ] ;
const nextTickCallbacks = [ ] ;
function setMacrotaskCallback ( cb ) {
ArrayPrototypePush ( macrotaskCallbacks , cb ) ;
}
function setNextTickCallback ( cb ) {
ArrayPrototypePush ( nextTickCallbacks , cb ) ;
}
// This function has variable number of arguments. The last argument describes
// if there's a "next tick" scheduled by the Node.js compat layer. Arguments
// before last are alternating integers and any values that describe the
// responses of async ops.
function eventLoopTick ( ) {
// First respond to all pending ops.
for ( let i = 0 ; i < arguments . length - 1 ; i += 2 ) {
2021-04-09 11:55:33 -04:00
const promiseId = arguments [ i ] ;
const res = arguments [ i + 1 ] ;
const promise = getPromise ( promiseId ) ;
promise . resolve ( res ) ;
2019-03-14 19:17:52 -04:00
}
2023-04-13 20:41:32 -04:00
// Drain nextTick queue if there's a tick scheduled.
if ( arguments [ arguments . length - 1 ] ) {
for ( let i = 0 ; i < nextTickCallbacks . length ; i ++ ) {
nextTickCallbacks [ i ] ( ) ;
}
} else {
ops . op _run _microtasks ( ) ;
}
// Finally drain macrotask queue.
for ( let i = 0 ; i < macrotaskCallbacks . length ; i ++ ) {
const cb = macrotaskCallbacks [ i ] ;
while ( true ) {
const res = cb ( ) ;
2023-06-14 10:21:06 -04:00
// If callback returned `undefined` then it has no work to do, we don't
// need to perform microtask checkpoint.
if ( res === undefined ) {
break ;
}
2023-04-13 20:41:32 -04:00
ops . op _run _microtasks ( ) ;
2023-06-14 10:21:06 -04:00
// If callback returned `true` then it has no more work to do, stop
// calling it then.
2023-04-13 20:41:32 -04:00
if ( res === true ) {
break ;
}
}
}
2019-03-14 19:17:52 -04:00
}
2021-04-21 20:50:50 -04:00
function registerErrorClass ( className , errorClass ) {
2021-05-03 11:30:41 -04:00
registerErrorBuilder ( className , ( msg ) => new errorClass ( msg ) ) ;
}
function registerErrorBuilder ( className , errorBuilder ) {
2021-04-21 20:50:50 -04:00
if ( typeof errorMap [ className ] !== "undefined" ) {
throw new TypeError ( ` Error class for " ${ className } " already registered ` ) ;
2021-03-20 12:51:08 -04:00
}
2021-05-03 11:30:41 -04:00
errorMap [ className ] = errorBuilder ;
2019-03-14 19:17:52 -04:00
}
2022-08-11 05:57:20 -04:00
function buildCustomError ( className , message , code ) {
2022-12-13 16:59:21 -05:00
let error ;
try {
error = errorMap [ className ] ? . ( message ) ;
} catch ( e ) {
throw new Error (
` Unsable to build custom error for " ${ className } " \n ${ e . message } ` ,
) ;
}
2022-08-11 05:57:20 -04:00
// Strip buildCustomError() calls from stack trace
if ( typeof error == "object" ) {
ErrorCaptureStackTrace ( error , buildCustomError ) ;
if ( code ) {
error . code = code ;
}
}
return error ;
}
2023-04-30 04:50:24 -04:00
function unwrapOpError ( hideFunction ) {
return ( res ) => {
// .$err_class_name is a special key that should only exist on errors
const className = res ? . $err _class _name ;
if ( ! className ) {
return res ;
}
const errorBuilder = errorMap [ className ] ;
const err = errorBuilder ? errorBuilder ( res . message ) : new Error (
` Unregistered error class: " ${ className } " \n ${ res . message } \n Classes of errors returned from ops should be registered via Deno.core.registerErrorClass(). ` ,
) ;
// Set .code if error was a known OS error, see error_codes.rs
if ( res . code ) {
err . code = res . code ;
}
// Strip unwrapOpResult() and errorBuilder() calls from stack trace
ErrorCaptureStackTrace ( err , hideFunction ) ;
throw err ;
} ;
}
function unwrapOpResultNewPromise ( id , res , hideFunction ) {
2021-04-09 11:55:33 -04:00
// .$err_class_name is a special key that should only exist on errors
if ( res ? . $err _class _name ) {
const className = res . $err _class _name ;
2021-05-03 11:30:41 -04:00
const errorBuilder = errorMap [ className ] ;
2021-10-07 12:39:27 -04:00
const err = errorBuilder ? errorBuilder ( res . message ) : new Error (
` Unregistered error class: " ${ className } " \n ${ res . message } \n Classes of errors returned from ops should be registered via Deno.core.registerErrorClass(). ` ,
) ;
2021-11-04 11:44:34 -04:00
// Set .code if error was a known OS error, see error_codes.rs
if ( res . code ) {
err . code = res . code ;
}
2021-10-07 12:39:27 -04:00
// Strip unwrapOpResult() and errorBuilder() calls from stack trace
2023-04-30 04:50:24 -04:00
ErrorCaptureStackTrace ( err , hideFunction ) ;
return PromiseReject ( err ) ;
2020-08-07 16:47:18 -04:00
}
2023-04-30 04:50:24 -04:00
const promise = PromiseResolve ( res ) ;
promise [ promiseIdSymbol ] = id ;
return promise ;
}
/ *
Basic codegen .
TODO ( mmastrac ) : automate this ( handlebars ? )
let s = "" ;
const vars = "abcdefghijklm" ;
for ( let i = 0 ; i < 10 ; i ++ ) {
let args = "" ;
for ( let j = 0 ; j < i ; j ++ ) {
args += ` ${ vars [ j ] } , ` ;
}
s += `
case $ { i } :
fn = function async _op _$ { i } ( $ { args } ) {
const id = nextPromiseId ++ ;
try {
const maybeResult = originalOp ( id , $ { args } ) ;
if ( maybeResult !== undefined ) {
movePromise ( id ) ;
return unwrapOpResultNewPromise ( id , maybeResult , async _op _$ { i } ) ;
}
} catch ( err ) {
movePromise ( id ) ;
ErrorCaptureStackTrace ( err , async _op _$ { i } ) ;
return PromiseReject ( err ) ;
}
let promise = PromisePrototypeThen ( setPromise ( id ) , unwrapOpError ( eventLoopTick ) ) ;
promise = handleOpCallTracing ( opName , id , promise ) ;
promise [ promiseIdSymbol ] = id ;
return promise ;
} ;
break ;
` ;
}
* /
// This function is called once per async stub
function asyncStub ( opName , args ) {
setUpAsyncStub ( opName ) ;
return ReflectApply ( ops [ opName ] , undefined , args ) ;
}
function setUpAsyncStub ( opName ) {
const originalOp = asyncOps [ opName ] ;
let fn ;
// The body of this switch statement can be generated using the script above.
switch ( originalOp . length - 1 ) {
case 0 :
fn = function async _op _0 ( ) {
const id = nextPromiseId ++ ;
try {
const maybeResult = originalOp ( id ) ;
if ( maybeResult !== undefined ) {
movePromise ( id ) ;
return unwrapOpResultNewPromise ( id , maybeResult , async _op _0 ) ;
}
} catch ( err ) {
movePromise ( id ) ;
ErrorCaptureStackTrace ( err , async _op _0 ) ;
return PromiseReject ( err ) ;
}
let promise = PromisePrototypeThen (
setPromise ( id ) ,
unwrapOpError ( eventLoopTick ) ,
) ;
promise = handleOpCallTracing ( opName , id , promise ) ;
promise [ promiseIdSymbol ] = id ;
return promise ;
} ;
break ;
case 1 :
fn = function async _op _1 ( a ) {
const id = nextPromiseId ++ ;
try {
const maybeResult = originalOp ( id , a ) ;
if ( maybeResult !== undefined ) {
movePromise ( id ) ;
return unwrapOpResultNewPromise ( id , maybeResult , async _op _1 ) ;
}
} catch ( err ) {
movePromise ( id ) ;
ErrorCaptureStackTrace ( err , async _op _1 ) ;
return PromiseReject ( err ) ;
}
let promise = PromisePrototypeThen (
setPromise ( id ) ,
unwrapOpError ( eventLoopTick ) ,
) ;
promise = handleOpCallTracing ( opName , id , promise ) ;
promise [ promiseIdSymbol ] = id ;
return promise ;
} ;
break ;
case 2 :
fn = function async _op _2 ( a , b ) {
const id = nextPromiseId ++ ;
try {
const maybeResult = originalOp ( id , a , b ) ;
if ( maybeResult !== undefined ) {
movePromise ( id ) ;
return unwrapOpResultNewPromise ( id , maybeResult , async _op _2 ) ;
}
} catch ( err ) {
movePromise ( id ) ;
ErrorCaptureStackTrace ( err , async _op _2 ) ;
return PromiseReject ( err ) ;
}
let promise = PromisePrototypeThen (
setPromise ( id ) ,
unwrapOpError ( eventLoopTick ) ,
) ;
promise = handleOpCallTracing ( opName , id , promise ) ;
promise [ promiseIdSymbol ] = id ;
return promise ;
} ;
break ;
case 3 :
fn = function async _op _3 ( a , b , c ) {
const id = nextPromiseId ++ ;
try {
const maybeResult = originalOp ( id , a , b , c ) ;
if ( maybeResult !== undefined ) {
movePromise ( id ) ;
return unwrapOpResultNewPromise ( id , maybeResult , async _op _3 ) ;
}
} catch ( err ) {
movePromise ( id ) ;
ErrorCaptureStackTrace ( err , async _op _3 ) ;
return PromiseReject ( err ) ;
}
let promise = PromisePrototypeThen (
setPromise ( id ) ,
unwrapOpError ( eventLoopTick ) ,
) ;
promise = handleOpCallTracing ( opName , id , promise ) ;
promise [ promiseIdSymbol ] = id ;
return promise ;
} ;
break ;
case 4 :
fn = function async _op _4 ( a , b , c , d ) {
const id = nextPromiseId ++ ;
try {
const maybeResult = originalOp ( id , a , b , c , d ) ;
if ( maybeResult !== undefined ) {
movePromise ( id ) ;
return unwrapOpResultNewPromise ( id , maybeResult , async _op _4 ) ;
}
} catch ( err ) {
movePromise ( id ) ;
ErrorCaptureStackTrace ( err , async _op _4 ) ;
return PromiseReject ( err ) ;
}
let promise = PromisePrototypeThen (
setPromise ( id ) ,
unwrapOpError ( eventLoopTick ) ,
) ;
promise = handleOpCallTracing ( opName , id , promise ) ;
promise [ promiseIdSymbol ] = id ;
return promise ;
} ;
break ;
case 5 :
fn = function async _op _5 ( a , b , c , d , e ) {
const id = nextPromiseId ++ ;
try {
const maybeResult = originalOp ( id , a , b , c , d , e ) ;
if ( maybeResult !== undefined ) {
movePromise ( id ) ;
return unwrapOpResultNewPromise ( id , maybeResult , async _op _5 ) ;
}
} catch ( err ) {
movePromise ( id ) ;
ErrorCaptureStackTrace ( err , async _op _5 ) ;
return PromiseReject ( err ) ;
}
let promise = PromisePrototypeThen (
setPromise ( id ) ,
unwrapOpError ( eventLoopTick ) ,
) ;
promise = handleOpCallTracing ( opName , id , promise ) ;
promise [ promiseIdSymbol ] = id ;
return promise ;
} ;
break ;
case 6 :
fn = function async _op _6 ( a , b , c , d , e , f ) {
const id = nextPromiseId ++ ;
try {
const maybeResult = originalOp ( id , a , b , c , d , e , f ) ;
if ( maybeResult !== undefined ) {
movePromise ( id ) ;
return unwrapOpResultNewPromise ( id , maybeResult , async _op _6 ) ;
}
} catch ( err ) {
movePromise ( id ) ;
ErrorCaptureStackTrace ( err , async _op _6 ) ;
return PromiseReject ( err ) ;
}
let promise = PromisePrototypeThen (
setPromise ( id ) ,
unwrapOpError ( eventLoopTick ) ,
) ;
promise = handleOpCallTracing ( opName , id , promise ) ;
promise [ promiseIdSymbol ] = id ;
return promise ;
} ;
break ;
case 7 :
fn = function async _op _7 ( a , b , c , d , e , f , g ) {
const id = nextPromiseId ++ ;
try {
const maybeResult = originalOp ( id , a , b , c , d , e , f , g ) ;
if ( maybeResult !== undefined ) {
movePromise ( id ) ;
return unwrapOpResultNewPromise ( id , maybeResult , async _op _7 ) ;
}
} catch ( err ) {
movePromise ( id ) ;
ErrorCaptureStackTrace ( err , async _op _7 ) ;
return PromiseReject ( err ) ;
}
let promise = PromisePrototypeThen (
setPromise ( id ) ,
unwrapOpError ( eventLoopTick ) ,
) ;
promise = handleOpCallTracing ( opName , id , promise ) ;
promise [ promiseIdSymbol ] = id ;
return promise ;
} ;
break ;
case 8 :
fn = function async _op _8 ( a , b , c , d , e , f , g , h ) {
const id = nextPromiseId ++ ;
try {
const maybeResult = originalOp ( id , a , b , c , d , e , f , g , h ) ;
if ( maybeResult !== undefined ) {
movePromise ( id ) ;
return unwrapOpResultNewPromise ( id , maybeResult , async _op _8 ) ;
}
} catch ( err ) {
movePromise ( id ) ;
ErrorCaptureStackTrace ( err , async _op _8 ) ;
return PromiseReject ( err ) ;
}
let promise = PromisePrototypeThen (
setPromise ( id ) ,
unwrapOpError ( eventLoopTick ) ,
) ;
promise = handleOpCallTracing ( opName , id , promise ) ;
promise [ promiseIdSymbol ] = id ;
return promise ;
} ;
break ;
case 9 :
fn = function async _op _9 ( a , b , c , d , e , f , g , h , i ) {
const id = nextPromiseId ++ ;
try {
const maybeResult = originalOp ( id , a , b , c , d , e , f , g , h , i ) ;
if ( maybeResult !== undefined ) {
movePromise ( id ) ;
return unwrapOpResultNewPromise ( id , maybeResult , async _op _9 ) ;
}
} catch ( err ) {
movePromise ( id ) ;
ErrorCaptureStackTrace ( err , async _op _9 ) ;
return PromiseReject ( err ) ;
}
let promise = PromisePrototypeThen (
setPromise ( id ) ,
unwrapOpError ( eventLoopTick ) ,
) ;
promise = handleOpCallTracing ( opName , id , promise ) ;
promise [ promiseIdSymbol ] = id ;
return promise ;
} ;
break ;
default :
throw new Error (
` Too many arguments for async op codegen (length of ${ opName } was ${
originalOp . length - 1
} ) ` ,
) ;
}
2023-05-21 16:23:28 -04:00
ObjectDefineProperty ( fn , "name" , {
value : opName ,
configurable : false ,
writable : false ,
} ) ;
2023-04-30 04:50:24 -04:00
return ( ops [ opName ] = fn ) ;
2020-08-07 16:47:18 -04:00
}
2023-02-23 14:50:15 -05:00
function opAsync ( name , ... args ) {
2023-03-31 11:58:21 -04:00
const id = nextPromiseId ++ ;
2023-02-23 14:50:15 -05:00
try {
2023-04-30 04:50:24 -04:00
const maybeResult = asyncOps [ name ] ( id , ... new SafeArrayIterator ( args ) ) ;
if ( maybeResult !== undefined ) {
movePromise ( id ) ;
return unwrapOpResultNewPromise ( id , maybeResult , opAsync ) ;
}
2023-02-23 14:50:15 -05:00
} catch ( err ) {
2023-04-30 04:50:24 -04:00
movePromise ( id ) ;
if ( ! ReflectHas ( asyncOps , name ) ) {
return PromiseReject ( new TypeError ( ` ${ name } is not a registered op ` ) ) ;
2023-04-19 10:22:41 -04:00
}
2023-04-30 04:50:24 -04:00
ErrorCaptureStackTrace ( err , opAsync ) ;
return PromiseReject ( err ) ;
2022-10-28 07:20:17 -04:00
}
2023-04-30 04:50:24 -04:00
let promise = PromisePrototypeThen (
setPromise ( id ) ,
unwrapOpError ( eventLoopTick ) ,
) ;
2023-02-23 14:50:15 -05:00
promise = handleOpCallTracing ( name , id , promise ) ;
promise [ promiseIdSymbol ] = id ;
return promise ;
2022-10-28 07:20:17 -04:00
}
function handleOpCallTracing ( opName , promiseId , p ) {
2022-02-16 13:53:17 -05:00
if ( opCallTracingEnabled ) {
const stack = StringPrototypeSlice ( new Error ( ) . stack , 6 ) ;
MapPrototypeSet ( opCallTraces , promiseId , { opName , stack } ) ;
2023-01-26 06:26:42 -05:00
return SafePromisePrototypeFinally (
2022-02-16 13:53:17 -05:00
p ,
( ) => MapPrototypeDelete ( opCallTraces , promiseId ) ,
) ;
2022-12-06 15:58:18 -05:00
} else {
return p ;
2022-02-16 13:53:17 -05:00
}
2022-10-28 07:20:17 -04:00
}
2022-03-11 11:18:49 -05:00
function refOp ( promiseId ) {
if ( ! hasPromise ( promiseId ) ) {
return ;
}
2022-08-11 09:56:56 -04:00
ops . op _ref _op ( promiseId ) ;
2022-03-11 11:18:49 -05:00
}
function unrefOp ( promiseId ) {
if ( ! hasPromise ( promiseId ) ) {
return ;
}
2022-08-11 09:56:56 -04:00
ops . op _unref _op ( promiseId ) ;
2022-03-11 11:18:49 -05:00
}
2020-09-17 12:09:50 -04:00
function resources ( ) {
2022-08-11 09:56:56 -04:00
return ObjectFromEntries ( ops . op _resources ( ) ) ;
2020-09-17 12:09:50 -04:00
}
2021-03-31 10:37:38 -04:00
2021-10-10 11:20:30 -04:00
function metrics ( ) {
2023-01-26 06:26:42 -05:00
const { 0 : aggregate , 1 : perOps } = ops . op _metrics ( ) ;
2021-10-10 11:20:30 -04:00
aggregate . ops = ObjectFromEntries ( ArrayPrototypeMap (
2022-08-11 09:56:56 -04:00
ops . op _op _names ( ) ,
2022-04-08 04:32:48 -04:00
( opName , opId ) => [ opName , perOps [ opId ] ] ,
2021-10-10 11:20:30 -04:00
) ) ;
return aggregate ;
}
2022-08-21 14:16:42 -04:00
let reportExceptionCallback = undefined ;
// Used to report errors thrown from functions passed to `queueMicrotask()`.
// The callback will be passed the thrown error. For example, you can use this
// to dispatch an error event to the global scope.
// In other words, set the implementation for
// https://html.spec.whatwg.org/multipage/webappapis.html#report-the-exception
function setReportExceptionCallback ( cb ) {
if ( typeof cb != "function" ) {
throw new TypeError ( "expected a function" ) ;
}
reportExceptionCallback = cb ;
}
2022-08-11 09:56:56 -04:00
function queueMicrotask ( cb ) {
2022-08-21 14:16:42 -04:00
if ( typeof cb != "function" ) {
throw new TypeError ( "expected a function" ) ;
}
return ops . op _queue _microtask ( ( ) => {
try {
cb ( ) ;
} catch ( error ) {
if ( reportExceptionCallback ) {
reportExceptionCallback ( error ) ;
} else {
throw error ;
}
}
} ) ;
2022-06-07 05:25:10 -04:00
}
2021-06-28 19:43:03 -04:00
// Some "extensions" rely on "BadResource" and "Interrupted" errors in the
// JS code (eg. "deno_net") so they are provided in "Deno.core" but later
// reexported on "Deno.errors"
class BadResource extends Error {
constructor ( msg ) {
super ( msg ) ;
this . name = "BadResource" ;
}
}
2022-02-01 12:06:11 -05:00
const BadResourcePrototype = BadResource . prototype ;
2021-06-28 19:43:03 -04:00
class Interrupted extends Error {
constructor ( msg ) {
super ( msg ) ;
this . name = "Interrupted" ;
}
}
2022-02-01 12:06:11 -05:00
const InterruptedPrototype = Interrupted . prototype ;
2021-06-28 19:43:03 -04:00
2023-02-10 07:06:19 -05:00
const promiseHooks = [
[ ] , // init
[ ] , // before
[ ] , // after
[ ] , // resolve
] ;
2022-09-28 10:09:33 -04:00
function setPromiseHooks ( init , before , after , resolve ) {
2023-02-10 07:06:19 -05:00
const hooks = [ init , before , after , resolve ] ;
for ( let i = 0 ; i < hooks . length ; i ++ ) {
const hook = hooks [ i ] ;
// Skip if no callback was provided for this hook type.
if ( hook == null ) {
continue ;
}
// Verify that the type of `hook` is a function.
if ( typeof hook !== "function" ) {
throw new TypeError ( ` Expected function at position ${ i } ` ) ;
}
// Add the hook to the list.
ArrayPrototypePush ( promiseHooks [ i ] , hook ) ;
}
2022-09-28 10:09:33 -04:00
2023-02-10 07:06:19 -05:00
const wrappedHooks = ArrayPrototypeMap ( promiseHooks , ( hooks ) => {
switch ( hooks . length ) {
case 0 :
return undefined ;
case 1 :
return hooks [ 0 ] ;
case 2 :
return create2xHookWrapper ( hooks [ 0 ] , hooks [ 1 ] ) ;
case 3 :
return create3xHookWrapper ( hooks [ 0 ] , hooks [ 1 ] , hooks [ 2 ] ) ;
default :
return createHookListWrapper ( hooks ) ;
}
2022-09-28 10:09:33 -04:00
2023-02-10 07:06:19 -05:00
// The following functions are used to create wrapper functions that call
// all the hooks in a list of a certain length. The reason to use a
// function that creates a wrapper is to minimize the number of objects
// captured in the closure.
function create2xHookWrapper ( hook1 , hook2 ) {
return function ( promise , parent ) {
hook1 ( promise , parent ) ;
hook2 ( promise , parent ) ;
} ;
}
function create3xHookWrapper ( hook1 , hook2 , hook3 ) {
return function ( promise , parent ) {
hook1 ( promise , parent ) ;
hook2 ( promise , parent ) ;
hook3 ( promise , parent ) ;
} ;
}
function createHookListWrapper ( hooks ) {
return function ( promise , parent ) {
for ( let i = 0 ; i < hooks . length ; i ++ ) {
const hook = hooks [ i ] ;
hook ( promise , parent ) ;
}
} ;
}
} ) ;
ops . op _set _promise _hooks (
wrappedHooks [ 0 ] ,
wrappedHooks [ 1 ] ,
wrappedHooks [ 2 ] ,
wrappedHooks [ 3 ] ,
) ;
2022-09-28 10:09:33 -04:00
}
2023-04-30 04:50:24 -04:00
// Eagerly initialize ops for snapshot purposes
for ( const opName of new SafeArrayIterator ( ObjectKeys ( asyncOps ) ) ) {
setUpAsyncStub ( opName ) ;
}
2023-06-06 05:01:28 -04:00
function ensureFastOps ( ) {
return new Proxy ( { } , {
get ( _target , opName ) {
if ( ops [ opName ] === undefined ) {
throw new Error ( ` Unknown or disabled op ' ${ opName } ' ` ) ;
}
if ( asyncOps [ opName ] !== undefined ) {
return setUpAsyncStub ( opName ) ;
} else {
return ops [ opName ] ;
}
} ,
} ) ;
2023-04-30 04:50:24 -04:00
}
const {
op _close : close ,
op _try _close : tryClose ,
op _read : read ,
op _read _all : readAll ,
op _write : write ,
op _write _all : writeAll ,
op _read _sync : readSync ,
op _write _sync : writeSync ,
op _shutdown : shutdown ,
2023-06-06 05:01:28 -04:00
} = ensureFastOps ( ) ;
2023-04-30 04:50:24 -04:00
2021-04-30 08:13:23 -04:00
// Extra Deno.core.* exports
2021-07-02 06:18:30 -04:00
const core = ObjectAssign ( globalThis . Deno . core , {
2023-04-30 04:50:24 -04:00
asyncStub ,
2023-06-06 05:01:28 -04:00
ensureFastOps ,
2021-04-12 15:55:05 -04:00
opAsync ,
2020-09-17 12:09:50 -04:00
resources ,
2021-10-10 11:20:30 -04:00
metrics ,
2021-05-03 11:30:41 -04:00
registerErrorBuilder ,
2020-08-07 16:47:18 -04:00
registerErrorClass ,
2022-08-11 05:57:20 -04:00
buildCustomError ,
2023-04-13 20:41:32 -04:00
eventLoopTick ,
2021-06-28 19:43:03 -04:00
BadResource ,
2022-02-01 12:06:11 -05:00
BadResourcePrototype ,
2021-06-28 19:43:03 -04:00
Interrupted ,
2022-02-01 12:06:11 -05:00
InterruptedPrototype ,
2023-04-27 18:37:03 -04:00
enableOpCallTracing ,
2022-02-25 10:14:46 -05:00
isOpCallTracingEnabled ,
2022-02-16 13:53:17 -05:00
opCallTraces ,
2022-03-11 11:18:49 -05:00
refOp ,
unrefOp ,
2022-08-21 14:16:42 -04:00
setReportExceptionCallback ,
2022-09-28 10:09:33 -04:00
setPromiseHooks ,
2023-04-30 04:50:24 -04:00
close ,
tryClose ,
read ,
readAll ,
write ,
writeAll ,
readSync ,
writeSync ,
shutdown ,
2022-08-11 09:56:56 -04:00
print : ( msg , isErr ) => ops . op _print ( msg , isErr ) ,
2023-04-13 20:41:32 -04:00
setMacrotaskCallback ,
setNextTickCallback ,
2022-08-11 09:56:56 -04:00
runMicrotasks : ( ) => ops . op _run _microtasks ( ) ,
hasTickScheduled : ( ) => ops . op _has _tick _scheduled ( ) ,
setHasTickScheduled : ( bool ) => ops . op _set _has _tick _scheduled ( bool ) ,
evalContext : (
source ,
specifier ,
) => ops . op _eval _context ( source , specifier ) ,
createHostObject : ( ) => ops . op _create _host _object ( ) ,
encode : ( text ) => ops . op _encode ( text ) ,
decode : ( buffer ) => ops . op _decode ( buffer ) ,
serialize : (
value ,
options ,
errorCallback ,
) => ops . op _serialize ( value , options , errorCallback ) ,
deserialize : ( buffer , options ) => ops . op _deserialize ( buffer , options ) ,
getPromiseDetails : ( promise ) => ops . op _get _promise _details ( promise ) ,
getProxyDetails : ( proxy ) => ops . op _get _proxy _details ( proxy ) ,
2022-09-22 00:35:24 -04:00
isProxy : ( value ) => ops . op _is _proxy ( value ) ,
2022-08-11 09:56:56 -04:00
memoryUsage : ( ) => ops . op _memory _usage ( ) ,
setWasmStreamingCallback : ( fn ) => ops . op _set _wasm _streaming _callback ( fn ) ,
abortWasmStreaming : (
rid ,
error ,
) => ops . op _abort _wasm _streaming ( rid , error ) ,
destructureError : ( error ) => ops . op _destructure _error ( error ) ,
opNames : ( ) => ops . op _op _names ( ) ,
eventLoopHasMoreWork : ( ) => ops . op _event _loop _has _more _work ( ) ,
setPromiseRejectCallback : ( fn ) => ops . op _set _promise _reject _callback ( fn ) ,
2022-09-07 06:51:30 -04:00
byteLength : ( str ) => ops . op _str _byte _length ( str ) ,
2023-03-05 17:18:13 -05:00
build ,
setBuildInfo ,
2020-05-12 11:09:28 -04:00
} ) ;
2021-07-02 06:18:30 -04:00
ObjectAssign ( globalThis . _ _bootstrap , { core } ) ;
2023-04-27 18:37:03 -04:00
const internals = { } ;
ObjectAssign ( globalThis . _ _bootstrap , { internals } ) ;
2021-07-02 06:18:30 -04:00
ObjectAssign ( globalThis . Deno , { core } ) ;
2022-06-07 05:25:10 -04:00
// Direct bindings on `globalThis`
ObjectAssign ( globalThis , { queueMicrotask } ) ;
setQueueMicrotask ( queueMicrotask ) ;
2021-07-02 06:18:30 -04:00
} ) ( globalThis ) ;