// Hardcoded module "node:async_hooks" // Bun is only going to implement AsyncLocalStorage and AsyncResource (partial). // The other functions are deprecated anyways, and would impact performance too much. // API: https://nodejs.org/api/async_hooks.html // // JSC has been patched to include a special global variable $asyncContext which is set to // a constant InternalFieldTuple<[AsyncContextData, never]>. `get` and `set` read/write to the // first element of this tuple. Inside of PromiseOperations.js, we "snapshot" the context (store it // in the promise reaction) and then just before we call .then, we restore it. // // This means context tracking is *kind-of* manual. If we recieve a callback in native code // - In Zig, call jsValue.withAsyncContextIfNeeded(); which returns another JSValue. Store that and // then run .call() on it later. // - In C++, call AsyncContextFrame::withAsyncContextIfNeeded(jsValue). Then to call it, // use AsyncContextFrame:: call(...) instead of JSC:: call. // // The above functions will return the same JSFunction if the context is empty, and there are many // other checks to ensure that AsyncLocalStorage has virtually no impact on performance when not in // use. But the nature of this approach makes the implementation *itself* very low-impact on performance. // // AsyncContextData is an immutable array managed in here, formatted [key, value, key, value] where // each key is an AsyncLocalStorage object and the value is the associated value. // const { cleanupLater, setAsyncHooksEnabled } = $lazy("async_hooks"); function get(): ReadonlyArray | undefined { $debug("get", $getInternalField($asyncContext, 0)); return $getInternalField($asyncContext, 0); } function set(contextValue: ReadonlyArray | undefined) { $debug("set", contextValue); return $putInternalField($asyncContext, 0, contextValue); } class AsyncLocalStorage { #disableCalled = false; constructor() { setAsyncHooksEnabled(true); } static bind(fn, ...args: any) { return this.snapshot().bind(null, fn, ...args); } static snapshot() { var context = get(); return (fn, ...args) => { var prev = get(); set(context); try { return fn(...args); } catch (error) { throw error; } finally { set(prev); } }; } enterWith(store) { cleanupLater(); var context = get(); if (!context) { set([this, store]); return; } var { length } = context; for (var i = 0; i < length; i += 2) { if (context[i] === this) { const clone = context.slice(); clone[i + 1] = store; set(clone); return; } } set(context.concat(this, store)); } exit(cb, ...args) { return this.run(undefined, cb, ...args); } run(store, callback, ...args) { var context = get() as any[]; // we make sure to .slice() before mutating var hasPrevious = false; var previous; var i = 0; var contextWasInit = !context; if (contextWasInit) { set((context = [this, store])); } else { // it's safe to mutate context now that it was cloned context = context!.slice(); i = context.indexOf(this); if (i > -1) { hasPrevious = true; previous = context[i + 1]; context[i + 1] = store; } else { context.push(this, store); } set(context); } try { return callback(...args); } catch (e) { throw e; } finally { // Note: early `return` will prevent `throw` above from working. I think... // Set AsyncContextFrame to undefined if we are out of context values if (!this.#disableCalled) { var context2 = get()! as any[]; if (context2 === context && contextWasInit) { set(undefined); } else { context2 = context2.slice(); // array is cloned here if (hasPrevious) { context2[i + 1] = previous; set(context2); } else { context2.splice(i, 2); set(context2.length ? context2 : undefined); } } } } } disable() { // In this case, we actually do want to mutate the context state if (!this.#disableCalled) { var context = get() as any[]; if (context) { var { length } = context; for (var i = 0; i < length; i += 2) { if (context[i] === this) { context.splice(i, 2); set(context.length ? context : undefined); break; } } } this.#disableCalled = true; } } getStore() { var context = get(); if (!context) return; var { length } = context; for (var i = 0; i < length; i += 2) { if (context[i] === this) return context[i + 1]; } } } class AsyncResource { type; #snapshot; constructor(type, options) { if (typeof type !== "string") { throw new TypeError('The "type" argument must be of type string. Received type ' + typeof type); } setAsyncHooksEnabled(true); this.type = type; this.#snapshot = get(); } emitBefore() { return true; } emitAfter() { return true; } asyncId() { return 0; } triggerAsyncId() { return 0; } emitDestroy() { // } runInAsyncScope(fn, thisArg, ...args) { var prev = get(); set(this.#snapshot); try { return fn.apply(thisArg, args); } catch (error) { throw error; } finally { set(prev); } } } // The rest of async_hooks is not implemented and is stubbed with no-ops and warnings. function createWarning(message) { let warned = false; var wrapped = function () { if (warned) return; // zx does not need createHook to function const isFromZX = new Error().stack!.includes("zx/build/core.js"); if (isFromZX) return; warned = true; console.warn("[bun] Warning:", message); }; return wrapped; } const createHookNotImpl = createWarning( "async_hooks.createHook is not implemented in Bun. Hooks can still be created but will never be called.", ); function createHook(callbacks) { return { enable: createHookNotImpl, disable: createHookNotImpl, }; } const executionAsyncIdNotImpl = createWarning( "async_hooks.executionAsyncId/triggerAsyncId are not implemented in Bun. It will return 0 every time.", ); function executionAsyncId() { executionAsyncIdNotImpl(); return 0; } function triggerAsyncId() { return 0; } const executionAsyncResourceWarning = createWarning( "async_hooks.executionAsyncResource is not implemented in Bun. It returns a reference to process.stdin every time.", ); function executionAsyncResource() { executionAsyncResourceWarning(); return process.stdin; } const asyncWrapProviders = { NONE: 0, DIRHANDLE: 1, DNSCHANNEL: 2, ELDHISTOGRAM: 3, FILEHANDLE: 4, FILEHANDLECLOSEREQ: 5, FIXEDSIZEBLOBCOPY: 6, FSEVENTWRAP: 7, FSREQCALLBACK: 8, FSREQPROMISE: 9, GETADDRINFOREQWRAP: 10, GETNAMEINFOREQWRAP: 11, HEAPSNAPSHOT: 12, HTTP2SESSION: 13, HTTP2STREAM: 14, HTTP2PING: 15, HTTP2SETTINGS: 16, HTTPINCOMINGMESSAGE: 17, HTTPCLIENTREQUEST: 18, JSSTREAM: 19, JSUDPWRAP: 20, MESSAGEPORT: 21, PIPECONNECTWRAP: 22, PIPESERVERWRAP: 23, PIPEWRAP: 24, PROCESSWRAP: 25, PROMISE: 26, QUERYWRAP: 27, SHUTDOWNWRAP: 28, SIGNALWRAP: 29, STATWATCHER: 30, STREAMPIPE: 31, TCPCONNECTWRAP: 32, TCPSERVERWRAP: 33, TCPWRAP: 34, TTYWRAP: 35, UDPSENDWRAP: 36, UDPWRAP: 37, SIGINTWATCHDOG: 38, WORKER: 39, WORKERHEAPSNAPSHOT: 40, WRITEWRAP: 41, ZLIB: 42, CHECKPRIMEREQUEST: 43, PBKDF2REQUEST: 44, KEYPAIRGENREQUEST: 45, KEYGENREQUEST: 46, KEYEXPORTREQUEST: 47, CIPHERREQUEST: 48, DERIVEBITSREQUEST: 49, HASHREQUEST: 50, RANDOMBYTESREQUEST: 51, RANDOMPRIMEREQUEST: 52, SCRYPTREQUEST: 53, SIGNREQUEST: 54, TLSWRAP: 55, VERIFYREQUEST: 56, INSPECTORJSBINDING: 57, }; export default { AsyncLocalStorage, createHook, executionAsyncId, triggerAsyncId, executionAsyncResource, asyncWrapProviders, AsyncResource, }; option> Unnamed repository; edit this file 'description' to name the repository.
aboutsummaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2023-04-06fix(node:events): fix abort behaviorGravatar Derrick Farris 3-170/+177
2023-04-06test(node:events): remove `console.log`Gravatar Derrick Farris 1-1/+0
2023-04-06feat(node:events): finish `EE.AsyncIterator` and `node:events.on()`, add ↵Gravatar Derrick Farris 5-369/+276
some tests
2023-04-06wip(node:events): get async iter working, work through test flakinessGravatar Derrick Farris 5-236/+328
2023-04-06wip(node:events): fix `node:events.on` async iter to specGravatar Derrick Farris 16-136/+1116
2023-04-06docs: add a section on uninstalling bun (#2560)Gravatar dave caruso 1-0/+8
2023-04-06docs(cli/bunx): add notice (#2574)Gravatar Jozef Steinhübl 1-0/+4
* docs(cli/bunx): add notice bunx alias bun x * docs: grammar
2023-04-06Fix `toEqual` when the second array has extra array holes (#2580)Gravatar Dylan Conway 3-18/+76
* iterate through remaining indexes, keep prop identifier * tests * format
2023-04-06Add last modify field "mtime" for FileBlob (#1431) (#2491)Gravatar Zhongwei Yao 6-33/+128
* Add lastModified field for FileBlob (#1431) lastModified value is epoch timestamp in millisecond unit. * update according to review comment.
2023-04-06bun-types: infer strict `Subprocess` from `Bun.spawn()` options, part 2 (#2573)Gravatar dave caruso 9-67/+165
2023-04-06cache needs to update, move to another process (#2578)Gravatar Dylan Conway 2-156/+171
2023-04-06fix(ws): export Server (#2575)Gravatar hiroki osame 1-13/+30
2023-04-06docs(CONTRIBUTING): referece development guide (#2576)Gravatar hiroki osame 1-1/+5
2023-04-05rebase (#1501)Gravatar dave caruso 2-144/+305
2023-04-05Update `typecheck` (#2572)Gravatar Colin McDonnell 3-4/+8
* Update typecheck * Test ci * Test ci * Prettify files
2023-04-05prependGravatar Jarred Sumner 1-7/+3
2023-04-05Add tests for `bun test` with preload scripts (#2566)Gravatar Jake Boone 2-1/+107
* Use zsh-compatible syntax in cowsay example zsh interprets the string !" differently than bash or sh, but we can use single quotes in all of them. See https://unix.stackexchange.com/a/497335/548905. * Add tests for bun:test with preload scripts * Look at `stderr` in `bun test --preload` tests
2023-04-05Disable buffering when we clear terminalGravatar Jarred Sumner 1-0/+2
hopefully fixes an issue reported in Discord
2023-04-05PrettierGravatar Jarred Sumner 3-4/+4
2023-04-05fix(fetch.proxy) fix proxy authentication (#2554)Gravatar Ciro Spaciari 3-31/+186
* fix proxy authentication * add auth tests * remove unused
2023-04-05fix: build warnings (#2562)Gravatar hiroki osame 4-4/+1
2023-04-05In Documentation, move --watch before the script name (#2569)Gravatar Lawlzer 1-4/+5
Related message by Jarred: https://discord.com/channels/876711213126520882/876711213126520885/1093286199369682944 If you put `--watch` after the script name, it will not work.
2023-04-05fix `deepEquals` with array holes and accessors (#2557)Gravatar Dylan Conway 2-10/+249
* `deepEqual` handles slow array indexes * another test * oops * remove bad test * compare indexes in non-strict mode * more tests
2023-04-05fix: modules to have null prototype (#2561)Gravatar hiroki osame 2-2/+9
2023-04-04:clock1: :clock2: :clock3:Gravatar Jarred Sumner 1-1/+1
2023-04-04Implement `import.meta.main` (#2556)Gravatar Jarred Sumner 10-8/+89
* Implement `import.meta.main` * Update main-test-1.js * Update fs.test.ts --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
2023-04-04Dylan/fix some failing tests (#2544)Gravatar Jarred Sumner 10-29/+72
* handle `umask()` invalid arguments * move `bktree-fast` to test root, fix postinstall * fix fs test * could be baseline * handle different timezones * accidentally deleted tests * fix hang in `AbortSignal.timeout` * bring abort tests back * Revert "bring abort tests back" This reverts commit 0ff2ad5bf408694ac719b8ba0a38b16070e10201. * bunx node-gyp * bun x * fix typecheck * test * Update inspect.test.js --------- Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
2023-04-04Add npm benchmark (#2555)Gravatar Colin McDonnell 13-1/+271
* Add install bench * Update scripts and readme * remove lockfiles * Format bench * Add dev instructions
2023-04-03Use absolute paths morebun-v0.5.9Gravatar Jarred Sumner 2-6/+11
2023-04-03Fix test failureGravatar Jarred Sumner 1-15/+18