diff options
author | 2023-07-31 06:17:56 -0700 | |
---|---|---|
committer | 2023-07-31 06:17:56 -0700 | |
commit | f2983e50b7004277800a14c4bf9371906884693c (patch) | |
tree | f4f97db8720b4a4a4c8dc957eafdbfec715e0ac9 | |
parent | e47a448434acc6c5ebfcaf2d22ed1c96a979e761 (diff) | |
download | bun-f2983e50b7004277800a14c4bf9371906884693c.tar.gz bun-f2983e50b7004277800a14c4bf9371906884693c.tar.zst bun-f2983e50b7004277800a14c4bf9371906884693c.zip |
Add a test for TransformStream
-rw-r--r-- | src/js/builtins/ReadableStreamDefaultReader.ts | 1 | ||||
-rw-r--r-- | src/js/builtins/TransformStreamInternals.ts | 6 | ||||
-rw-r--r-- | src/js/out/WebCoreJSBuiltins.cpp | 14 | ||||
-rw-r--r-- | test/js/web/streams/streams.test.js | 47 |
4 files changed, 53 insertions, 15 deletions
diff --git a/src/js/builtins/ReadableStreamDefaultReader.ts b/src/js/builtins/ReadableStreamDefaultReader.ts index b4e0c2bd3..ea1a64b68 100644 --- a/src/js/builtins/ReadableStreamDefaultReader.ts +++ b/src/js/builtins/ReadableStreamDefaultReader.ts @@ -59,7 +59,6 @@ export function readMany(this: ReadableStreamDefaultReader): ReadableStreamDefau var controller = $getByIdDirectPrivate(stream, "readableStreamController"); var queue = $getByIdDirectPrivate(controller, "queue"); - if (!queue) { // This is a ReadableStream direct controller implemented in JS // It hasn't been started yet. diff --git a/src/js/builtins/TransformStreamInternals.ts b/src/js/builtins/TransformStreamInternals.ts index 103b0651f..833fafdc6 100644 --- a/src/js/builtins/TransformStreamInternals.ts +++ b/src/js/builtins/TransformStreamInternals.ts @@ -241,7 +241,7 @@ export function transformStreamDefaultControllerPerformTransform(controller, chu const transformPromise = $getByIdDirectPrivate(controller, "transformAlgorithm").$call(undefined, chunk); transformPromise.$then( () => { - promiseCapability.$resolve(); + promiseCapability.resolve(); }, r => { $transformStreamError($getByIdDirectPrivate(controller, "stream"), r); @@ -286,7 +286,7 @@ export function transformStreamDefaultSinkWriteAlgorithm(stream, chunk) { $assert(state === "writable"); $transformStreamDefaultControllerPerformTransform(controller, chunk).$then( () => { - promiseCapability.$resolve(); + promiseCapability.resolve(); }, e => { promiseCapability.reject.$call(undefined, e); @@ -329,7 +329,7 @@ export function transformStreamDefaultSinkCloseAlgorithm(stream) { // FIXME: Update readableStreamDefaultControllerClose to make this check. if ($readableStreamDefaultControllerCanCloseOrEnqueue(readableController)) $readableStreamDefaultControllerClose(readableController); - promiseCapability.$resolve(); + promiseCapability.resolve(); }, r => { $transformStreamError($getByIdDirectPrivate(controller, "stream"), r); diff --git a/src/js/out/WebCoreJSBuiltins.cpp b/src/js/out/WebCoreJSBuiltins.cpp index a28464a57..06be7ba77 100644 --- a/src/js/out/WebCoreJSBuiltins.cpp +++ b/src/js/out/WebCoreJSBuiltins.cpp @@ -580,9 +580,9 @@ const char* const s_transformStreamInternalsTransformStreamDefaultControllerErro const JSC::ConstructAbility s_transformStreamInternalsTransformStreamDefaultControllerPerformTransformCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; const JSC::ConstructorKind s_transformStreamInternalsTransformStreamDefaultControllerPerformTransformCodeConstructorKind = JSC::ConstructorKind::None; const JSC::ImplementationVisibility s_transformStreamInternalsTransformStreamDefaultControllerPerformTransformCodeImplementationVisibility = JSC::ImplementationVisibility::Public; -const int s_transformStreamInternalsTransformStreamDefaultControllerPerformTransformCodeLength = 275; +const int s_transformStreamInternalsTransformStreamDefaultControllerPerformTransformCodeLength = 274; static const JSC::Intrinsic s_transformStreamInternalsTransformStreamDefaultControllerPerformTransformCodeIntrinsic = JSC::NoIntrinsic; -const char* const s_transformStreamInternalsTransformStreamDefaultControllerPerformTransformCode = "(function (d,g){\"use strict\";const _=@newPromiseCapability(@Promise);return @getByIdDirectPrivate(d,\"transformAlgorithm\").@call(@undefined,g).@then(()=>{_.@resolve()},(f)=>{@transformStreamError(@getByIdDirectPrivate(d,\"stream\"),f),_.reject.@call(@undefined,f)}),_.promise})\n"; +const char* const s_transformStreamInternalsTransformStreamDefaultControllerPerformTransformCode = "(function (d,g){\"use strict\";const _=@newPromiseCapability(@Promise);return @getByIdDirectPrivate(d,\"transformAlgorithm\").@call(@undefined,g).@then(()=>{_.resolve()},(f)=>{@transformStreamError(@getByIdDirectPrivate(d,\"stream\"),f),_.reject.@call(@undefined,f)}),_.promise})\n"; // transformStreamDefaultControllerTerminate const JSC::ConstructAbility s_transformStreamInternalsTransformStreamDefaultControllerTerminateCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; @@ -596,9 +596,9 @@ const char* const s_transformStreamInternalsTransformStreamDefaultControllerTerm const JSC::ConstructAbility s_transformStreamInternalsTransformStreamDefaultSinkWriteAlgorithmCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; const JSC::ConstructorKind s_transformStreamInternalsTransformStreamDefaultSinkWriteAlgorithmCodeConstructorKind = JSC::ConstructorKind::None; const JSC::ImplementationVisibility s_transformStreamInternalsTransformStreamDefaultSinkWriteAlgorithmCodeImplementationVisibility = JSC::ImplementationVisibility::Public; -const int s_transformStreamInternalsTransformStreamDefaultSinkWriteAlgorithmCodeLength = 759; +const int s_transformStreamInternalsTransformStreamDefaultSinkWriteAlgorithmCodeLength = 758; static const JSC::Intrinsic s_transformStreamInternalsTransformStreamDefaultSinkWriteAlgorithmCodeIntrinsic = JSC::NoIntrinsic; -const char* const s_transformStreamInternalsTransformStreamDefaultSinkWriteAlgorithmCode = "(function (d,q){\"use strict\";const j=@getByIdDirectPrivate(d,\"internalWritable\");@assert(@getByIdDirectPrivate(j,\"state\")===\"writable\");const v=@getByIdDirectPrivate(d,\"controller\");if(@getByIdDirectPrivate(d,\"backpressure\")){const _=@newPromiseCapability(@Promise),x=@getByIdDirectPrivate(d,\"backpressureChangePromise\");return @assert(x!==@undefined),x.promise.@then(()=>{const f=@getByIdDirectPrivate(j,\"state\");if(f===\"erroring\"){_.reject.@call(@undefined,@getByIdDirectPrivate(j,\"storedError\"));return}@assert(f===\"writable\"),@transformStreamDefaultControllerPerformTransform(v,q).@then(()=>{_.@resolve()},(z)=>{_.reject.@call(@undefined,z)})},(f)=>{_.reject.@call(@undefined,f)}),_.promise}return @transformStreamDefaultControllerPerformTransform(v,q)})\n"; +const char* const s_transformStreamInternalsTransformStreamDefaultSinkWriteAlgorithmCode = "(function (d,q){\"use strict\";const j=@getByIdDirectPrivate(d,\"internalWritable\");@assert(@getByIdDirectPrivate(j,\"state\")===\"writable\");const v=@getByIdDirectPrivate(d,\"controller\");if(@getByIdDirectPrivate(d,\"backpressure\")){const _=@newPromiseCapability(@Promise),x=@getByIdDirectPrivate(d,\"backpressureChangePromise\");return @assert(x!==@undefined),x.promise.@then(()=>{const f=@getByIdDirectPrivate(j,\"state\");if(f===\"erroring\"){_.reject.@call(@undefined,@getByIdDirectPrivate(j,\"storedError\"));return}@assert(f===\"writable\"),@transformStreamDefaultControllerPerformTransform(v,q).@then(()=>{_.resolve()},(z)=>{_.reject.@call(@undefined,z)})},(f)=>{_.reject.@call(@undefined,f)}),_.promise}return @transformStreamDefaultControllerPerformTransform(v,q)})\n"; // transformStreamDefaultSinkAbortAlgorithm const JSC::ConstructAbility s_transformStreamInternalsTransformStreamDefaultSinkAbortAlgorithmCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; @@ -612,9 +612,9 @@ const char* const s_transformStreamInternalsTransformStreamDefaultSinkAbortAlgor const JSC::ConstructAbility s_transformStreamInternalsTransformStreamDefaultSinkCloseAlgorithmCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; const JSC::ConstructorKind s_transformStreamInternalsTransformStreamDefaultSinkCloseAlgorithmCodeConstructorKind = JSC::ConstructorKind::None; const JSC::ImplementationVisibility s_transformStreamInternalsTransformStreamDefaultSinkCloseAlgorithmCodeImplementationVisibility = JSC::ImplementationVisibility::Public; -const int s_transformStreamInternalsTransformStreamDefaultSinkCloseAlgorithmCodeLength = 786; +const int s_transformStreamInternalsTransformStreamDefaultSinkCloseAlgorithmCodeLength = 785; static const JSC::Intrinsic s_transformStreamInternalsTransformStreamDefaultSinkCloseAlgorithmCodeIntrinsic = JSC::NoIntrinsic; -const char* const s_transformStreamInternalsTransformStreamDefaultSinkCloseAlgorithmCode = "(function (j){\"use strict\";const _=@getByIdDirectPrivate(j,\"readable\"),I=@getByIdDirectPrivate(j,\"controller\"),k=@getByIdDirectPrivate(_,\"readableStreamController\"),q=@getByIdDirectPrivate(I,\"flushAlgorithm\");@assert(q!==@undefined);const u=@getByIdDirectPrivate(I,\"flushAlgorithm\").@call();@transformStreamDefaultControllerClearAlgorithms(I);const S=@newPromiseCapability(@Promise);return u.@then(()=>{if(@getByIdDirectPrivate(_,\"state\")===@streamErrored){S.reject.@call(@undefined,@getByIdDirectPrivate(_,\"storedError\"));return}if(@readableStreamDefaultControllerCanCloseOrEnqueue(k))@readableStreamDefaultControllerClose(k);S.@resolve()},(v)=>{@transformStreamError(@getByIdDirectPrivate(I,\"stream\"),v),S.reject.@call(@undefined,@getByIdDirectPrivate(_,\"storedError\"))}),S.promise})\n"; +const char* const s_transformStreamInternalsTransformStreamDefaultSinkCloseAlgorithmCode = "(function (S){\"use strict\";const _=@getByIdDirectPrivate(S,\"readable\"),u=@getByIdDirectPrivate(S,\"controller\"),c=@getByIdDirectPrivate(_,\"readableStreamController\"),g=@getByIdDirectPrivate(u,\"flushAlgorithm\");@assert(g!==@undefined);const j=@getByIdDirectPrivate(u,\"flushAlgorithm\").@call();@transformStreamDefaultControllerClearAlgorithms(u);const I=@newPromiseCapability(@Promise);return j.@then(()=>{if(@getByIdDirectPrivate(_,\"state\")===@streamErrored){I.reject.@call(@undefined,@getByIdDirectPrivate(_,\"storedError\"));return}if(@readableStreamDefaultControllerCanCloseOrEnqueue(c))@readableStreamDefaultControllerClose(c);I.resolve()},(k)=>{@transformStreamError(@getByIdDirectPrivate(u,\"stream\"),k),I.reject.@call(@undefined,@getByIdDirectPrivate(_,\"storedError\"))}),I.promise})\n"; // transformStreamDefaultSourcePullAlgorithm const JSC::ConstructAbility s_transformStreamInternalsTransformStreamDefaultSourcePullAlgorithmCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; @@ -2054,7 +2054,7 @@ const JSC::ConstructorKind s_readableStreamDefaultReaderReadManyCodeConstructorK const JSC::ImplementationVisibility s_readableStreamDefaultReaderReadManyCodeImplementationVisibility = JSC::ImplementationVisibility::Public; const int s_readableStreamDefaultReaderReadManyCodeLength = 2598; static const JSC::Intrinsic s_readableStreamDefaultReaderReadManyCodeIntrinsic = JSC::NoIntrinsic; -const char* const s_readableStreamDefaultReaderReadManyCode = "(function (){\"use strict\";if(!@isReadableStreamDefaultReader(this))@throwTypeError(\"ReadableStreamDefaultReader.readMany() should not be called directly\");const j=@getByIdDirectPrivate(this,\"ownerReadableStream\");if(!j)@throwTypeError(\"readMany() called on a reader owned by no readable stream\");const I=@getByIdDirectPrivate(j,\"state\");if(@putByIdDirectPrivate(j,\"disturbed\",!0),I===@streamClosed)return{value:[],size:0,done:!0};else if(I===@streamErrored)throw @getByIdDirectPrivate(j,\"storedError\");var B=@getByIdDirectPrivate(j,\"readableStreamController\"),F=@getByIdDirectPrivate(B,\"queue\");if(!F)return B.@pull(B).@then(function({done:_,value:w}){return _\?{done:!0,value:[],size:0}:{value:[w],size:1,done:!1}});const N=F.content;var Q=F.size,x=N.toArray(!1),C=x.length;if(C>0){var D=@newArrayWithSize(C);if(@isReadableByteStreamController(B)){{const _=x[0];if(!(@ArrayBuffer.@isView(_)||_ instanceof @ArrayBuffer))@putByValDirect(D,0,new @Uint8Array(_.buffer,_.byteOffset,_.byteLength));else @putByValDirect(D,0,_)}for(var d=1;d<C;d++){const _=x[d];if(!(@ArrayBuffer.@isView(_)||_ instanceof @ArrayBuffer))@putByValDirect(D,d,new @Uint8Array(_.buffer,_.byteOffset,_.byteLength));else @putByValDirect(D,d,_)}}else{@putByValDirect(D,0,x[0].value);for(var d=1;d<C;d++)@putByValDirect(D,d,x[d].value)}if(@resetQueue(@getByIdDirectPrivate(B,\"queue\")),@getByIdDirectPrivate(B,\"closeRequested\"))@readableStreamClose(@getByIdDirectPrivate(B,\"controlledReadableStream\"));else if(@isReadableStreamDefaultController(B))@readableStreamDefaultControllerCallPullIfNeeded(B);else if(@isReadableByteStreamController(B))@readableByteStreamControllerCallPullIfNeeded(B);return{value:D,size:Q,done:!1}}var J=(_)=>{if(_.done)return{value:[],size:0,done:!0};var w=@getByIdDirectPrivate(j,\"readableStreamController\"),G=@getByIdDirectPrivate(w,\"queue\"),k=[_.value].concat(G.content.toArray(!1)),K=k.length;if(@isReadableByteStreamController(w))for(var A=0;A<K;A++){const H=k[A];if(!(@ArrayBuffer.@isView(H)||H instanceof @ArrayBuffer)){const{buffer:T,byteOffset:U,byteLength:W}=H;@putByValDirect(k,A,new @Uint8Array(T,U,W))}}else for(var A=1;A<K;A++)@putByValDirect(k,A,k[A].value);var S=G.size;if(@resetQueue(G),@getByIdDirectPrivate(w,\"closeRequested\"))@readableStreamClose(@getByIdDirectPrivate(w,\"controlledReadableStream\"));else if(@isReadableStreamDefaultController(w))@readableStreamDefaultControllerCallPullIfNeeded(w);else if(@isReadableByteStreamController(w))@readableByteStreamControllerCallPullIfNeeded(w);return{value:k,size:S,done:!1}},E=B.@pull(B);if(E&&@isPromise(E))return E.@then(J);return J(E)})\n"; +const char* const s_readableStreamDefaultReaderReadManyCode = "(function (){\"use strict\";if(!@isReadableStreamDefaultReader(this))@throwTypeError(\"ReadableStreamDefaultReader.readMany() should not be called directly\");const k=@getByIdDirectPrivate(this,\"ownerReadableStream\");if(!k)@throwTypeError(\"readMany() called on a reader owned by no readable stream\");const H=@getByIdDirectPrivate(k,\"state\");if(@putByIdDirectPrivate(k,\"disturbed\",!0),H===@streamClosed)return{value:[],size:0,done:!0};else if(H===@streamErrored)throw @getByIdDirectPrivate(k,\"storedError\");var d=@getByIdDirectPrivate(k,\"readableStreamController\"),E=@getByIdDirectPrivate(d,\"queue\");if(!E)return d.@pull(d).@then(function({done:_,value:B}){return _\?{done:!0,value:[],size:0}:{value:[B],size:1,done:!1}});const L=E.content;var N=E.size,A=L.toArray(!1),C=A.length;if(C>0){var j=@newArrayWithSize(C);if(@isReadableByteStreamController(d)){{const _=A[0];if(!(@ArrayBuffer.@isView(_)||_ instanceof @ArrayBuffer))@putByValDirect(j,0,new @Uint8Array(_.buffer,_.byteOffset,_.byteLength));else @putByValDirect(j,0,_)}for(var w=1;w<C;w++){const _=A[w];if(!(@ArrayBuffer.@isView(_)||_ instanceof @ArrayBuffer))@putByValDirect(j,w,new @Uint8Array(_.buffer,_.byteOffset,_.byteLength));else @putByValDirect(j,w,_)}}else{@putByValDirect(j,0,A[0].value);for(var w=1;w<C;w++)@putByValDirect(j,w,A[w].value)}if(@resetQueue(@getByIdDirectPrivate(d,\"queue\")),@getByIdDirectPrivate(d,\"closeRequested\"))@readableStreamClose(@getByIdDirectPrivate(d,\"controlledReadableStream\"));else if(@isReadableStreamDefaultController(d))@readableStreamDefaultControllerCallPullIfNeeded(d);else if(@isReadableByteStreamController(d))@readableByteStreamControllerCallPullIfNeeded(d);return{value:j,size:N,done:!1}}var J=(_)=>{if(_.done)return{value:[],size:0,done:!0};var B=@getByIdDirectPrivate(k,\"readableStreamController\"),F=@getByIdDirectPrivate(B,\"queue\"),x=[_.value].concat(F.content.toArray(!1)),K=x.length;if(@isReadableByteStreamController(B))for(var I=0;I<K;I++){const G=x[I];if(!(@ArrayBuffer.@isView(G)||G instanceof @ArrayBuffer)){const{buffer:S,byteOffset:T,byteLength:U}=G;@putByValDirect(x,I,new @Uint8Array(S,T,U))}}else for(var I=1;I<K;I++)@putByValDirect(x,I,x[I].value);var Q=F.size;if(@resetQueue(F),@getByIdDirectPrivate(B,\"closeRequested\"))@readableStreamClose(@getByIdDirectPrivate(B,\"controlledReadableStream\"));else if(@isReadableStreamDefaultController(B))@readableStreamDefaultControllerCallPullIfNeeded(B);else if(@isReadableByteStreamController(B))@readableByteStreamControllerCallPullIfNeeded(B);return{value:x,size:Q,done:!1}},D=d.@pull(d);if(D&&@isPromise(D))return D.@then(J);return J(D)})\n"; // read const JSC::ConstructAbility s_readableStreamDefaultReaderReadCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; diff --git a/test/js/web/streams/streams.test.js b/test/js/web/streams/streams.test.js index 55843cb23..7359009b7 100644 --- a/test/js/web/streams/streams.test.js +++ b/test/js/web/streams/streams.test.js @@ -5,6 +5,48 @@ import { realpathSync, unlinkSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "os"; +it("TransformStream", async () => { + // https://developer.mozilla.org/en-US/docs/Web/API/TransformStream + const TextEncoderStreamInterface = { + start() { + this.encoder = new TextEncoder(); + }, + transform(chunk, controller) { + controller.enqueue(this.encoder.encode(chunk)); + }, + }; + + let instances = new WeakMap(); + class JSTextEncoderStream extends TransformStream { + constructor() { + super(TextEncoderStreamInterface); + instances.set(this, TextEncoderStreamInterface); + } + get encoding() { + return instances.get(this).encoder.encoding; + } + } + + const stream = new JSTextEncoderStream(); + const { writable, readable } = stream; + + const writer = writable.getWriter(); + writer.write("hello"); + writer.write("world"); + writer.close(); + + const reader = readable.getReader(); + const chunks = []; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + chunks.push(value); + } + reader.cancel(); + + expect(Buffer.concat(chunks).toString()).toEqual("helloworld"); +}); + describe("readableStreamToFormData", () => { const fixtures = { withTextFile: [ @@ -171,10 +213,7 @@ describe("WritableStream", () => { write(chunk, controller) { chunks.push(chunk); }, - close(er) { - console.log("closed"); - console.log(er); - }, + close(er) {}, abort(reason) { console.log("aborted!"); console.log(reason); |