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.
@@ -390,24 +396,12 @@ function thenAlgorithmResult(result, onFulfilled, onRejected) {
390396
391397function createPromiseCallback1Param ( name , fn , thisArg ) {
392398 validateFunction ( fn , name ) ;
393- return ( arg ) => {
394- try {
395- return FunctionPrototypeCall ( fn , thisArg , arg ) ;
396- } catch ( error ) {
397- return PromiseReject ( error ) ;
398- }
399- } ;
399+ return async ( arg ) => FunctionPrototypeCall ( fn , thisArg , arg ) ;
400400}
401401
402402function createPromiseCallback2Params ( name , fn , thisArg ) {
403403 validateFunction ( fn , name ) ;
404- return ( arg1 , arg2 ) => {
405- try {
406- return FunctionPrototypeCall ( fn , thisArg , arg1 , arg2 ) ;
407- } catch ( error ) {
408- return PromiseReject ( error ) ;
409- }
410- } ;
404+ return async ( arg1 , arg2 ) => FunctionPrototypeCall ( fn , thisArg , arg1 , arg2 ) ;
411405}
412406
413407function isPromisePending ( promise ) {
@@ -416,31 +410,12 @@ function isPromisePending(promise) {
416410 return details ?. [ 0 ] === kPending ;
417411}
418412
419- // Convert a promise-returning algorithm's raw result into a Promise. A
420- // value that cannot be a thenable (null, undefined, or a non-object
421- // non-function primitive) becomes the shared resolved promise. Objects
422- // and functions go through PromiseResolve so a `.then` lookup, if any,
423- // stays observable.
424- function promiseFromAlgorithmResult ( result ) {
425- if ( isNonThenable ( result ) )
426- return kResolvedPromise ;
427- return PromiseResolve ( result ) ;
428- }
429-
430- // Cancel/flush/abort only: insert an extra microtask so "upon fulfillment"
431- // of an already-settled user promise runs after start-settlement reactions
432- // queued during construction. Pull/write must not use this.
433- function delayedAlgorithmResult ( result ) {
434- if ( isNonThenable ( result ) )
435- return kResolvedPromise ;
436- return PromisePrototypeThen ( kResolvedPromise , ( ) => result ) ;
437- }
438-
439413// Shared shapes for lazily-materialized { promise, resolve, reject }
440- // records whose settlement is already known.
414+ // records whose settlement is already known. Each call mints a fresh
415+ // promise so public slots (writer.ready / writer.closed) stay distinct.
441416function resolvedRecord ( ) {
442417 return {
443- promise : kResolvedPromise ,
418+ promise : PromiseResolve ( ) ,
444419 resolve : undefined ,
445420 reject : undefined ,
446421 } ;
@@ -464,13 +439,16 @@ function setPromiseHandled(promise) {
464439 PromisePrototypeThen ( promise , undefined , ( ) => { } ) ;
465440}
466441
467- // Shared no-op. Start/pull/write use the raw-callback contract (see
468- // createRawCallback*): a non-thenable return takes the allocation-free
469- // path in thenAlgorithmResult(). Cancel/flush/abort wrap the result
470- // with promiseFromAlgorithmResult/delayedAlgorithmResult, so a sync
471- // no-op is equivalent to the previous async empty functions.
442+ async function nonOpFlush ( ) { }
443+
444+ // Shared non-op for the start/pull/write algorithm callbacks, which all
445+ // follow the raw-callback contract (see createRawCallback*): the
446+ // non-thenable return takes the allocation-free fast path in
447+ // thenAlgorithmResult().
472448function nonOpCallback ( ) { }
473449
450+ async function nonOpCancel ( ) { }
451+
474452let transfer ;
475453function lazyTransfer ( ) {
476454 if ( transfer === undefined )
@@ -486,7 +464,6 @@ module.exports = {
486464 Queue,
487465 canCopyArrayBuffer,
488466 cloneAsUint8Array,
489- isNonThenable,
490467 copyArrayBuffer,
491468 createPromiseCallbackNoParams,
492469 createPromiseCallback1Param,
@@ -501,6 +478,7 @@ module.exports = {
501478 extractSizeAlgorithm,
502479 getNonWritablePropertyDescriptor,
503480 isBrandCheck,
481+ isNonThenable,
504482 isPromisePending,
505483 kEmptyQueue,
506484 kParkedAlgorithmResult,
@@ -510,10 +488,8 @@ module.exports = {
510488 lazyTransfer,
511489 materializeQueue,
512490 nonOpCallback,
513- nonOpCancel : nonOpCallback ,
514- nonOpFlush : nonOpCallback ,
515- promiseFromAlgorithmResult,
516- delayedAlgorithmResult,
491+ nonOpCancel,
492+ nonOpFlush,
517493 peekQueueValue,
518494 rejectedHandledRecord,
519495 resetQueue,
0 commit comments