| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 864fe99 commit ded8335
7 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,10 +7,10 @@ const { | |||
| 7 | 7 | MathMin, | |
| 8 | 8 | NumberIsSafeInteger, | |
| 9 | 9 | Promise, | |
| 10 | - PromisePrototypeFinally, | ||
| 11 | 10 | PromisePrototypeThen, | |
| 12 | 11 | PromiseResolve, | |
| 13 | 12 | SafeArrayIterator, | |
| 13 | + SafePromisePrototypeFinally, | ||
| 14 | 14 | Symbol, | |
| 15 | 15 | Uint8Array, | |
| 16 | 16 | } = primordials; | |
@@ -186,12 +186,12 @@ class FileHandle extends EventEmitterMixin(JSTransferable) { | |||
| 186 | 186 | this[kRefs]--; | |
| 187 | 187 | if (this[kRefs] === 0) { | |
| 188 | 188 | this[kFd] = -1; | |
| 189 | - this[kClosePromise] = PromisePrototypeFinally( | ||
| 189 | + this[kClosePromise] = SafePromisePrototypeFinally( | ||
| 190 | 190 | this[kHandle].close(), | |
| 191 | 191 | () => { this[kClosePromise] = undefined; } | |
| 192 | 192 | ); | |
| 193 | 193 | } else { | |
| 194 | - this[kClosePromise] = PromisePrototypeFinally( | ||
| 194 | + this[kClosePromise] = SafePromisePrototypeFinally( | ||
| 195 | 195 | new Promise((resolve, reject) => { | |
| 196 | 196 | this[kCloseResolve] = resolve; | |
| 197 | 197 | this[kCloseReject] = reject; | |
@@ -507,7 +507,7 @@ async function rename(oldPath, newPath) { | |||
| 507 | 507 | ||
| 508 | 508 | async function truncate(path, len = 0) { | |
| 509 | 509 | const fd = await open(path, 'r+'); | |
| 510 | - return PromisePrototypeFinally(ftruncate(fd, len), fd.close); | ||
| 510 | + return SafePromisePrototypeFinally(ftruncate(fd, len), fd.close); | ||
| 511 | 511 | } | |
| 512 | 512 | ||
| 513 | 513 | async function ftruncate(handle, len = 0) { | |
@@ -638,7 +638,7 @@ async function lchmod(path, mode) { | |||
| 638 | 638 | throw new ERR_METHOD_NOT_IMPLEMENTED('lchmod()'); | |
| 639 | 639 | ||
| 640 | 640 | const fd = await open(path, O_WRONLY | O_SYMLINK); | |
| 641 | - return PromisePrototypeFinally(fchmod(fd, mode), fd.close); | ||
| 641 | + return SafePromisePrototypeFinally(fchmod(fd, mode), fd.close); | ||
| 642 | 642 | } | |
| 643 | 643 | ||
| 644 | 644 | async function lchown(path, uid, gid) { | |
@@ -717,7 +717,7 @@ async function writeFile(path, data, options) { | |||
| 717 | 717 | checkAborted(options.signal); | |
| 718 | 718 | ||
| 719 | 719 | const fd = await open(path, flag, options.mode); | |
| 720 | - return PromisePrototypeFinally( | ||
| 720 | + return SafePromisePrototypeFinally( | ||
| 721 | 721 | writeFileHandle(fd, data, options.signal, options.encoding), fd.close); | |
| 722 | 722 | } | |
| 723 | 723 | ||
@@ -742,7 +742,7 @@ async function readFile(path, options) { | |||
| 742 | 742 | checkAborted(options.signal); | |
| 743 | 743 | ||
| 744 | 744 | const fd = await open(path, flag, 0o666); | |
| 745 | - return PromisePrototypeFinally(readFileHandle(fd, options), fd.close); | ||
| 745 | + return SafePromisePrototypeFinally(readFileHandle(fd, options), fd.close); | ||
| 746 | 746 | } | |
| 747 | 747 | ||
| 748 | 748 | module.exports = { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,7 +1,6 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | 3 | const { | |
| 4 | - PromisePrototypeFinally, | ||
| 5 | 4 | StringPrototypeEndsWith, | |
| 6 | 5 | } = primordials; | |
| 7 | 6 | const CJSLoader = require('internal/modules/cjs/loader'); | |
@@ -51,7 +50,7 @@ function runMainESM(mainPath) { | |||
| 51 | 50 | })); | |
| 52 | 51 | } | |
| 53 | 52 | ||
| 54 | - function handleMainPromise(promise) { | ||
| 53 | + async function handleMainPromise(promise) { | ||
| 55 | 54 | // Handle a Promise from running code that potentially does Top-Level Await. | |
| 56 | 55 | // In that case, it makes sense to set the exit code to a specific non-zero | |
| 57 | 56 | // value if the main code never finishes running. | |
@@ -60,7 +59,11 @@ function handleMainPromise(promise) { | |||
| 60 | 59 | process.exitCode = 13; | |
| 61 | 60 | } | |
| 62 | 61 | process.on('exit', handler); | |
| 63 | - return PromisePrototypeFinally(promise, () => process.off('exit', handler)); | ||
| 62 | + try { | ||
| 63 | + return await promise; | ||
| 64 | + } finally { | ||
| 65 | + process.off('exit', handler); | ||
| 66 | + } | ||
| 64 | 67 | } | |
| 65 | 68 | ||
| 66 | 69 | // For backwards compatibility, we have to run a bunch of | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -253,6 +253,8 @@ const { | |||
| 253 | 253 | Map, | |
| 254 | 254 | ObjectFreeze, | |
| 255 | 255 | ObjectSetPrototypeOf, | |
| 256 | + Promise, | ||
| 257 | + PromisePrototypeThen, | ||
| 256 | 258 | Set, | |
| 257 | 259 | SymbolIterator, | |
| 258 | 260 | WeakMap, | |
@@ -384,5 +386,34 @@ primordials.SafeWeakRef = makeSafe( | |||
| 384 | 386 | } | |
| 385 | 387 | ); | |
| 386 | 388 | ||
| 389 | + const SafePromise = makeSafe( | ||
| 390 | + Promise, | ||
| 391 | + class SafePromise extends Promise { | ||
| 392 | + // eslint-disable-next-line no-useless-constructor | ||
| 393 | + constructor(executor) { super(executor); } | ||
| 394 | + } | ||
| 395 | + ); | ||
| 396 | + | ||
| 397 | + primordials.PromisePrototypeCatch = (thisPromise, onRejected) => | ||
| 398 | + PromisePrototypeThen(thisPromise, undefined, onRejected); | ||
| 399 | + | ||
| 400 | + /** | ||
| 401 | + * Attaches a callback that is invoked when the Promise is settled (fulfilled or | ||
| 402 | + * rejected). The resolved value cannot be modified from the callback. | ||
| 403 | + * Prefer using async functions when possible. | ||
| 404 | + * @param {Promise<any>} thisPromise | ||
| 405 | + * @param {() => void) | undefined | null} onFinally The callback to execute | ||
| 406 | + * when the Promise is settled (fulfilled or rejected). | ||
| 407 | + * @returns A Promise for the completion of the callback. | ||
| 408 | + */ | ||
| 409 | + primordials.SafePromisePrototypeFinally = (thisPromise, onFinally) => | ||
| 410 | + // Wrapping on a new Promise is necessary to not expose the SafePromise | ||
| 411 | + // prototype to user-land. | ||
| 412 | + new Promise((a, b) => | ||
| 413 | + new SafePromise((a, b) => PromisePrototypeThen(thisPromise, a, b)) | ||
| 414 | + .finally(onFinally) | ||
| 415 | + .then(a, b) | ||
| 416 | + ); | ||
| 417 | + | ||
| 387 | 418 | ObjectSetPrototypeOf(primordials, null); | |
| 388 | 419 | ObjectFreeze(primordials); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,8 +3,8 @@ | |||
| 3 | 3 | const { | |
| 4 | 4 | FunctionPrototypeBind, | |
| 5 | 5 | Promise, | |
| 6 | - PromisePrototypeFinally, | ||
| 7 | 6 | PromiseReject, | |
| 7 | + SafePromisePrototypeFinally, | ||
| 8 | 8 | } = primordials; | |
| 9 | 9 | ||
| 10 | 10 | const { | |
@@ -71,7 +71,7 @@ function setTimeout(after, value, options = {}) { | |||
| 71 | 71 | } | |
| 72 | 72 | }); | |
| 73 | 73 | return oncancel !== undefined ? | |
| 74 | - PromisePrototypeFinally( | ||
| 74 | + SafePromisePrototypeFinally( | ||
| 75 | 75 | ret, | |
| 76 | 76 | () => signal.removeEventListener('abort', oncancel)) : ret; | |
| 77 | 77 | } | |
@@ -115,7 +115,7 @@ function setImmediate(value, options = {}) { | |||
| 115 | 115 | } | |
| 116 | 116 | }); | |
| 117 | 117 | return oncancel !== undefined ? | |
| 118 | - PromisePrototypeFinally( | ||
| 118 | + SafePromisePrototypeFinally( | ||
| 119 | 119 | ret, | |
| 120 | 120 | () => signal.removeEventListener('abort', oncancel)) : ret; | |
| 121 | 121 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,3 +6,4 @@ SyntaxError: The requested module '../fixtures/es-module-loaders/module-named-ex | |||
| 6 | 6 | at async ModuleJob.run (node:internal/modules/esm/module_job:*:*) | |
| 7 | 7 | at async Loader.import (node:internal/modules/esm/loader:*:*) | |
| 8 | 8 | at async Object.loadESM (node:internal/process/esm_loader:*:*) | |
| 9 | + at async handleMainPromise (node:internal/modules/run_main:*:*) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,3 +6,4 @@ SyntaxError: The requested module './module-named-exports.mjs' does not provide | |||
| 6 | 6 | at async ModuleJob.run (node:internal/modules/esm/module_job:*:*) | |
| 7 | 7 | at async Loader.import (node:internal/modules/esm/loader:*:*) | |
| 8 | 8 | at async Object.loadESM (node:internal/process/esm_loader:*:*) | |
| 9 | + at async handleMainPromise (node:internal/modules/run_main:*:*) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,38 @@ | |||
| 1 | + // Flags: --expose-internals | ||
| 2 | + 'use strict'; | ||
| 3 | + | ||
| 4 | + const common = require('../common'); | ||
| 5 | + const assert = require('assert'); | ||
| 6 | + | ||
| 7 | + const { | ||
| 8 | + PromisePrototypeCatch, | ||
| 9 | + PromisePrototypeThen, | ||
| 10 | + SafePromisePrototypeFinally, | ||
| 11 | + } = require('internal/test/binding').primordials; | ||
| 12 | + | ||
| 13 | + Promise.prototype.catch = common.mustNotCall(); | ||
| 14 | + Promise.prototype.finally = common.mustNotCall(); | ||
| 15 | + Promise.prototype.then = common.mustNotCall(); | ||
| 16 | + | ||
| 17 | + assertIsPromise(PromisePrototypeCatch(Promise.reject(), common.mustCall())); | ||
| 18 | + assertIsPromise(PromisePrototypeThen(test(), common.mustCall())); | ||
| 19 | + assertIsPromise(SafePromisePrototypeFinally(test(), common.mustCall())); | ||
| 20 | + | ||
| 21 | + async function test() { | ||
| 22 | + const catchFn = common.mustCall(); | ||
| 23 | + const finallyFn = common.mustCall(); | ||
| 24 | + | ||
| 25 | + try { | ||
| 26 | + await Promise.reject(); | ||
| 27 | + } catch { | ||
| 28 | + catchFn(); | ||
| 29 | + } finally { | ||
| 30 | + finallyFn(); | ||
| 31 | + } | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + function assertIsPromise(promise) { | ||
| 35 | + // Make sure the returned promise is a genuine %Promise% object and not a | ||
| 36 | + // subclass instance. | ||
| 37 | + assert.strictEqual(Object.getPrototypeOf(promise), Promise.prototype); | ||
| 38 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments