44 Array,
55 ArrayBufferPrototypeGetByteLength,
66 ArrayBufferPrototypeGetDetached,
7+ ArrayBufferPrototypeSlice,
78 AsyncIteratorPrototype,
89 DataViewPrototypeGetBuffer,
910 DataViewPrototypeGetByteLength,
@@ -19,6 +20,7 @@ const {
1920 TypedArrayPrototypeGetBuffer,
2021 TypedArrayPrototypeGetByteLength,
2122 TypedArrayPrototypeGetByteOffset,
23+ Uint8Array,
2224} = primordials ;
2325
2426const {
@@ -31,11 +33,6 @@ const {
3133 copyArrayBuffer,
3234} = internalBinding ( 'buffer' ) ;
3335
34- const {
35- isNonThenable,
36- cloneAsUint8Array : nativeCloneAsUint8Array ,
37- } = internalBinding ( 'webstreams' ) ;
38-
3936const {
4037 inspect,
4138} = require ( 'util' ) ;
@@ -131,7 +128,22 @@ function ArrayBufferViewGetByteOffset(view) {
131128}
132129
133130function cloneAsUint8Array ( view ) {
134- return nativeCloneAsUint8Array ( view ) ;
131+ const buffer = ArrayBufferViewGetBuffer ( view ) ;
132+ const byteOffset = ArrayBufferViewGetByteOffset ( view ) ;
133+ const byteLength = ArrayBufferViewGetByteLength ( view ) ;
134+ return new Uint8Array (
135+ ArrayBufferPrototypeSlice ( buffer , byteOffset , byteOffset + byteLength ) ,
136+ ) ;
137+ }
138+
139+ // True when `value` cannot be a thenable: null, undefined, or a
140+ // non-object non-function primitive. Objects and functions are treated
141+ // as maybe-thenable without looking up `.then` (that lookup is
142+ // observable). Proxies of objects/functions take the maybe-thenable
143+ // path; a Proxy around a primitive is still an object.
144+ function isNonThenable ( value ) {
145+ return value === null ||
146+ ( typeof value !== 'object' && typeof value !== 'function' ) ;
135147}
136148
137149function canCopyArrayBuffer ( toBuffer , toIndex , fromBuffer , fromIndex , count ) {
@@ -332,19 +344,13 @@ function enqueueValueWithSize(controller, value, size) {
332344// arguments passed through to the user callback is observable and must be
333345// preserved.
334346//
335- // These are intentionally not `async` functions and not `Promise.try`.
336- // Both always allocate a Promise, even when the user callback is
337- // synchronous and returns a non-thenable. Callers use `isNonThenable()`
338- // (or `PromisePrototypeThen` for thenables) to settle the result .
347+ // Cold algorithms (cancel/close/abort/flush/transform) stay `async` so
348+ // a user thenable is adopted with the same microtask count as before.
349+ // Pull/write use the raw-callback contract instead (see
350+ // createRawCallback*) and route results through thenAlgorithmResult() .
339351function createPromiseCallbackNoParams ( name , fn , thisArg ) {
340352 validateFunction ( fn , name ) ;
341- return ( ) => {
342- try {
343- return FunctionPrototypeCall ( fn , thisArg ) ;
344- } catch ( error ) {
345- return PromiseReject ( error ) ;
346- }
347- } ;
353+ return async ( ) => FunctionPrototypeCall ( fn , thisArg ) ;
348354}
349355
350356// Raw variants that skip the async wrapper's implicit result promise.
@@ -382,24 +388,12 @@ function thenAlgorithmResult(result, onFulfilled, onRejected) {
382388
383389function createPromiseCallback1Param ( name , fn , thisArg ) {
384390 validateFunction ( fn , name ) ;
385- return ( arg ) => {
386- try {
387- return FunctionPrototypeCall ( fn , thisArg , arg ) ;
388- } catch ( error ) {
389- return PromiseReject ( error ) ;
390- }
391- } ;
391+ return async ( arg ) => FunctionPrototypeCall ( fn , thisArg , arg ) ;
392392}
393393
394394function createPromiseCallback2Params ( name , fn , thisArg ) {
395395 validateFunction ( fn , name ) ;
396- return ( arg1 , arg2 ) => {
397- try {
398- return FunctionPrototypeCall ( fn , thisArg , arg1 , arg2 ) ;
399- } catch ( error ) {
400- return PromiseReject ( error ) ;
401- }
402- } ;
396+ return async ( arg1 , arg2 ) => FunctionPrototypeCall ( fn , thisArg , arg1 , arg2 ) ;
403397}
404398
405399function isPromisePending ( promise ) {
@@ -408,31 +402,12 @@ function isPromisePending(promise) {
408402 return details ?. [ 0 ] === kPending ;
409403}
410404
411- // Convert a promise-returning algorithm's raw result into a Promise. A
412- // value that cannot be a thenable (null, undefined, or a non-object
413- // non-function primitive) becomes the shared resolved promise. Objects
414- // and functions go through PromiseResolve so a `.then` lookup, if any,
415- // stays observable.
416- function promiseFromAlgorithmResult ( result ) {
417- if ( isNonThenable ( result ) )
418- return kResolvedPromise ;
419- return PromiseResolve ( result ) ;
420- }
421-
422- // Cancel/flush/abort only: insert an extra microtask so "upon fulfillment"
423- // of an already-settled user promise runs after start-settlement reactions
424- // queued during construction. Pull/write must not use this.
425- function delayedAlgorithmResult ( result ) {
426- if ( isNonThenable ( result ) )
427- return kResolvedPromise ;
428- return PromisePrototypeThen ( kResolvedPromise , ( ) => result ) ;
429- }
430-
431405// Shared shapes for lazily-materialized { promise, resolve, reject }
432- // records whose settlement is already known.
406+ // records whose settlement is already known. Each call mints a fresh
407+ // promise so public slots (writer.ready / writer.closed) stay distinct.
433408function resolvedRecord ( ) {
434409 return {
435- promise : kResolvedPromise ,
410+ promise : PromiseResolve ( ) ,
436411 resolve : undefined ,
437412 reject : undefined ,
438413 } ;
@@ -456,13 +431,16 @@ function setPromiseHandled(promise) {
456431 PromisePrototypeThen ( promise , undefined , ( ) => { } ) ;
457432}
458433
459- // Shared no-op. Start/pull/write use the raw-callback contract (see
460- // createRawCallback*): a non-thenable return takes the allocation-free
461- // path in thenAlgorithmResult(). Cancel/flush/abort wrap the result
462- // with promiseFromAlgorithmResult/delayedAlgorithmResult, so a sync
463- // no-op is equivalent to the previous async empty functions.
434+ async function nonOpFlush ( ) { }
435+
436+ // Shared non-op for the start/pull/write algorithm callbacks, which all
437+ // follow the raw-callback contract (see createRawCallback*): the
438+ // non-thenable return takes the allocation-free fast path in
439+ // thenAlgorithmResult().
464440function nonOpCallback ( ) { }
465441
442+ async function nonOpCancel ( ) { }
443+
466444let transfer ;
467445function lazyTransfer ( ) {
468446 if ( transfer === undefined )
@@ -478,7 +456,6 @@ module.exports = {
478456 Queue,
479457 canCopyArrayBuffer,
480458 cloneAsUint8Array,
481- isNonThenable,
482459 copyArrayBuffer,
483460 createPromiseCallbackNoParams,
484461 createPromiseCallback1Param,
@@ -493,6 +470,7 @@ module.exports = {
493470 extractSizeAlgorithm,
494471 getNonWritablePropertyDescriptor,
495472 isBrandCheck,
473+ isNonThenable,
496474 isPromisePending,
497475 kEmptyQueue,
498476 kResolvedPromise,
@@ -501,10 +479,8 @@ module.exports = {
501479 lazyTransfer,
502480 materializeQueue,
503481 nonOpCallback,
504- nonOpCancel : nonOpCallback ,
505- nonOpFlush : nonOpCallback ,
506- promiseFromAlgorithmResult,
507- delayedAlgorithmResult,
482+ nonOpCancel,
483+ nonOpFlush,
508484 peekQueueValue,
509485 rejectedHandledRecord,
510486 resetQueue,
0 commit comments