2601 lines
81 KiB
Plaintext
2601 lines
81 KiB
Plaintext
@CommonOperationsU
|
||
(function(global, binding, v8) {
|
||
'use strict';
|
||
const _queue = v8.createPrivateSymbol('[[queue]]');
|
||
const _queueTotalSize = v8.createPrivateSymbol('[[queueTotalSize]]');
|
||
const _isSettled = v8.createPrivateSymbol('isSettled');
|
||
const Boolean = global.Boolean;
|
||
const Number = global.Number;
|
||
const Number_isFinite = Number.isFinite;
|
||
const Number_isNaN = Number.isNaN;
|
||
const RangeError = global.RangeError;
|
||
const TypeError = global.TypeError;
|
||
const TypeError_prototype = TypeError.prototype;
|
||
const hasOwnProperty = v8.uncurryThis(global.Object.hasOwnProperty);
|
||
const getPrototypeOf = global.Object.getPrototypeOf.bind(global.Object);
|
||
const getOwnPropertyDescriptor =
|
||
global.Object.getOwnPropertyDescriptor.bind(global.Object);
|
||
const thenPromise = v8.uncurryThis(Promise.prototype.then);
|
||
const JSON_parse = global.JSON.parse.bind(global.JSON);
|
||
const JSON_stringify = global.JSON.stringify.bind(global.JSON);
|
||
function hasOwnPropertyNoThrow(x, property) {
|
||
return Boolean(x) && hasOwnProperty(x, property);
|
||
}
|
||
function streamInternalError() {
|
||
throw new RangeError('Stream API Internal Error');
|
||
}
|
||
function createPromise() {
|
||
const p = v8.createPromise();
|
||
p[_isSettled] = false;
|
||
return p;
|
||
}
|
||
function rejectPromise(p, reason) {
|
||
if (!v8.isPromise(p)) {
|
||
streamInternalError();
|
||
}
|
||
if (p[_isSettled] !== false) {
|
||
return;
|
||
}
|
||
p[_isSettled] = true;
|
||
v8.rejectPromise(p, reason);
|
||
}
|
||
function createRejectedPromise(reason) {
|
||
const p = createPromise();
|
||
rejectPromise(p, reason);
|
||
return p;
|
||
}
|
||
function resolvePromise(p, value) {
|
||
if (!v8.isPromise(p)) {
|
||
streamInternalError();
|
||
}
|
||
if (p[_isSettled] !== false) {
|
||
return;
|
||
}
|
||
p[_isSettled] = true;
|
||
v8.resolvePromise(p, value);
|
||
}
|
||
function createResolvedPromise(value) {
|
||
if (v8.isPromise(value)) {
|
||
return value;
|
||
}
|
||
const p = createPromise();
|
||
resolvePromise(p, value);
|
||
return p;
|
||
}
|
||
function markPromiseAsHandled(p) {
|
||
if (!v8.isPromise(p)) {
|
||
streamInternalError();
|
||
}
|
||
v8.markPromiseAsHandled(p);
|
||
}
|
||
function promiseState(p) {
|
||
if (!v8.isPromise(p)) {
|
||
streamInternalError();
|
||
}
|
||
return v8.promiseState(p);
|
||
}
|
||
function DequeueValue(container) {
|
||
const pair = container[_queue].shift();
|
||
container[_queueTotalSize] -= pair.size;
|
||
if (container[_queueTotalSize] < 0) {
|
||
container[_queueTotalSize] = 0;
|
||
}
|
||
return pair.value;
|
||
}
|
||
function EnqueueValueWithSize(container, value, size) {
|
||
size = Number(size);
|
||
if (!IsFiniteNonNegativeNumber(size)) {
|
||
throw new RangeError(binding.streamErrors.invalidSize);
|
||
}
|
||
container[_queue].push({value, size});
|
||
container[_queueTotalSize] += size;
|
||
}
|
||
function PeekQueueValue(container) {
|
||
const pair = container[_queue].peek();
|
||
return pair.value;
|
||
}
|
||
function ResetQueue(container) {
|
||
container[_queue] = new binding.SimpleQueue();
|
||
container[_queueTotalSize] = 0;
|
||
}
|
||
function IsFiniteNonNegativeNumber(v) {
|
||
return Number_isFinite(v) && v >= 0;
|
||
}
|
||
function ValidateAndNormalizeHighWaterMark(highWaterMark) {
|
||
highWaterMark = Number(highWaterMark);
|
||
if (Number_isNaN(highWaterMark)) {
|
||
throw new RangeError(binding.streamErrors.invalidHWM);
|
||
}
|
||
if (highWaterMark < 0) {
|
||
throw new RangeError(binding.streamErrors.invalidHWM);
|
||
}
|
||
return highWaterMark;
|
||
}
|
||
function MakeSizeAlgorithmFromSizeFunction(size) {
|
||
if (size === undefined) {
|
||
return () => 1;
|
||
}
|
||
if (typeof size !== 'function') {
|
||
throw new TypeError(binding.streamErrors.sizeNotAFunction);
|
||
}
|
||
return size;
|
||
}
|
||
const callFunction = v8.uncurryThis(global.Function.prototype.call);
|
||
const errTmplMustBeFunctionOrUndefined = name =>
|
||
`${name} must be a function or undefined`;
|
||
const Function_bind = v8.uncurryThis(global.Function.prototype.bind);
|
||
function resolveMethod(O, P, nameForError) {
|
||
const method = O[P];
|
||
if (typeof method !== 'function' && typeof method !== 'undefined') {
|
||
throw new TypeError(errTmplMustBeFunctionOrUndefined(nameForError));
|
||
}
|
||
return method;
|
||
}
|
||
function CreateAlgorithmFromUnderlyingMethod(
|
||
underlyingObject, methodName, algoArgCount, methodNameForError) {
|
||
const method =
|
||
resolveMethod(underlyingObject, methodName, methodNameForError);
|
||
if (method === undefined) {
|
||
return () => createResolvedPromise();
|
||
}
|
||
if (algoArgCount === 0) {
|
||
return Function_bind(PromiseCall0, undefined, method, underlyingObject);
|
||
}
|
||
return Function_bind(PromiseCall1, undefined, method, underlyingObject);
|
||
}
|
||
function CreateAlgorithmFromUnderlyingMethodPassingController(
|
||
underlyingObject, methodName, algoArgCount, controller,
|
||
methodNameForError) {
|
||
const method =
|
||
resolveMethod(underlyingObject, methodName, methodNameForError);
|
||
if (method === undefined) {
|
||
return () => createResolvedPromise();
|
||
}
|
||
if (algoArgCount === 0) {
|
||
return Function_bind(
|
||
PromiseCall1, undefined, method, underlyingObject, controller);
|
||
}
|
||
return arg => PromiseCall2(method, underlyingObject, arg, controller);
|
||
}
|
||
function CallOrNoop1(O, P, arg0, nameForError) {
|
||
const method = resolveMethod(O, P, nameForError);
|
||
if (method === undefined) {
|
||
return undefined;
|
||
}
|
||
return callFunction(method, O, arg0);
|
||
}
|
||
function PromiseCall0(F, V) {
|
||
try {
|
||
return createResolvedPromise(callFunction(F, V));
|
||
} catch (e) {
|
||
return createRejectedPromise(e);
|
||
}
|
||
}
|
||
function PromiseCall1(F, V, arg0) {
|
||
try {
|
||
return createResolvedPromise(callFunction(F, V, arg0));
|
||
} catch (e) {
|
||
return createRejectedPromise(e);
|
||
}
|
||
}
|
||
function PromiseCall2(F, V, arg0, arg1) {
|
||
try {
|
||
return createResolvedPromise(callFunction(F, V, arg0, arg1));
|
||
} catch (e) {
|
||
return createRejectedPromise(e);
|
||
}
|
||
}
|
||
const kPull = 1;
|
||
const kCancel = 2;
|
||
const kChunk = 3;
|
||
const kClose = 4;
|
||
const kAbort = 5;
|
||
const kError = 6;
|
||
function isATypeError(object) {
|
||
return object !== null && getPrototypeOf(object) === TypeError_prototype;
|
||
}
|
||
function isADOMException(object) {
|
||
try {
|
||
callFunction(binding.DOMException_name_get, object);
|
||
return true;
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
}
|
||
function packReason(reason) {
|
||
switch (typeof reason) {
|
||
case 'string':
|
||
case 'number':
|
||
case 'boolean':
|
||
return {encoder: 'json', string: JSON_stringify(reason)};
|
||
case 'object':
|
||
try {
|
||
if (isATypeError(reason)) {
|
||
let message;
|
||
const descriptor = getOwnPropertyDescriptor(reason, 'message');
|
||
if (descriptor) {
|
||
message = descriptor.value;
|
||
if (typeof message !== 'string') {
|
||
message = undefined;
|
||
}
|
||
}
|
||
return {encoder: 'typeerror', string: message};
|
||
}
|
||
if (isADOMException(reason)) {
|
||
const message =
|
||
callFunction(binding.DOMException_message_get, reason);
|
||
const name = callFunction(binding.DOMException_name_get, reason);
|
||
return {
|
||
encoder: 'domexception',
|
||
string: JSON_stringify({message, name})
|
||
};
|
||
}
|
||
return {encoder: 'json', string: JSON_stringify(reason)};
|
||
} catch (e) {
|
||
return {encoder: 'typeerror', string: 'Cannot transfer message'};
|
||
}
|
||
default:
|
||
return {encoder: 'undefined', string: undefined};
|
||
}
|
||
}
|
||
function unpackReason(packedReason) {
|
||
const {encoder, string} = packedReason;
|
||
switch (encoder) {
|
||
case 'json':
|
||
return JSON_parse(string);
|
||
case 'typeerror':
|
||
return new TypeError(string);
|
||
case 'domexception':
|
||
const {message, name} = JSON_parse(string);
|
||
return new binding.DOMException(message, name);
|
||
case 'undefined':
|
||
return undefined;
|
||
}
|
||
}
|
||
function CreateCrossRealmTransformWritable(port) {
|
||
let backpressurePromise = createPromise();
|
||
callFunction(binding.EventTarget_addEventListener, port, 'message', evt => {
|
||
const {type, value} = callFunction(binding.MessageEvent_data_get, evt);
|
||
switch (type) {
|
||
case kPull:
|
||
resolvePromise(backpressurePromise);
|
||
backpressurePromise = undefined;
|
||
break;
|
||
case kCancel:
|
||
case kError:
|
||
binding.WritableStreamDefaultControllerErrorIfNeeded(
|
||
controller, unpackReason(value));
|
||
if (backpressurePromise !== undefined) {
|
||
resolvePromise(backpressurePromise);
|
||
backpressurePromise = undefined;
|
||
}
|
||
break;
|
||
}
|
||
});
|
||
callFunction(
|
||
binding.EventTarget_addEventListener, port, 'messageerror', () => {
|
||
const error = new binding.DOMException('chunk could not be cloned',
|
||
'DataCloneError');
|
||
callFunction(binding.MessagePort_postMessage, port,
|
||
{type: kError, value: packReason(error)});
|
||
callFunction(binding.MessagePort_close, port);
|
||
binding.WritableStreamDefaultControllerErrorIfNeeded(controller,
|
||
error);
|
||
});
|
||
callFunction(binding.MessagePort_start, port);
|
||
function doWrite(chunk) {
|
||
backpressurePromise = createPromise();
|
||
try {
|
||
callFunction(
|
||
binding.MessagePort_postMessage, port,
|
||
{type: kChunk, value: chunk});
|
||
} catch (e) {
|
||
callFunction(
|
||
binding.MessagePort_postMessage, port,
|
||
{type: kError, value: packReason(e)});
|
||
callFunction(binding.MessagePort_close, port);
|
||
throw e;
|
||
}
|
||
}
|
||
const stream = binding.CreateWritableStream(
|
||
() => undefined,
|
||
chunk => {
|
||
if (!backpressurePromise) {
|
||
return PromiseCall1(doWrite, null, chunk);
|
||
}
|
||
return thenPromise(backpressurePromise, () => doWrite(chunk));
|
||
},
|
||
() => {
|
||
callFunction(
|
||
binding.MessagePort_postMessage, port,
|
||
{type: kClose, value: undefined});
|
||
callFunction(binding.MessagePort_close, port);
|
||
return createResolvedPromise();
|
||
},
|
||
reason => {
|
||
callFunction(
|
||
binding.MessagePort_postMessage, port,
|
||
{type: kAbort, value: packReason(reason)});
|
||
callFunction(binding.MessagePort_close, port);
|
||
return createResolvedPromise();
|
||
});
|
||
const controller = binding.getWritableStreamController(stream);
|
||
return stream;
|
||
}
|
||
function CreateCrossRealmTransformReadable(port) {
|
||
let backpressurePromise = createPromise();
|
||
let finished = false;
|
||
callFunction(binding.EventTarget_addEventListener, port, 'message', evt => {
|
||
const {type, value} = callFunction(binding.MessageEvent_data_get, evt);
|
||
if (finished) {
|
||
return;
|
||
}
|
||
switch (type) {
|
||
case kChunk:
|
||
binding.ReadableStreamDefaultControllerEnqueue(controller, value);
|
||
resolvePromise(backpressurePromise);
|
||
backpressurePromise = createPromise();
|
||
break;
|
||
case kClose:
|
||
finished = true;
|
||
binding.ReadableStreamDefaultControllerClose(controller);
|
||
callFunction(binding.MessagePort_close, port);
|
||
break;
|
||
case kAbort:
|
||
case kError:
|
||
finished = true;
|
||
binding.ReadableStreamDefaultControllerError(
|
||
controller, unpackReason(value));
|
||
callFunction(binding.MessagePort_close, port);
|
||
break;
|
||
}
|
||
});
|
||
callFunction(
|
||
binding.EventTarget_addEventListener, port, 'messageerror', () => {
|
||
const error = new binding.DOMException('chunk could not be cloned',
|
||
'DataCloneError');
|
||
callFunction(binding.MessagePort_postMessage, port,
|
||
{type: kError, value: packReason(error)});
|
||
callFunction(binding.MessagePort_close, port);
|
||
binding.ReadableStreamDefaultControllerError(controller, error);
|
||
});
|
||
callFunction(binding.MessagePort_start, port);
|
||
const stream = binding.CreateReadableStream(
|
||
() => undefined,
|
||
() => {
|
||
callFunction(
|
||
binding.MessagePort_postMessage, port,
|
||
{type: kPull, value: undefined});
|
||
return backpressurePromise;
|
||
},
|
||
reason => {
|
||
finished = true;
|
||
callFunction(
|
||
binding.MessagePort_postMessage, port,
|
||
{type: kCancel, value: packReason(reason)});
|
||
callFunction(binding.MessagePort_close, port);
|
||
return createResolvedPromise();
|
||
},
|
||
0);
|
||
const controller = binding.getReadableStreamController(stream);
|
||
return stream;
|
||
}
|
||
binding.streamOperations = {
|
||
_queue,
|
||
_queueTotalSize,
|
||
createPromise,
|
||
createRejectedPromise,
|
||
createResolvedPromise,
|
||
hasOwnPropertyNoThrow,
|
||
rejectPromise,
|
||
resolvePromise,
|
||
markPromiseAsHandled,
|
||
promiseState,
|
||
CreateAlgorithmFromUnderlyingMethod,
|
||
CreateAlgorithmFromUnderlyingMethodPassingController,
|
||
CreateCrossRealmTransformWritable,
|
||
CreateCrossRealmTransformReadable,
|
||
DequeueValue,
|
||
EnqueueValueWithSize,
|
||
PeekQueueValue,
|
||
ResetQueue,
|
||
ValidateAndNormalizeHighWaterMark,
|
||
MakeSizeAlgorithmFromSizeFunction,
|
||
CallOrNoop1,
|
||
PromiseCall2
|
||
};
|
||
});
|
||
4CommonStringså
|
||
(function(global, binding, v8) {
|
||
'use strict';
|
||
binding.streamErrors = {
|
||
cannotTransferLockedStream: 'Cannot transfer a locked stream',
|
||
cannotTransferContext: 'Cannot transfer from this context',
|
||
illegalInvocation: 'Illegal invocation',
|
||
illegalConstructor: 'Illegal constructor',
|
||
invalidType: 'Invalid type is specified',
|
||
invalidSize: 'The return value of a queuing strategy\'s size function ' +
|
||
'must be a finite, non-NaN, non-negative number',
|
||
sizeNotAFunction: 'A queuing strategy\'s size property must be a function',
|
||
invalidHWM:
|
||
'A queueing strategy\'s highWaterMark property must be a nonnegative, ' +
|
||
'non-NaN number',
|
||
};
|
||
});
|
||
,SimpleQueueý
|
||
(function(global, binding, v8) {
|
||
'use strict';
|
||
const _front = v8.createPrivateSymbol('front');
|
||
const _back = v8.createPrivateSymbol('back');
|
||
const _cursor = v8.createPrivateSymbol('cursor');
|
||
const _size = v8.createPrivateSymbol('size');
|
||
const _elements = v8.createPrivateSymbol('elements');
|
||
const _next = v8.createPrivateSymbol('next');
|
||
const RangeError = global.RangeError;
|
||
function requireNonEmptyQueue(queue, functionName) {
|
||
if (queue[_size] === 0) {
|
||
throw new RangeError(
|
||
`${functionName}() must not be called on an empty queue`);
|
||
}
|
||
}
|
||
const QUEUE_MAX_ARRAY_SIZE = 16384;
|
||
class SimpleQueue {
|
||
constructor() {
|
||
this[_front] = {
|
||
[_elements]: new v8.InternalPackedArray(),
|
||
[_next]: undefined,
|
||
};
|
||
this[_back] = this[_front];
|
||
this[_cursor] = 0;
|
||
this[_size] = 0;
|
||
}
|
||
get length() {
|
||
return this[_size];
|
||
}
|
||
push(element) {
|
||
const oldBack = this[_back];
|
||
let newBack = oldBack;
|
||
if (oldBack[_elements].length === QUEUE_MAX_ARRAY_SIZE - 1) {
|
||
newBack = {
|
||
[_elements]: new v8.InternalPackedArray(),
|
||
[_next]: undefined,
|
||
};
|
||
}
|
||
oldBack[_elements].push(element);
|
||
if (newBack !== oldBack) {
|
||
this[_back] = newBack;
|
||
oldBack[_next] = newBack;
|
||
}
|
||
++this[_size];
|
||
}
|
||
shift() {
|
||
requireNonEmptyQueue(this, 'shift');
|
||
const oldFront = this[_front];
|
||
let newFront = oldFront;
|
||
const oldCursor = this[_cursor];
|
||
let newCursor = oldCursor + 1;
|
||
const elements = oldFront[_elements];
|
||
const element = elements[oldCursor];
|
||
if (newCursor === QUEUE_MAX_ARRAY_SIZE) {
|
||
newFront = oldFront[_next];
|
||
newCursor = 0;
|
||
}
|
||
--this[_size];
|
||
this[_cursor] = newCursor;
|
||
if (oldFront !== newFront) {
|
||
this[_front] = newFront;
|
||
}
|
||
elements[oldCursor] = undefined;
|
||
return element;
|
||
}
|
||
forEach(callback) {
|
||
let i = this[_cursor];
|
||
let node = this[_front];
|
||
let elements = node[_elements];
|
||
while (i !== elements.length || node[_next] !== undefined) {
|
||
if (i === elements.length) {
|
||
node = node[_next];
|
||
elements = node[_elements];
|
||
i = 0;
|
||
if (elements.length === 0) {
|
||
break;
|
||
}
|
||
}
|
||
callback(elements[i]);
|
||
++i;
|
||
}
|
||
}
|
||
peek() {
|
||
requireNonEmptyQueue(this, 'peek');
|
||
const front = this[_front];
|
||
const cursor = this[_cursor];
|
||
return front[_elements][cursor];
|
||
}
|
||
}
|
||
binding.SimpleQueue = SimpleQueue;
|
||
});
|
||
dByteLengthQueuingStrategy<EFBFBD>
|
||
(function(global, binding, v8) {
|
||
'use strict';
|
||
const defineProperty = global.Object.defineProperty;
|
||
class ByteLengthQueuingStrategy {
|
||
constructor(options) {
|
||
defineProperty(this, 'highWaterMark', {
|
||
value: options.highWaterMark,
|
||
enumerable: true,
|
||
configurable: true,
|
||
writable: true
|
||
});
|
||
}
|
||
size(chunk) {
|
||
return chunk.byteLength;
|
||
}
|
||
}
|
||
defineProperty(global, 'ByteLengthQueuingStrategy', {
|
||
value: ByteLengthQueuingStrategy,
|
||
enumerable: false,
|
||
configurable: true,
|
||
writable: true
|
||
});
|
||
});
|
||
PCountQueuingStrategy
|
||
|
||
(function(global, binding, v8) {
|
||
'use strict';
|
||
const defineProperty = global.Object.defineProperty;
|
||
class CountQueuingStrategy {
|
||
constructor(options) {
|
||
defineProperty(this, 'highWaterMark', {
|
||
value: options.highWaterMark,
|
||
enumerable: true,
|
||
configurable: true,
|
||
writable: true
|
||
});
|
||
}
|
||
size() {
|
||
return 1;
|
||
}
|
||
}
|
||
defineProperty(global, 'CountQueuingStrategy', {
|
||
value: CountQueuingStrategy,
|
||
enumerable: false,
|
||
configurable: true,
|
||
writable: true
|
||
});
|
||
class BuiltInCountQueuingStrategy {
|
||
constructor(highWaterMark) {
|
||
defineProperty(this, 'highWaterMark', {value: highWaterMark});
|
||
}
|
||
size() {
|
||
return 1;
|
||
}
|
||
}
|
||
binding.createBuiltInCountQueuingStrategy = highWaterMark =>
|
||
new BuiltInCountQueuingStrategy(highWaterMark);
|
||
});
|
||
8ReadableStream¸
|
||
(function(global, binding, v8) {
|
||
'use strict';
|
||
const _reader = v8.createPrivateSymbol('[[reader]]');
|
||
const _storedError = v8.createPrivateSymbol('[[storedError]]');
|
||
const _controller = v8.createPrivateSymbol('[[controller]]');
|
||
const _closedPromise = v8.createPrivateSymbol('[[closedPromise]]');
|
||
const _ownerReadableStream =
|
||
v8.createPrivateSymbol('[[ownerReadableStream]]');
|
||
const _readRequests = v8.createPrivateSymbol('[[readRequests]]');
|
||
const createWithExternalControllerSentinel =
|
||
v8.createPrivateSymbol('flag for UA-created ReadableStream to pass');
|
||
const _readableStreamBits =
|
||
v8.createPrivateSymbol('bit field for [[state]] and [[disturbed]]');
|
||
const DISTURBED = 0b1;
|
||
const STATE_MASK = 0b110;
|
||
const STATE_BITS_OFFSET = 1;
|
||
const STATE_READABLE = 0;
|
||
const STATE_CLOSED = 1;
|
||
const STATE_ERRORED = 2;
|
||
const _controlledReadableStream =
|
||
v8.createPrivateSymbol('[[controlledReadableStream]]');
|
||
const _strategyHWM = v8.createPrivateSymbol('[[strategyHWM]]');
|
||
const _readableStreamDefaultControllerBits = v8.createPrivateSymbol(
|
||
'bit field for [[started]], [[closeRequested]], [[pulling]], ' +
|
||
'[[pullAgain]]');
|
||
const internalReadableStreamSymbol = v8.createPrivateSymbol(
|
||
'internal ReadableStream in exposed ReadableStream interface');
|
||
const _lockNotifyTarget = v8.createPrivateSymbol('[[lockNotifyTarget]]');
|
||
const _strategySizeAlgorithm = v8.createPrivateSymbol(
|
||
'[[strategySizeAlgorithm]]');
|
||
const _pullAlgorithm = v8.createPrivateSymbol('[[pullAlgorithm]]');
|
||
const _cancelAlgorithm = v8.createPrivateSymbol('[[cancelAlgorithm]]');
|
||
const STARTED = 0b1;
|
||
const CLOSE_REQUESTED = 0b10;
|
||
const PULLING = 0b100;
|
||
const PULL_AGAIN = 0b1000;
|
||
const BLINK_LOCK_NOTIFICATIONS = 0b10000;
|
||
const ObjectCreate = global.Object.create;
|
||
const callFunction = v8.uncurryThis(global.Function.prototype.call);
|
||
const applyFunction = v8.uncurryThis(global.Function.prototype.apply);
|
||
const TypeError = global.TypeError;
|
||
const RangeError = global.RangeError;
|
||
const String = global.String;
|
||
const Promise = global.Promise;
|
||
const thenPromise = v8.uncurryThis(Promise.prototype.then);
|
||
const {
|
||
_queue,
|
||
_queueTotalSize,
|
||
createPromise,
|
||
createRejectedPromise,
|
||
createResolvedPromise,
|
||
hasOwnPropertyNoThrow,
|
||
rejectPromise,
|
||
resolvePromise,
|
||
markPromiseAsHandled,
|
||
CallOrNoop1,
|
||
CreateAlgorithmFromUnderlyingMethod,
|
||
CreateAlgorithmFromUnderlyingMethodPassingController,
|
||
CreateCrossRealmTransformReadable,
|
||
CreateCrossRealmTransformWritable,
|
||
DequeueValue,
|
||
EnqueueValueWithSize,
|
||
MakeSizeAlgorithmFromSizeFunction,
|
||
ValidateAndNormalizeHighWaterMark,
|
||
} = binding.streamOperations;
|
||
const streamErrors = binding.streamErrors;
|
||
const errEnqueueCloseRequestedStream =
|
||
'Cannot enqueue a chunk into a readable stream that is closed or ' +
|
||
'has been requested to be closed';
|
||
const errCancelReleasedReader =
|
||
'This readable stream reader has been released and cannot be used ' +
|
||
'to cancel its previous owner stream';
|
||
const errReadReleasedReader =
|
||
'This readable stream reader has been released and cannot be used ' +
|
||
'to read from its previous owner stream';
|
||
const errCloseCloseRequestedStream =
|
||
'Cannot close a readable stream that has already been requested to ' +
|
||
'be closed';
|
||
const errEnqueueClosedStream =
|
||
'Cannot enqueue a chunk into a closed readable stream';
|
||
const errEnqueueErroredStream =
|
||
'Cannot enqueue a chunk into an errored readable stream';
|
||
const errCloseClosedStream = 'Cannot close a closed readable stream';
|
||
const errCloseErroredStream = 'Cannot close an errored readable stream';
|
||
const errReaderConstructorBadArgument =
|
||
'ReadableStreamReader constructor argument is not a readable stream';
|
||
const errReaderConstructorStreamAlreadyLocked =
|
||
'ReadableStreamReader constructor can only accept readable streams ' +
|
||
'that are not yet locked to a reader';
|
||
const errReleaseReaderWithPendingRead =
|
||
'Cannot release a readable stream reader when it still has ' +
|
||
'outstanding read() calls that have not yet settled';
|
||
const errReleasedReaderClosedPromise =
|
||
'This readable stream reader has been released and cannot be used ' +
|
||
'to monitor the stream\'s state';
|
||
const errDestinationStreamClosed = 'Destination stream closed';
|
||
let useCounted = false;
|
||
class ReadableStream {
|
||
constructor(underlyingSource = {}, strategy = {},
|
||
internalArgument = undefined) {
|
||
const enableBlinkLockNotifications =
|
||
internalArgument === createWithExternalControllerSentinel;
|
||
if (!useCounted && !enableBlinkLockNotifications) {
|
||
binding.countUse('ReadableStreamConstructor');
|
||
useCounted = true;
|
||
}
|
||
InitializeReadableStream(this);
|
||
const size = strategy.size;
|
||
let highWaterMark = strategy.highWaterMark;
|
||
const type = underlyingSource.type;
|
||
const typeString = String(type);
|
||
if (typeString === 'bytes') {
|
||
throw new RangeError('bytes type is not yet implemented');
|
||
}
|
||
if (type !== undefined) {
|
||
throw new RangeError(streamErrors.invalidType);
|
||
}
|
||
const sizeAlgorithm = MakeSizeAlgorithmFromSizeFunction(size);
|
||
if (highWaterMark === undefined) {
|
||
highWaterMark = 1;
|
||
}
|
||
highWaterMark = ValidateAndNormalizeHighWaterMark(highWaterMark);
|
||
SetUpReadableStreamDefaultControllerFromUnderlyingSource(
|
||
this, underlyingSource, highWaterMark, sizeAlgorithm,
|
||
enableBlinkLockNotifications);
|
||
}
|
||
}
|
||
const ReadableStream_prototype = ReadableStream.prototype;
|
||
function ReadableStreamPipeTo(
|
||
readable, dest, preventClose, preventAbort, preventCancel) {
|
||
const reader = AcquireReadableStreamDefaultReader(readable);
|
||
const writer = binding.AcquireWritableStreamDefaultWriter(dest);
|
||
let shuttingDown = false;
|
||
const promise = createPromise();
|
||
let reading = false;
|
||
let lastWrite;
|
||
if (checkInitialState()) {
|
||
thenPromise(reader[_closedPromise], onReaderClosed, readableError);
|
||
thenPromise(
|
||
binding.getWritableStreamDefaultWriterClosedPromise(writer),
|
||
undefined, writableError);
|
||
pump();
|
||
}
|
||
function checkInitialState() {
|
||
const state = ReadableStreamGetState(readable);
|
||
if (state === STATE_ERRORED) {
|
||
readableError(readable[_storedError]);
|
||
return false;
|
||
}
|
||
if (binding.isWritableStreamErrored(dest)) {
|
||
writableError(binding.getWritableStreamStoredError(dest));
|
||
return false;
|
||
}
|
||
if (state === STATE_CLOSED) {
|
||
readableClosed();
|
||
return false;
|
||
}
|
||
if (binding.isWritableStreamClosingOrClosed(dest)) {
|
||
writableStartedClosed();
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
function pump() {
|
||
if (shuttingDown) {
|
||
return;
|
||
}
|
||
const desiredSize =
|
||
binding.WritableStreamDefaultWriterGetDesiredSize(writer);
|
||
if (desiredSize === null) {
|
||
return;
|
||
}
|
||
if (desiredSize <= 0) {
|
||
thenPromise(
|
||
binding.getWritableStreamDefaultWriterReadyPromise(writer), pump,
|
||
writableError);
|
||
return;
|
||
}
|
||
reading = true;
|
||
thenPromise(
|
||
ReadableStreamDefaultReaderRead(reader), readFulfilled, readRejected);
|
||
}
|
||
function readFulfilled({value, done}) {
|
||
reading = false;
|
||
if (done) {
|
||
readableClosed();
|
||
return;
|
||
}
|
||
const write = binding.WritableStreamDefaultWriterWrite(writer, value);
|
||
lastWrite = write;
|
||
thenPromise(write, undefined, writableError);
|
||
pump();
|
||
}
|
||
function readRejected() {
|
||
reading = false;
|
||
readableError(readable[_storedError]);
|
||
}
|
||
function onReaderClosed() {
|
||
if (!reading) {
|
||
readableClosed();
|
||
}
|
||
}
|
||
function readableError(error) {
|
||
if (!preventAbort) {
|
||
shutdownWithAction(
|
||
binding.WritableStreamAbort, [dest, error], error, true);
|
||
} else {
|
||
shutdown(error, true);
|
||
}
|
||
}
|
||
function writableError(error) {
|
||
if (!preventCancel) {
|
||
shutdownWithAction(
|
||
ReadableStreamCancel, [readable, error], error, true);
|
||
} else {
|
||
shutdown(error, true);
|
||
}
|
||
}
|
||
function readableClosed() {
|
||
if (!preventClose) {
|
||
shutdownWithAction(
|
||
binding.WritableStreamDefaultWriterCloseWithErrorPropagation,
|
||
[writer]);
|
||
} else {
|
||
shutdown();
|
||
}
|
||
}
|
||
function writableStartedClosed() {
|
||
const destClosed = new TypeError(errDestinationStreamClosed);
|
||
if (!preventCancel) {
|
||
shutdownWithAction(
|
||
ReadableStreamCancel, [readable, destClosed], destClosed, true);
|
||
} else {
|
||
shutdown(destClosed, true);
|
||
}
|
||
}
|
||
function shutdownWithAction(
|
||
action, args, originalError = undefined, errorGiven = false) {
|
||
if (shuttingDown) {
|
||
return;
|
||
}
|
||
shuttingDown = true;
|
||
let p;
|
||
if (shouldWriteQueuedChunks()) {
|
||
p = thenPromise(writeQueuedChunks(),
|
||
() => applyFunction(action, undefined, args));
|
||
} else {
|
||
p = applyFunction(action, undefined, args);
|
||
}
|
||
thenPromise(
|
||
p, () => finalize(originalError, errorGiven),
|
||
newError => finalize(newError, true));
|
||
}
|
||
function shutdown(error = undefined, errorGiven = false) {
|
||
if (shuttingDown) {
|
||
return;
|
||
}
|
||
shuttingDown = true;
|
||
if (shouldWriteQueuedChunks()) {
|
||
thenPromise(writeQueuedChunks(), () => finalize(error, errorGiven));
|
||
} else {
|
||
finalize(error, errorGiven);
|
||
}
|
||
}
|
||
function finalize(error, errorGiven) {
|
||
binding.WritableStreamDefaultWriterRelease(writer);
|
||
ReadableStreamReaderGenericRelease(reader);
|
||
if (errorGiven) {
|
||
rejectPromise(promise, error);
|
||
} else {
|
||
resolvePromise(promise, undefined);
|
||
}
|
||
}
|
||
function shouldWriteQueuedChunks() {
|
||
return binding.isWritableStreamWritable(dest) &&
|
||
!binding.WritableStreamCloseQueuedOrInFlight(dest);
|
||
}
|
||
function writeQueuedChunks() {
|
||
if (lastWrite) {
|
||
return thenPromise(lastWrite, () => undefined, () => undefined);
|
||
}
|
||
return createResolvedPromise(undefined);
|
||
}
|
||
return promise;
|
||
}
|
||
function AcquireReadableStreamDefaultReader(stream) {
|
||
return new ReadableStreamDefaultReader(stream);
|
||
}
|
||
function CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm,
|
||
highWaterMark, sizeAlgorithm,
|
||
enableBlinkLockNotifications) {
|
||
if (highWaterMark === undefined) {
|
||
highWaterMark = 1;
|
||
}
|
||
if (sizeAlgorithm === undefined) {
|
||
sizeAlgorithm = () => 1;
|
||
}
|
||
const stream = ObjectCreate(ReadableStream_prototype);
|
||
InitializeReadableStream(stream);
|
||
const controller = ObjectCreate(ReadableStreamDefaultController_prototype);
|
||
SetUpReadableStreamDefaultController(
|
||
stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm,
|
||
highWaterMark, sizeAlgorithm, enableBlinkLockNotifications);
|
||
return stream;
|
||
}
|
||
function InitializeReadableStream(stream) {
|
||
stream[_readableStreamBits] = 0b0;
|
||
ReadableStreamSetState(stream, STATE_READABLE);
|
||
stream[_reader] = undefined;
|
||
stream[_storedError] = undefined;
|
||
}
|
||
function IsReadableStream(x) {
|
||
return hasOwnPropertyNoThrow(x, _controller);
|
||
}
|
||
function IsReadableStreamDisturbed(stream) {
|
||
return stream[_readableStreamBits] & DISTURBED;
|
||
}
|
||
function IsReadableStreamLocked(stream) {
|
||
return stream[_reader] !== undefined;
|
||
}
|
||
function ReadableStreamTee(stream) {
|
||
const reader = AcquireReadableStreamDefaultReader(stream);
|
||
let closedOrErrored = false;
|
||
let canceled1 = false;
|
||
let canceled2 = false;
|
||
let reason1;
|
||
let reason2;
|
||
const cancelPromise = createPromise();
|
||
function pullAlgorithm() {
|
||
return thenPromise(
|
||
ReadableStreamDefaultReaderRead(reader), ({value, done}) => {
|
||
if (done && !closedOrErrored) {
|
||
if (!canceled1) {
|
||
ReadableStreamDefaultControllerClose(branch1controller);
|
||
}
|
||
if (!canceled2) {
|
||
ReadableStreamDefaultControllerClose(branch2controller);
|
||
}
|
||
closedOrErrored = true;
|
||
}
|
||
if (closedOrErrored) {
|
||
return;
|
||
}
|
||
if (!canceled1) {
|
||
ReadableStreamDefaultControllerEnqueue(branch1controller, value);
|
||
}
|
||
if (!canceled2) {
|
||
ReadableStreamDefaultControllerEnqueue(branch2controller, value);
|
||
}
|
||
});
|
||
}
|
||
function cancel1Algorithm(reason) {
|
||
canceled1 = true;
|
||
reason1 = reason;
|
||
if (canceled2) {
|
||
const cancelResult = ReadableStreamCancel(stream, [reason1, reason2]);
|
||
resolvePromise(cancelPromise, cancelResult);
|
||
}
|
||
return cancelPromise;
|
||
}
|
||
function cancel2Algorithm(reason) {
|
||
canceled2 = true;
|
||
reason2 = reason;
|
||
if (canceled1) {
|
||
const cancelResult = ReadableStreamCancel(stream, [reason1, reason2]);
|
||
resolvePromise(cancelPromise, cancelResult);
|
||
}
|
||
return cancelPromise;
|
||
}
|
||
const startAlgorithm = () => undefined;
|
||
const branch1Stream = CreateReadableStream(
|
||
startAlgorithm, pullAlgorithm, cancel1Algorithm, undefined, undefined,
|
||
false);
|
||
const branch2Stream = CreateReadableStream(
|
||
startAlgorithm, pullAlgorithm, cancel2Algorithm, undefined, undefined,
|
||
false);
|
||
const branch1controller = branch1Stream[_controller];
|
||
const branch2controller = branch2Stream[_controller];
|
||
thenPromise(reader[_closedPromise], undefined, r => {
|
||
if (closedOrErrored === true) {
|
||
return;
|
||
}
|
||
ReadableStreamDefaultControllerError(branch1controller, r);
|
||
ReadableStreamDefaultControllerError(branch2controller, r);
|
||
closedOrErrored = true;
|
||
});
|
||
return [branch1Stream, branch2Stream];
|
||
}
|
||
function ReadableStreamAddReadRequest(stream, forAuthorCode) {
|
||
const promise = createPromise();
|
||
stream[_reader][_readRequests].push({promise, forAuthorCode});
|
||
return promise;
|
||
}
|
||
function ReadableStreamCancel(stream, reason) {
|
||
stream[_readableStreamBits] |= DISTURBED;
|
||
const state = ReadableStreamGetState(stream);
|
||
if (state === STATE_CLOSED) {
|
||
return createResolvedPromise(undefined);
|
||
}
|
||
if (state === STATE_ERRORED) {
|
||
return createRejectedPromise(stream[_storedError]);
|
||
}
|
||
ReadableStreamClose(stream);
|
||
const sourceCancelPromise =
|
||
ReadableStreamDefaultControllerCancel(stream[_controller], reason);
|
||
return thenPromise(sourceCancelPromise, () => undefined);
|
||
}
|
||
function ReadableStreamClose(stream) {
|
||
ReadableStreamSetState(stream, STATE_CLOSED);
|
||
const reader = stream[_reader];
|
||
if (reader === undefined) {
|
||
return;
|
||
}
|
||
if (IsReadableStreamDefaultReader(reader) === true) {
|
||
reader[_readRequests].forEach(
|
||
request =>
|
||
resolvePromise(
|
||
request.promise,
|
||
ReadableStreamCreateReadResult(undefined, true,
|
||
request.forAuthorCode)));
|
||
reader[_readRequests] = new binding.SimpleQueue();
|
||
}
|
||
resolvePromise(reader[_closedPromise], undefined);
|
||
}
|
||
function ReadableStreamCreateReadResult(value, done, forAuthorCode) {
|
||
if (forAuthorCode) {
|
||
return {value, done};
|
||
}
|
||
const obj = ObjectCreate(null);
|
||
obj.value = value;
|
||
obj.done = done;
|
||
return obj;
|
||
}
|
||
function ReadableStreamError(stream, e) {
|
||
ReadableStreamSetState(stream, STATE_ERRORED);
|
||
stream[_storedError] = e;
|
||
const reader = stream[_reader];
|
||
if (reader === undefined) {
|
||
return;
|
||
}
|
||
if (IsReadableStreamDefaultReader(reader) === true) {
|
||
reader[_readRequests].forEach(request =>
|
||
rejectPromise(request.promise, e));
|
||
reader[_readRequests] = new binding.SimpleQueue();
|
||
}
|
||
rejectPromise(reader[_closedPromise], e);
|
||
markPromiseAsHandled(reader[_closedPromise]);
|
||
}
|
||
function ReadableStreamFulfillReadRequest(stream, chunk, done) {
|
||
const readRequest = stream[_reader][_readRequests].shift();
|
||
resolvePromise(readRequest.promise,
|
||
ReadableStreamCreateReadResult(chunk, done,
|
||
readRequest.forAuthorCode));
|
||
}
|
||
function ReadableStreamGetNumReadRequests(stream) {
|
||
const reader = stream[_reader];
|
||
const readRequests = reader[_readRequests];
|
||
return readRequests.length;
|
||
}
|
||
class ReadableStreamDefaultReader {
|
||
constructor(stream) {
|
||
if (stream[internalReadableStreamSymbol] !== undefined) {
|
||
stream = stream[internalReadableStreamSymbol];
|
||
}
|
||
if (IsReadableStream(stream) === false) {
|
||
throw new TypeError(errReaderConstructorBadArgument);
|
||
}
|
||
if (IsReadableStreamLocked(stream) === true) {
|
||
throw new TypeError(errReaderConstructorStreamAlreadyLocked);
|
||
}
|
||
ReadableStreamReaderGenericInitialize(this, stream);
|
||
this[_readRequests] = new binding.SimpleQueue();
|
||
}
|
||
get closed() {
|
||
if (IsReadableStreamDefaultReader(this) === false) {
|
||
return createRejectedPromise(
|
||
new TypeError(streamErrors.illegalInvocation));
|
||
}
|
||
return this[_closedPromise];
|
||
}
|
||
cancel(reason) {
|
||
if (IsReadableStreamDefaultReader(this) === false) {
|
||
return createRejectedPromise(
|
||
new TypeError(streamErrors.illegalInvocation));
|
||
}
|
||
if (this[_ownerReadableStream] === undefined) {
|
||
return createRejectedPromise(new TypeError(errCancelReleasedReader));
|
||
}
|
||
return ReadableStreamReaderGenericCancel(this, reason);
|
||
}
|
||
read() {
|
||
if (IsReadableStreamDefaultReader(this) === false) {
|
||
return createRejectedPromise(
|
||
new TypeError(streamErrors.illegalInvocation));
|
||
}
|
||
if (this[_ownerReadableStream] === undefined) {
|
||
return createRejectedPromise(new TypeError(errReadReleasedReader));
|
||
}
|
||
return ReadableStreamDefaultReaderRead(this, true);
|
||
}
|
||
releaseLock() {
|
||
if (IsReadableStreamDefaultReader(this) === false) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
if (this[_ownerReadableStream] === undefined) {
|
||
return;
|
||
}
|
||
if (this[_readRequests].length > 0) {
|
||
throw new TypeError(errReleaseReaderWithPendingRead);
|
||
}
|
||
ReadableStreamReaderGenericRelease(this);
|
||
}
|
||
}
|
||
function IsReadableStreamDefaultReader(x) {
|
||
return hasOwnPropertyNoThrow(x, _readRequests);
|
||
}
|
||
function ReadableStreamReaderGenericCancel(reader, reason) {
|
||
return ReadableStreamCancel(reader[_ownerReadableStream], reason);
|
||
}
|
||
function ReadableStreamReaderGenericInitialize(reader, stream) {
|
||
const controller = stream[_controller];
|
||
if (controller[_readableStreamDefaultControllerBits] &
|
||
BLINK_LOCK_NOTIFICATIONS) {
|
||
const lockNotifyTarget = controller[_lockNotifyTarget];
|
||
callFunction(lockNotifyTarget.notifyLockAcquired, lockNotifyTarget);
|
||
}
|
||
reader[_ownerReadableStream] = stream;
|
||
stream[_reader] = reader;
|
||
switch (ReadableStreamGetState(stream)) {
|
||
case STATE_READABLE:
|
||
reader[_closedPromise] = createPromise();
|
||
break;
|
||
case STATE_CLOSED:
|
||
reader[_closedPromise] = createResolvedPromise(undefined);
|
||
break;
|
||
case STATE_ERRORED:
|
||
reader[_closedPromise] = createRejectedPromise(stream[_storedError]);
|
||
markPromiseAsHandled(reader[_closedPromise]);
|
||
break;
|
||
}
|
||
}
|
||
function ReadableStreamReaderGenericRelease(reader) {
|
||
const controller = reader[_ownerReadableStream][_controller];
|
||
if (controller[_readableStreamDefaultControllerBits] &
|
||
BLINK_LOCK_NOTIFICATIONS) {
|
||
const lockNotifyTarget = controller[_lockNotifyTarget];
|
||
callFunction(lockNotifyTarget.notifyLockReleased, lockNotifyTarget);
|
||
}
|
||
if (ReadableStreamGetState(reader[_ownerReadableStream]) ===
|
||
STATE_READABLE) {
|
||
rejectPromise(
|
||
reader[_closedPromise],
|
||
new TypeError(errReleasedReaderClosedPromise));
|
||
} else {
|
||
reader[_closedPromise] =
|
||
createRejectedPromise(new TypeError(errReleasedReaderClosedPromise));
|
||
}
|
||
markPromiseAsHandled(reader[_closedPromise]);
|
||
reader[_ownerReadableStream][_reader] = undefined;
|
||
reader[_ownerReadableStream] = undefined;
|
||
}
|
||
function ReadableStreamDefaultReaderRead(reader, forAuthorCode = false) {
|
||
const stream = reader[_ownerReadableStream];
|
||
stream[_readableStreamBits] |= DISTURBED;
|
||
switch (ReadableStreamGetState(stream)) {
|
||
case STATE_CLOSED:
|
||
return createResolvedPromise(
|
||
ReadableStreamCreateReadResult(undefined, true, forAuthorCode));
|
||
case STATE_ERRORED:
|
||
return createRejectedPromise(stream[_storedError]);
|
||
default:
|
||
return ReadableStreamDefaultControllerPull(stream[_controller],
|
||
forAuthorCode);
|
||
}
|
||
}
|
||
class ReadableStreamDefaultController {
|
||
constructor() {
|
||
throw new TypeError(streamErrors.illegalConstructor);
|
||
}
|
||
get desiredSize() {
|
||
if (IsReadableStreamDefaultController(this) === false) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
return ReadableStreamDefaultControllerGetDesiredSize(this);
|
||
}
|
||
close() {
|
||
if (IsReadableStreamDefaultController(this) === false) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
if (ReadableStreamDefaultControllerCanCloseOrEnqueue(this) === false) {
|
||
let errorDescription;
|
||
if (this[_readableStreamDefaultControllerBits] & CLOSE_REQUESTED) {
|
||
errorDescription = errCloseCloseRequestedStream;
|
||
} else {
|
||
const stream = this[_controlledReadableStream];
|
||
switch (ReadableStreamGetState(stream)) {
|
||
case STATE_ERRORED:
|
||
errorDescription = errCloseErroredStream;
|
||
break;
|
||
case STATE_CLOSED:
|
||
errorDescription = errCloseClosedStream;
|
||
break;
|
||
}
|
||
}
|
||
throw new TypeError(errorDescription);
|
||
}
|
||
return ReadableStreamDefaultControllerClose(this);
|
||
}
|
||
enqueue(chunk) {
|
||
if (IsReadableStreamDefaultController(this) === false) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) {
|
||
const stream = this[_controlledReadableStream];
|
||
throw getReadableStreamEnqueueError(stream, this);
|
||
}
|
||
return ReadableStreamDefaultControllerEnqueue(this, chunk);
|
||
}
|
||
error(e) {
|
||
if (IsReadableStreamDefaultController(this) === false) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
return ReadableStreamDefaultControllerError(this, e);
|
||
}
|
||
}
|
||
const ReadableStreamDefaultController_prototype =
|
||
ReadableStreamDefaultController.prototype;
|
||
function ReadableStreamDefaultControllerCancel(controller, reason) {
|
||
controller[_queue] = new binding.SimpleQueue();
|
||
return controller[_cancelAlgorithm](reason);
|
||
}
|
||
function ReadableStreamDefaultControllerPull(controller, forAuthorCode) {
|
||
const stream = controller[_controlledReadableStream];
|
||
if (controller[_queue].length > 0) {
|
||
const chunk = DequeueValue(controller);
|
||
if ((controller[_readableStreamDefaultControllerBits] &
|
||
CLOSE_REQUESTED) &&
|
||
controller[_queue].length === 0) {
|
||
ReadableStreamClose(stream);
|
||
} else {
|
||
ReadableStreamDefaultControllerCallPullIfNeeded(controller);
|
||
}
|
||
return createResolvedPromise(
|
||
ReadableStreamCreateReadResult(chunk, false, forAuthorCode));
|
||
}
|
||
const pendingPromise = ReadableStreamAddReadRequest(stream, forAuthorCode);
|
||
ReadableStreamDefaultControllerCallPullIfNeeded(controller);
|
||
return pendingPromise;
|
||
}
|
||
function IsReadableStreamDefaultController(x) {
|
||
return hasOwnPropertyNoThrow(x, _controlledReadableStream);
|
||
}
|
||
function ReadableStreamDefaultControllerCallPullIfNeeded(controller) {
|
||
const shouldPull =
|
||
ReadableStreamDefaultControllerShouldCallPull(controller);
|
||
if (shouldPull === false) {
|
||
return;
|
||
}
|
||
if (controller[_readableStreamDefaultControllerBits] & PULLING) {
|
||
controller[_readableStreamDefaultControllerBits] |= PULL_AGAIN;
|
||
return;
|
||
}
|
||
controller[_readableStreamDefaultControllerBits] |= PULLING;
|
||
thenPromise(
|
||
controller[_pullAlgorithm](),
|
||
() => {
|
||
controller[_readableStreamDefaultControllerBits] &= ~PULLING;
|
||
if (controller[_readableStreamDefaultControllerBits] & PULL_AGAIN) {
|
||
controller[_readableStreamDefaultControllerBits] &= ~PULL_AGAIN;
|
||
ReadableStreamDefaultControllerCallPullIfNeeded(controller);
|
||
}
|
||
},
|
||
e => {
|
||
ReadableStreamDefaultControllerError(controller, e);
|
||
});
|
||
}
|
||
function ReadableStreamDefaultControllerShouldCallPull(controller) {
|
||
if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) {
|
||
return false;
|
||
}
|
||
if (!(controller[_readableStreamDefaultControllerBits] & STARTED)) {
|
||
return false;
|
||
}
|
||
const stream = controller[_controlledReadableStream];
|
||
if (IsReadableStreamLocked(stream) === true &&
|
||
ReadableStreamGetNumReadRequests(stream) > 0) {
|
||
return true;
|
||
}
|
||
const desiredSize =
|
||
ReadableStreamDefaultControllerGetDesiredSize(controller);
|
||
return desiredSize > 0;
|
||
}
|
||
function ReadableStreamDefaultControllerClose(controller) {
|
||
controller[_readableStreamDefaultControllerBits] |= CLOSE_REQUESTED;
|
||
if (controller[_queue].length === 0) {
|
||
ReadableStreamClose(controller[_controlledReadableStream]);
|
||
}
|
||
}
|
||
function ReadableStreamDefaultControllerEnqueue(controller, chunk) {
|
||
const stream = controller[_controlledReadableStream];
|
||
if (IsReadableStreamLocked(stream) === true &&
|
||
ReadableStreamGetNumReadRequests(stream) > 0) {
|
||
ReadableStreamFulfillReadRequest(stream, chunk, false);
|
||
} else {
|
||
let chunkSize;
|
||
try {
|
||
chunkSize = callFunction(controller[_strategySizeAlgorithm], undefined,
|
||
chunk);
|
||
} catch (chunkSizeE) {
|
||
ReadableStreamDefaultControllerError(controller, chunkSizeE);
|
||
throw chunkSizeE;
|
||
}
|
||
try {
|
||
EnqueueValueWithSize(controller, chunk, chunkSize);
|
||
} catch (enqueueE) {
|
||
ReadableStreamDefaultControllerError(controller, enqueueE);
|
||
throw enqueueE;
|
||
}
|
||
}
|
||
ReadableStreamDefaultControllerCallPullIfNeeded(controller);
|
||
}
|
||
function ReadableStreamDefaultControllerError(controller, e) {
|
||
const stream = controller[_controlledReadableStream];
|
||
if (ReadableStreamGetState(stream) !== STATE_READABLE) {
|
||
return;
|
||
}
|
||
controller[_queue] = new binding.SimpleQueue();
|
||
ReadableStreamError(stream, e);
|
||
}
|
||
function ReadableStreamDefaultControllerGetDesiredSize(controller) {
|
||
switch (ReadableStreamGetState(controller[_controlledReadableStream])) {
|
||
case STATE_ERRORED:
|
||
return null;
|
||
case STATE_CLOSED:
|
||
return 0;
|
||
default:
|
||
return controller[_strategyHWM] - controller[_queueTotalSize];
|
||
}
|
||
}
|
||
function ReadableStreamDefaultControllerHasBackpressure(controller) {
|
||
return !ReadableStreamDefaultControllerShouldCallPull(controller);
|
||
}
|
||
function ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) {
|
||
if (controller[_readableStreamDefaultControllerBits] & CLOSE_REQUESTED) {
|
||
return false;
|
||
}
|
||
const state = ReadableStreamGetState(controller[_controlledReadableStream]);
|
||
return state === STATE_READABLE;
|
||
}
|
||
function SetUpReadableStreamDefaultController(
|
||
stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm,
|
||
highWaterMark, sizeAlgorithm, enableBlinkLockNotifications) {
|
||
controller[_controlledReadableStream] = stream;
|
||
controller[_queue] = new binding.SimpleQueue();
|
||
controller[_queueTotalSize] = 0;
|
||
controller[_readableStreamDefaultControllerBits] =
|
||
enableBlinkLockNotifications ? BLINK_LOCK_NOTIFICATIONS : 0b0;
|
||
controller[_strategySizeAlgorithm] = sizeAlgorithm;
|
||
controller[_strategyHWM] = highWaterMark;
|
||
controller[_pullAlgorithm] = pullAlgorithm;
|
||
controller[_cancelAlgorithm] = cancelAlgorithm;
|
||
stream[_controller] = controller;
|
||
thenPromise(createResolvedPromise(startAlgorithm()), () => {
|
||
controller[_readableStreamDefaultControllerBits] |= STARTED;
|
||
ReadableStreamDefaultControllerCallPullIfNeeded(controller);
|
||
}, r => ReadableStreamDefaultControllerError(controller, r));
|
||
}
|
||
function SetUpReadableStreamDefaultControllerFromUnderlyingSource(
|
||
stream, underlyingSource, highWaterMark, sizeAlgorithm,
|
||
enableBlinkLockNotifications) {
|
||
const controller = ObjectCreate(ReadableStreamDefaultController_prototype);
|
||
const startAlgorithm =
|
||
() => CallOrNoop1(underlyingSource, 'start', controller,
|
||
'underlyingSource.start');
|
||
const pullAlgorithm = CreateAlgorithmFromUnderlyingMethodPassingController(
|
||
underlyingSource, 'pull', 0, controller, 'underlyingSource.pull');
|
||
const cancelAlgorithm = CreateAlgorithmFromUnderlyingMethod(
|
||
underlyingSource, 'cancel', 1, 'underlyingSource.cancel');
|
||
if (enableBlinkLockNotifications) {
|
||
controller[_lockNotifyTarget] = underlyingSource;
|
||
}
|
||
SetUpReadableStreamDefaultController(
|
||
stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm,
|
||
highWaterMark, sizeAlgorithm, enableBlinkLockNotifications);
|
||
}
|
||
function ReadableStreamSerialize(readable, port) {
|
||
if (IsReadableStreamLocked(readable)) {
|
||
throw new TypeError(streamErrors.cannotTransferLockedStream);
|
||
}
|
||
if (!binding.MessagePort_postMessage) {
|
||
throw new TypeError(streamErrors.cannotTransferContext);
|
||
}
|
||
const writable = CreateCrossRealmTransformWritable(port);
|
||
const promise =
|
||
ReadableStreamPipeTo(readable, writable, false, false, false);
|
||
markPromiseAsHandled(promise);
|
||
}
|
||
function ReadableStreamDeserialize(port) {
|
||
return CreateCrossRealmTransformReadable(port);
|
||
}
|
||
function ReadableStreamGetState(stream) {
|
||
return (stream[_readableStreamBits] & STATE_MASK) >> STATE_BITS_OFFSET;
|
||
}
|
||
function ReadableStreamSetState(stream, state) {
|
||
stream[_readableStreamBits] = (stream[_readableStreamBits] & ~STATE_MASK) |
|
||
(state << STATE_BITS_OFFSET);
|
||
}
|
||
function IsReadableStreamReadable(stream) {
|
||
return ReadableStreamGetState(stream) === STATE_READABLE;
|
||
}
|
||
function IsReadableStreamClosed(stream) {
|
||
return ReadableStreamGetState(stream) === STATE_CLOSED;
|
||
}
|
||
function IsReadableStreamErrored(stream) {
|
||
return ReadableStreamGetState(stream) === STATE_ERRORED;
|
||
}
|
||
function getReadableStreamEnqueueError(stream, controller) {
|
||
if (controller[_readableStreamDefaultControllerBits] & CLOSE_REQUESTED) {
|
||
return new TypeError(errEnqueueCloseRequestedStream);
|
||
}
|
||
const state = ReadableStreamGetState(stream);
|
||
if (state === STATE_ERRORED) {
|
||
return new TypeError(errEnqueueErroredStream);
|
||
}
|
||
return new TypeError(errEnqueueClosedStream);
|
||
}
|
||
function getReadableStreamController(stream) {
|
||
return stream[_controller];
|
||
}
|
||
function getReadableStreamStoredError(stream) {
|
||
return stream[_storedError];
|
||
}
|
||
function createReadableStream(underlyingSource, strategy) {
|
||
return new ReadableStream(underlyingSource, strategy);
|
||
}
|
||
function createReadableStreamWithExternalController(
|
||
underlyingSource, strategy) {
|
||
return new ReadableStream(
|
||
underlyingSource, strategy, createWithExternalControllerSentinel);
|
||
}
|
||
Object.assign(binding, {
|
||
AcquireReadableStreamDefaultReader,
|
||
createReadableStream,
|
||
createReadableStreamWithExternalController,
|
||
IsReadableStream,
|
||
IsReadableStreamDisturbed,
|
||
IsReadableStreamLocked,
|
||
IsReadableStreamReadable,
|
||
IsReadableStreamClosed,
|
||
IsReadableStreamErrored,
|
||
IsReadableStreamDefaultReader,
|
||
ReadableStreamDefaultReaderRead,
|
||
ReadableStreamCancel,
|
||
ReadableStreamTee,
|
||
ReadableStreamPipeTo,
|
||
ReadableStreamSerialize,
|
||
ReadableStreamDeserialize,
|
||
internalReadableStreamSymbol,
|
||
ReadableStreamDefaultControllerClose,
|
||
ReadableStreamDefaultControllerGetDesiredSize,
|
||
ReadableStreamDefaultControllerEnqueue,
|
||
ReadableStreamDefaultControllerError,
|
||
CreateReadableStream,
|
||
ReadableStreamDefaultControllerCanCloseOrEnqueue,
|
||
ReadableStreamDefaultControllerHasBackpressure,
|
||
getReadableStreamEnqueueError,
|
||
getReadableStreamController,
|
||
getReadableStreamStoredError,
|
||
});
|
||
});
|
||
8WritableStreamv¥
|
||
(function(global, binding, v8) {
|
||
'use strict';
|
||
const _abortAlgorithm = v8.createPrivateSymbol('[[abortAlgorithm]]');
|
||
const _closeAlgorithm = v8.createPrivateSymbol('[[closeAlgorithm]]');
|
||
const _closeRequest = v8.createPrivateSymbol('[[closeRequest]]');
|
||
const _inFlightWriteRequest =
|
||
v8.createPrivateSymbol('[[inFlightWriteRequest]]');
|
||
const _inFlightCloseRequest =
|
||
v8.createPrivateSymbol('[[inFlightCloseRequest]]');
|
||
const _pendingAbortRequest =
|
||
v8.createPrivateSymbol('[[pendingAbortRequest]]');
|
||
const _stateAndFlags = v8.createPrivateSymbol('[[state]] and flags');
|
||
const _storedError = v8.createPrivateSymbol('[[storedError]]');
|
||
const _writableStreamController =
|
||
v8.createPrivateSymbol('[[writableStreamController]]');
|
||
const _writer = v8.createPrivateSymbol('[[writer]]');
|
||
const _writeRequests = v8.createPrivateSymbol('[[writeRequests]]');
|
||
const _closedPromise = v8.createPrivateSymbol('[[closedPromise]]');
|
||
const _ownerWritableStream =
|
||
v8.createPrivateSymbol('[[ownerWritableStream]]');
|
||
const _readyPromise = v8.createPrivateSymbol('[[readyPromise]]');
|
||
const _controlledWritableStream =
|
||
v8.createPrivateSymbol('[[controlledWritableStream]]');
|
||
const _started = v8.createPrivateSymbol('[[started]]');
|
||
const _strategyHWM = v8.createPrivateSymbol('[[strategyHWM]]');
|
||
const _strategySizeAlgorithm =
|
||
v8.createPrivateSymbol('[[strategySizeAlgorithm]]');
|
||
const _writeAlgorithm = v8.createPrivateSymbol('[[writeAlgorithm]]');
|
||
const internalWritableStreamSymbol = v8.createPrivateSymbol(
|
||
'internal WritableStream in exposed WritableStream interface');
|
||
const WRITABLE = 0;
|
||
const CLOSED = 1;
|
||
const ERRORING = 2;
|
||
const ERRORED = 3;
|
||
const STATE_MASK = 0xF;
|
||
const BACKPRESSURE_FLAG = 0x10;
|
||
const ObjectCreate = global.Object.create;
|
||
const Function_call = v8.uncurryThis(global.Function.prototype.call);
|
||
const TypeError = global.TypeError;
|
||
const RangeError = global.RangeError;
|
||
const Boolean = global.Boolean;
|
||
const Promise = global.Promise;
|
||
const thenPromise = v8.uncurryThis(Promise.prototype.then);
|
||
const {
|
||
_queue,
|
||
_queueTotalSize,
|
||
createPromise,
|
||
createRejectedPromise,
|
||
createResolvedPromise,
|
||
hasOwnPropertyNoThrow,
|
||
rejectPromise,
|
||
resolvePromise,
|
||
markPromiseAsHandled,
|
||
promiseState,
|
||
CreateAlgorithmFromUnderlyingMethod,
|
||
CreateAlgorithmFromUnderlyingMethodPassingController,
|
||
DequeueValue,
|
||
EnqueueValueWithSize,
|
||
MakeSizeAlgorithmFromSizeFunction,
|
||
PeekQueueValue,
|
||
ResetQueue,
|
||
ValidateAndNormalizeHighWaterMark,
|
||
CreateCrossRealmTransformReadable,
|
||
CreateCrossRealmTransformWritable,
|
||
CallOrNoop1,
|
||
} = binding.streamOperations;
|
||
const streamErrors = binding.streamErrors;
|
||
const errWriterLockReleasedPrefix =
|
||
'This writable stream writer has been released and cannot be ';
|
||
const errCloseCloseRequestedStream = 'Cannot close a writable stream that ' +
|
||
'has already been requested to be closed';
|
||
const templateErrorCannotActionOnStateStream = (action, state) =>
|
||
`Cannot ${action} a ${state} writable stream`;
|
||
const errReleasedWriterClosedPromise = 'This writable stream writer has ' +
|
||
'been released and cannot be used to monitor the stream\'s state';
|
||
const verbUsedToGetTheDesiredSize = 'used to get the desiredSize';
|
||
const verbAborted = 'aborted';
|
||
const verbClosed = 'closed';
|
||
const verbWrittenTo = 'written to';
|
||
let useCounted = false;
|
||
function createWriterLockReleasedError(verb) {
|
||
return new TypeError(errWriterLockReleasedPrefix + verb);
|
||
}
|
||
const stateNames = {
|
||
[CLOSED]: 'closed',
|
||
[ERRORED]: 'errored'
|
||
};
|
||
function createCannotActionOnStateStreamError(action, state) {
|
||
return new TypeError(
|
||
templateErrorCannotActionOnStateStream(action, stateNames[state]));
|
||
}
|
||
function rejectPromises(queue, e) {
|
||
queue.forEach(promise => rejectPromise(promise, e));
|
||
}
|
||
class WritableStream {
|
||
constructor(underlyingSink = {}, strategy = {}) {
|
||
if (!useCounted) {
|
||
binding.countUse('WritableStreamConstructor');
|
||
useCounted = true;
|
||
}
|
||
InitializeWritableStream(this);
|
||
const size = strategy.size;
|
||
let highWaterMark = strategy.highWaterMark;
|
||
const type = underlyingSink.type;
|
||
if (type !== undefined) {
|
||
throw new RangeError(streamErrors.invalidType);
|
||
}
|
||
const sizeAlgorithm = MakeSizeAlgorithmFromSizeFunction(size);
|
||
if (highWaterMark === undefined) {
|
||
highWaterMark = 1;
|
||
}
|
||
highWaterMark = ValidateAndNormalizeHighWaterMark(highWaterMark);
|
||
SetUpWritableStreamDefaultControllerFromUnderlyingSink(
|
||
this, underlyingSink, highWaterMark, sizeAlgorithm);
|
||
}
|
||
}
|
||
const WritableStream_prototype = WritableStream.prototype;
|
||
function createWritableStream(underlyingSink, strategy) {
|
||
return new WritableStream(underlyingSink, strategy);
|
||
}
|
||
function AcquireWritableStreamDefaultWriter(stream) {
|
||
return new WritableStreamDefaultWriter(stream);
|
||
}
|
||
function CreateWritableStream(
|
||
startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm,
|
||
highWaterMark, sizeAlgorithm) {
|
||
if (highWaterMark === undefined) {
|
||
highWaterMark = 1;
|
||
}
|
||
if (sizeAlgorithm === undefined) {
|
||
sizeAlgorithm = () => 1;
|
||
}
|
||
const stream = ObjectCreate(WritableStream_prototype);
|
||
InitializeWritableStream(stream);
|
||
const controller = ObjectCreate(WritableStreamDefaultController_prototype);
|
||
SetUpWritableStreamDefaultController(
|
||
stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm,
|
||
abortAlgorithm, highWaterMark, sizeAlgorithm);
|
||
return stream;
|
||
}
|
||
function InitializeWritableStream(stream) {
|
||
stream[_stateAndFlags] = WRITABLE;
|
||
stream[_storedError] = undefined;
|
||
stream[_writer] = undefined;
|
||
stream[_writableStreamController] = undefined;
|
||
stream[_inFlightWriteRequest] = undefined;
|
||
stream[_closeRequest] = undefined;
|
||
stream[_inFlightCloseRequest] = undefined;
|
||
stream[_pendingAbortRequest] = undefined;
|
||
stream[_writeRequests] = new binding.SimpleQueue();
|
||
}
|
||
function IsWritableStream(x) {
|
||
return hasOwnPropertyNoThrow(x, _writableStreamController);
|
||
}
|
||
function IsWritableStreamLocked(stream) {
|
||
return stream[_writer] !== undefined;
|
||
}
|
||
function WritableStreamAbort(stream, reason) {
|
||
const state = stream[_stateAndFlags] & STATE_MASK;
|
||
if (state === CLOSED || state === ERRORED) {
|
||
return createResolvedPromise(undefined);
|
||
}
|
||
if (stream[_pendingAbortRequest] !== undefined) {
|
||
return stream[_pendingAbortRequest].promise;
|
||
}
|
||
const wasAlreadyErroring = state === ERRORING;
|
||
if (wasAlreadyErroring) {
|
||
reason = undefined;
|
||
}
|
||
const promise = createPromise();
|
||
stream[_pendingAbortRequest] = {promise, reason, wasAlreadyErroring};
|
||
if (!wasAlreadyErroring) {
|
||
WritableStreamStartErroring(stream, reason);
|
||
}
|
||
return promise;
|
||
}
|
||
function WritableStreamAddWriteRequest(stream) {
|
||
const promise = createPromise();
|
||
stream[_writeRequests].push(promise);
|
||
return promise;
|
||
}
|
||
function WritableStreamDealWithRejection(stream, error) {
|
||
const state = stream[_stateAndFlags] & STATE_MASK;
|
||
if (state === WRITABLE) {
|
||
WritableStreamStartErroring(stream, error);
|
||
return;
|
||
}
|
||
WritableStreamFinishErroring(stream);
|
||
}
|
||
function WritableStreamStartErroring(stream, reason) {
|
||
const controller = stream[_writableStreamController];
|
||
stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | ERRORING;
|
||
stream[_storedError] = reason;
|
||
const writer = stream[_writer];
|
||
if (writer !== undefined) {
|
||
WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason);
|
||
}
|
||
if (!WritableStreamHasOperationMarkedInFlight(stream) &&
|
||
controller[_started]) {
|
||
WritableStreamFinishErroring(stream);
|
||
}
|
||
}
|
||
function WritableStreamFinishErroring(stream) {
|
||
stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | ERRORED;
|
||
WritableStreamDefaultControllerErrorSteps(
|
||
stream[_writableStreamController]);
|
||
const storedError = stream[_storedError];
|
||
rejectPromises(stream[_writeRequests], storedError);
|
||
stream[_writeRequests] = new binding.SimpleQueue();
|
||
if (stream[_pendingAbortRequest] === undefined) {
|
||
WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
|
||
return;
|
||
}
|
||
const abortRequest = stream[_pendingAbortRequest];
|
||
stream[_pendingAbortRequest] = undefined;
|
||
if (abortRequest.wasAlreadyErroring === true) {
|
||
rejectPromise(abortRequest.promise, storedError);
|
||
WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
|
||
return;
|
||
}
|
||
const promise = WritableStreamDefaultControllerAbortSteps(
|
||
stream[_writableStreamController], abortRequest.reason);
|
||
thenPromise(
|
||
promise,
|
||
() => {
|
||
resolvePromise(abortRequest.promise, undefined);
|
||
WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
|
||
},
|
||
reason => {
|
||
rejectPromise(abortRequest.promise, reason);
|
||
WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
|
||
});
|
||
}
|
||
function WritableStreamFinishInFlightWrite(stream) {
|
||
resolvePromise(stream[_inFlightWriteRequest], undefined);
|
||
stream[_inFlightWriteRequest] = undefined;
|
||
}
|
||
function WritableStreamFinishInFlightWriteWithError(stream, error) {
|
||
rejectPromise(stream[_inFlightWriteRequest], error);
|
||
stream[_inFlightWriteRequest] = undefined;
|
||
WritableStreamDealWithRejection(stream, error);
|
||
}
|
||
function WritableStreamFinishInFlightClose(stream) {
|
||
resolvePromise(stream[_inFlightCloseRequest], undefined);
|
||
stream[_inFlightCloseRequest] = undefined;
|
||
const state = stream[_stateAndFlags] & STATE_MASK;
|
||
if (state === ERRORING) {
|
||
stream[_storedError] = undefined;
|
||
if (stream[_pendingAbortRequest] !== undefined) {
|
||
resolvePromise(stream[_pendingAbortRequest].promise, undefined);
|
||
stream[_pendingAbortRequest] = undefined;
|
||
}
|
||
}
|
||
stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | CLOSED;
|
||
const writer = stream[_writer];
|
||
if (writer !== undefined) {
|
||
resolvePromise(writer[_closedPromise], undefined);
|
||
}
|
||
}
|
||
function WritableStreamFinishInFlightCloseWithError(stream, error) {
|
||
rejectPromise(stream[_inFlightCloseRequest], error);
|
||
stream[_inFlightCloseRequest] = undefined;
|
||
if (stream[_pendingAbortRequest] !== undefined) {
|
||
rejectPromise(stream[_pendingAbortRequest].promise, error);
|
||
stream[_pendingAbortRequest] = undefined;
|
||
}
|
||
WritableStreamDealWithRejection(stream, error);
|
||
}
|
||
function WritableStreamCloseQueuedOrInFlight(stream) {
|
||
return stream[_closeRequest] !== undefined ||
|
||
stream[_inFlightCloseRequest] !== undefined;
|
||
}
|
||
function WritableStreamHasOperationMarkedInFlight(stream) {
|
||
return stream[_inFlightWriteRequest] !== undefined ||
|
||
stream[_inFlightCloseRequest] !== undefined;
|
||
}
|
||
function WritableStreamMarkCloseRequestInFlight(stream) {
|
||
stream[_inFlightCloseRequest] = stream[_closeRequest];
|
||
stream[_closeRequest] = undefined;
|
||
}
|
||
function WritableStreamMarkFirstWriteRequestInFlight(stream) {
|
||
const writeRequest = stream[_writeRequests].shift();
|
||
stream[_inFlightWriteRequest] = writeRequest;
|
||
}
|
||
function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) {
|
||
if (stream[_closeRequest] !== undefined) {
|
||
rejectPromise(stream[_closeRequest], stream[_storedError]);
|
||
stream[_closeRequest] = undefined;
|
||
}
|
||
const writer = stream[_writer];
|
||
if (writer !== undefined) {
|
||
rejectPromise(writer[_closedPromise], stream[_storedError]);
|
||
markPromiseAsHandled(writer[_closedPromise]);
|
||
}
|
||
}
|
||
function WritableStreamUpdateBackpressure(stream, backpressure) {
|
||
const writer = stream[_writer];
|
||
if (writer !== undefined &&
|
||
backpressure !== Boolean(stream[_stateAndFlags] & BACKPRESSURE_FLAG)) {
|
||
if (backpressure) {
|
||
writer[_readyPromise] = createPromise();
|
||
} else {
|
||
resolvePromise(writer[_readyPromise], undefined);
|
||
}
|
||
}
|
||
if (backpressure) {
|
||
stream[_stateAndFlags] |= BACKPRESSURE_FLAG;
|
||
} else {
|
||
stream[_stateAndFlags] &= ~BACKPRESSURE_FLAG;
|
||
}
|
||
}
|
||
function WritableStreamSerialize(writable, port) {
|
||
if (IsWritableStreamLocked(writable)) {
|
||
throw new TypeError(streamErrors.cannotTransferLockedStream);
|
||
}
|
||
if (!binding.MessagePort_postMessage) {
|
||
throw new TypeError(streamErrors.cannotTransferContext);
|
||
}
|
||
const readable = CreateCrossRealmTransformReadable(port);
|
||
const promise =
|
||
binding.ReadableStreamPipeTo(readable, writable, false, false, false);
|
||
markPromiseAsHandled(promise);
|
||
}
|
||
function WritableStreamDeserialize(port) {
|
||
return CreateCrossRealmTransformWritable(port);
|
||
}
|
||
function isWritableStreamErrored(stream) {
|
||
return (stream[_stateAndFlags] & STATE_MASK) === ERRORED;
|
||
}
|
||
function isWritableStreamClosingOrClosed(stream) {
|
||
return WritableStreamCloseQueuedOrInFlight(stream) ||
|
||
(stream[_stateAndFlags] & STATE_MASK) === CLOSED;
|
||
}
|
||
function getWritableStreamStoredError(stream) {
|
||
return stream[_storedError];
|
||
}
|
||
function isWritableStreamWritable(stream) {
|
||
return (stream[_stateAndFlags] & STATE_MASK) === WRITABLE;
|
||
}
|
||
function isWritableStreamErroring(stream) {
|
||
return (stream[_stateAndFlags] & STATE_MASK) === ERRORING;
|
||
}
|
||
function getWritableStreamController(stream) {
|
||
return stream[_writableStreamController];
|
||
}
|
||
class WritableStreamDefaultWriter {
|
||
constructor(stream) {
|
||
if (stream[internalWritableStreamSymbol] !== undefined) {
|
||
stream = stream[internalWritableStreamSymbol];
|
||
}
|
||
if (!IsWritableStream(stream)) {
|
||
throw new TypeError(streamErrors.illegalConstructor);
|
||
}
|
||
if (IsWritableStreamLocked(stream)) {
|
||
throw new TypeError(streamErrors.illegalConstructor);
|
||
}
|
||
this[_ownerWritableStream] = stream;
|
||
stream[_writer] = this;
|
||
const state = stream[_stateAndFlags] & STATE_MASK;
|
||
switch (state) {
|
||
case WRITABLE: {
|
||
if (!WritableStreamCloseQueuedOrInFlight(stream) &&
|
||
stream[_stateAndFlags] & BACKPRESSURE_FLAG) {
|
||
this[_readyPromise] = createPromise();
|
||
} else {
|
||
this[_readyPromise] = createResolvedPromise(undefined);
|
||
}
|
||
this[_closedPromise] = createPromise();
|
||
break;
|
||
}
|
||
case ERRORING: {
|
||
this[_readyPromise] = createRejectedPromise(stream[_storedError]);
|
||
markPromiseAsHandled(this[_readyPromise]);
|
||
this[_closedPromise] = createPromise();
|
||
break;
|
||
}
|
||
case CLOSED: {
|
||
this[_readyPromise] = createResolvedPromise(undefined);
|
||
this[_closedPromise] = createResolvedPromise(undefined);
|
||
break;
|
||
}
|
||
default: {
|
||
const storedError = stream[_storedError];
|
||
this[_readyPromise] = createRejectedPromise(storedError);
|
||
markPromiseAsHandled(this[_readyPromise]);
|
||
this[_closedPromise] = createRejectedPromise(storedError);
|
||
markPromiseAsHandled(this[_closedPromise]);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
get closed() {
|
||
if (!IsWritableStreamDefaultWriter(this)) {
|
||
return createRejectedPromise(
|
||
new TypeError(streamErrors.illegalInvocation));
|
||
}
|
||
return this[_closedPromise];
|
||
}
|
||
get desiredSize() {
|
||
if (!IsWritableStreamDefaultWriter(this)) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
if (this[_ownerWritableStream] === undefined) {
|
||
throw createWriterLockReleasedError(verbUsedToGetTheDesiredSize);
|
||
}
|
||
return WritableStreamDefaultWriterGetDesiredSize(this);
|
||
}
|
||
get ready() {
|
||
if (!IsWritableStreamDefaultWriter(this)) {
|
||
return createRejectedPromise(
|
||
new TypeError(streamErrors.illegalInvocation));
|
||
}
|
||
return this[_readyPromise];
|
||
}
|
||
abort(reason) {
|
||
if (!IsWritableStreamDefaultWriter(this)) {
|
||
return createRejectedPromise(
|
||
new TypeError(streamErrors.illegalInvocation));
|
||
}
|
||
if (this[_ownerWritableStream] === undefined) {
|
||
return createRejectedPromise(
|
||
createWriterLockReleasedError(verbAborted));
|
||
}
|
||
return WritableStreamDefaultWriterAbort(this, reason);
|
||
}
|
||
close() {
|
||
if (!IsWritableStreamDefaultWriter(this)) {
|
||
return createRejectedPromise(
|
||
new TypeError(streamErrors.illegalInvocation));
|
||
}
|
||
const stream = this[_ownerWritableStream];
|
||
if (stream === undefined) {
|
||
return createRejectedPromise(createWriterLockReleasedError(verbClosed));
|
||
}
|
||
if (WritableStreamCloseQueuedOrInFlight(stream)) {
|
||
return createRejectedPromise(
|
||
new TypeError(errCloseCloseRequestedStream));
|
||
}
|
||
return WritableStreamDefaultWriterClose(this);
|
||
}
|
||
releaseLock() {
|
||
if (!IsWritableStreamDefaultWriter(this)) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
const stream = this[_ownerWritableStream];
|
||
if (stream === undefined) {
|
||
return;
|
||
}
|
||
WritableStreamDefaultWriterRelease(this);
|
||
}
|
||
write(chunk) {
|
||
if (!IsWritableStreamDefaultWriter(this)) {
|
||
return createRejectedPromise(
|
||
new TypeError(streamErrors.illegalInvocation));
|
||
}
|
||
if (this[_ownerWritableStream] === undefined) {
|
||
return createRejectedPromise(
|
||
createWriterLockReleasedError(verbWrittenTo));
|
||
}
|
||
return WritableStreamDefaultWriterWrite(this, chunk);
|
||
}
|
||
}
|
||
function IsWritableStreamDefaultWriter(x) {
|
||
return hasOwnPropertyNoThrow(x, _ownerWritableStream);
|
||
}
|
||
function WritableStreamDefaultWriterAbort(writer, reason) {
|
||
const stream = writer[_ownerWritableStream];
|
||
return WritableStreamAbort(stream, reason);
|
||
}
|
||
function WritableStreamDefaultWriterClose(writer) {
|
||
const stream = writer[_ownerWritableStream];
|
||
const state = stream[_stateAndFlags] & STATE_MASK;
|
||
if (state === CLOSED || state === ERRORED) {
|
||
return createRejectedPromise(
|
||
createCannotActionOnStateStreamError('close', state));
|
||
}
|
||
const promise = createPromise();
|
||
stream[_closeRequest] = promise;
|
||
if ((stream[_stateAndFlags] & BACKPRESSURE_FLAG) && state === WRITABLE) {
|
||
resolvePromise(writer[_readyPromise], undefined);
|
||
}
|
||
WritableStreamDefaultControllerClose(stream[_writableStreamController]);
|
||
return promise;
|
||
}
|
||
function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) {
|
||
const stream = writer[_ownerWritableStream];
|
||
const state = stream[_stateAndFlags] & STATE_MASK;
|
||
if (WritableStreamCloseQueuedOrInFlight(stream) || state === CLOSED) {
|
||
return createResolvedPromise(undefined);
|
||
}
|
||
if (state === ERRORED) {
|
||
return createRejectedPromise(stream[_storedError]);
|
||
}
|
||
return WritableStreamDefaultWriterClose(writer);
|
||
}
|
||
function WritableStreamDefaultWriterEnsureClosedPromiseRejected(
|
||
writer, error) {
|
||
if (promiseState(writer[_closedPromise]) === v8.kPROMISE_PENDING) {
|
||
rejectPromise(writer[_closedPromise], error);
|
||
} else {
|
||
writer[_closedPromise] = createRejectedPromise(error);
|
||
}
|
||
markPromiseAsHandled(writer[_closedPromise]);
|
||
}
|
||
function WritableStreamDefaultWriterEnsureReadyPromiseRejected(
|
||
writer, error) {
|
||
if (promiseState(writer[_readyPromise]) === v8.kPROMISE_PENDING) {
|
||
rejectPromise(writer[_readyPromise], error);
|
||
} else {
|
||
writer[_readyPromise] = createRejectedPromise(error);
|
||
}
|
||
markPromiseAsHandled(writer[_readyPromise]);
|
||
}
|
||
function WritableStreamDefaultWriterGetDesiredSize(writer) {
|
||
const stream = writer[_ownerWritableStream];
|
||
const state = stream[_stateAndFlags] & STATE_MASK;
|
||
if (state === ERRORED || state === ERRORING) {
|
||
return null;
|
||
}
|
||
if (state === CLOSED) {
|
||
return 0;
|
||
}
|
||
return WritableStreamDefaultControllerGetDesiredSize(
|
||
stream[_writableStreamController]);
|
||
}
|
||
function WritableStreamDefaultWriterRelease(writer) {
|
||
const stream = writer[_ownerWritableStream];
|
||
const releasedError = new TypeError(errReleasedWriterClosedPromise);
|
||
WritableStreamDefaultWriterEnsureReadyPromiseRejected(
|
||
writer, releasedError);
|
||
WritableStreamDefaultWriterEnsureClosedPromiseRejected(
|
||
writer, releasedError);
|
||
stream[_writer] = undefined;
|
||
writer[_ownerWritableStream] = undefined;
|
||
}
|
||
function WritableStreamDefaultWriterWrite(writer, chunk) {
|
||
const stream = writer[_ownerWritableStream];
|
||
const controller = stream[_writableStreamController];
|
||
const chunkSize =
|
||
WritableStreamDefaultControllerGetChunkSize(controller, chunk);
|
||
if (stream !== writer[_ownerWritableStream]) {
|
||
return createRejectedPromise(
|
||
createWriterLockReleasedError(verbWrittenTo));
|
||
}
|
||
const state = stream[_stateAndFlags] & STATE_MASK;
|
||
if (state === ERRORED) {
|
||
return createRejectedPromise(stream[_storedError]);
|
||
}
|
||
if (WritableStreamCloseQueuedOrInFlight(stream)) {
|
||
return createRejectedPromise(new TypeError(
|
||
templateErrorCannotActionOnStateStream('write to', 'closing')));
|
||
}
|
||
if (state === CLOSED) {
|
||
return createRejectedPromise(
|
||
createCannotActionOnStateStreamError('write to', CLOSED));
|
||
}
|
||
if (state === ERRORING) {
|
||
return createRejectedPromise(stream[_storedError]);
|
||
}
|
||
const promise = WritableStreamAddWriteRequest(stream);
|
||
WritableStreamDefaultControllerWrite(controller, chunk, chunkSize);
|
||
return promise;
|
||
}
|
||
function getWritableStreamDefaultWriterClosedPromise(writer) {
|
||
return writer[_closedPromise];
|
||
}
|
||
function getWritableStreamDefaultWriterReadyPromise(writer) {
|
||
return writer[_readyPromise];
|
||
}
|
||
class WritableStreamDefaultController {
|
||
constructor() {
|
||
throw new TypeError(streamErrors.illegalConstructor);
|
||
}
|
||
error(e) {
|
||
if (!IsWritableStreamDefaultController(this)) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
const state =
|
||
this[_controlledWritableStream][_stateAndFlags] & STATE_MASK;
|
||
if (state !== WRITABLE) {
|
||
return;
|
||
}
|
||
WritableStreamDefaultControllerError(this, e);
|
||
}
|
||
}
|
||
const WritableStreamDefaultController_prototype =
|
||
WritableStreamDefaultController.prototype;
|
||
function WritableStreamDefaultControllerAbortSteps(controller, reason) {
|
||
const result = controller[_abortAlgorithm](reason);
|
||
WritableStreamDefaultControllerClearAlgorithms(controller);
|
||
return result;
|
||
}
|
||
function WritableStreamDefaultControllerErrorSteps(controller) {
|
||
ResetQueue(controller);
|
||
}
|
||
function IsWritableStreamDefaultController(x) {
|
||
return hasOwnPropertyNoThrow(x, _controlledWritableStream);
|
||
}
|
||
function SetUpWritableStreamDefaultController(
|
||
stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm,
|
||
abortAlgorithm, highWaterMark, sizeAlgorithm) {
|
||
controller[_controlledWritableStream] = stream;
|
||
stream[_writableStreamController] = controller;
|
||
controller[_queue] = undefined;
|
||
controller[_queueTotalSize] = undefined;
|
||
ResetQueue(controller);
|
||
controller[_started] = false;
|
||
controller[_strategySizeAlgorithm] = sizeAlgorithm;
|
||
controller[_strategyHWM] = highWaterMark;
|
||
controller[_writeAlgorithm] = writeAlgorithm;
|
||
controller[_closeAlgorithm] = closeAlgorithm;
|
||
controller[_abortAlgorithm] = abortAlgorithm;
|
||
const backpressure =
|
||
WritableStreamDefaultControllerGetBackpressure(controller);
|
||
WritableStreamUpdateBackpressure(stream, backpressure);
|
||
const startResult = startAlgorithm();
|
||
const startPromise = createResolvedPromise(startResult);
|
||
thenPromise(
|
||
startPromise,
|
||
() => {
|
||
controller[_started] = true;
|
||
WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
|
||
},
|
||
r => {
|
||
controller[_started] = true;
|
||
WritableStreamDealWithRejection(stream, r);
|
||
});
|
||
}
|
||
function SetUpWritableStreamDefaultControllerFromUnderlyingSink(
|
||
stream, underlyingSink, highWaterMark, sizeAlgorithm) {
|
||
const controller = ObjectCreate(WritableStreamDefaultController_prototype);
|
||
const startAlgorithm =
|
||
() => CallOrNoop1(underlyingSink, 'start', controller,
|
||
'underlyingSink.start');
|
||
const writeAlgorithm = CreateAlgorithmFromUnderlyingMethodPassingController(
|
||
underlyingSink, 'write', 1, controller, 'underlyingSink.write');
|
||
const closeAlgorithm = CreateAlgorithmFromUnderlyingMethod(
|
||
underlyingSink, 'close', 0, 'underlyingSink.close');
|
||
const abortAlgorithm = CreateAlgorithmFromUnderlyingMethod(
|
||
underlyingSink, 'abort', 1, 'underlyingSink.abort');
|
||
SetUpWritableStreamDefaultController(stream, controller, startAlgorithm,
|
||
writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark,
|
||
sizeAlgorithm);
|
||
}
|
||
function WritableStreamDefaultControllerClearAlgorithms(controller) {
|
||
controller[_writeAlgorithm] = undefined;
|
||
controller[_closeAlgorithm] = undefined;
|
||
controller[_abortAlgorithm] = undefined;
|
||
}
|
||
function WritableStreamDefaultControllerClose(controller) {
|
||
EnqueueValueWithSize(controller, 'close', 0);
|
||
WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
|
||
}
|
||
function WritableStreamDefaultControllerGetChunkSize(controller, chunk) {
|
||
try {
|
||
return Function_call(controller[_strategySizeAlgorithm], undefined,
|
||
chunk);
|
||
} catch (e) {
|
||
WritableStreamDefaultControllerErrorIfNeeded(controller, e);
|
||
return 1;
|
||
}
|
||
}
|
||
function WritableStreamDefaultControllerGetDesiredSize(controller) {
|
||
return controller[_strategyHWM] - controller[_queueTotalSize];
|
||
}
|
||
function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) {
|
||
const writeRecord = {chunk};
|
||
try {
|
||
EnqueueValueWithSize(controller, writeRecord, chunkSize);
|
||
} catch (e) {
|
||
WritableStreamDefaultControllerErrorIfNeeded(controller, e);
|
||
return;
|
||
}
|
||
const stream = controller[_controlledWritableStream];
|
||
if (!WritableStreamCloseQueuedOrInFlight(stream) &&
|
||
(stream[_stateAndFlags] & STATE_MASK) === WRITABLE) {
|
||
const backpressure =
|
||
WritableStreamDefaultControllerGetBackpressure(controller);
|
||
WritableStreamUpdateBackpressure(stream, backpressure);
|
||
}
|
||
WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
|
||
}
|
||
function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) {
|
||
const stream = controller[_controlledWritableStream];
|
||
if (!controller[_started]) {
|
||
return;
|
||
}
|
||
if (stream[_inFlightWriteRequest] !== undefined) {
|
||
return;
|
||
}
|
||
const state = stream[_stateAndFlags] & STATE_MASK;
|
||
if (state === CLOSED || state === ERRORED) {
|
||
return;
|
||
}
|
||
if (state === ERRORING) {
|
||
WritableStreamFinishErroring(stream);
|
||
return;
|
||
}
|
||
if (controller[_queue].length === 0) {
|
||
return;
|
||
}
|
||
const writeRecord = PeekQueueValue(controller);
|
||
if (writeRecord === 'close') {
|
||
WritableStreamDefaultControllerProcessClose(controller);
|
||
} else {
|
||
WritableStreamDefaultControllerProcessWrite(
|
||
controller, writeRecord.chunk);
|
||
}
|
||
}
|
||
function WritableStreamDefaultControllerErrorIfNeeded(controller, error) {
|
||
const state =
|
||
controller[_controlledWritableStream][_stateAndFlags] & STATE_MASK;
|
||
if (state === WRITABLE) {
|
||
WritableStreamDefaultControllerError(controller, error);
|
||
}
|
||
}
|
||
function WritableStreamDefaultControllerProcessClose(controller) {
|
||
const stream = controller[_controlledWritableStream];
|
||
WritableStreamMarkCloseRequestInFlight(stream);
|
||
DequeueValue(controller);
|
||
const sinkClosePromise = controller[_closeAlgorithm]();
|
||
WritableStreamDefaultControllerClearAlgorithms(controller);
|
||
thenPromise(
|
||
sinkClosePromise, () => WritableStreamFinishInFlightClose(stream),
|
||
reason => WritableStreamFinishInFlightCloseWithError(stream, reason));
|
||
}
|
||
function WritableStreamDefaultControllerProcessWrite(controller, chunk) {
|
||
const stream = controller[_controlledWritableStream];
|
||
WritableStreamMarkFirstWriteRequestInFlight(stream);
|
||
const sinkWritePromise = controller[_writeAlgorithm](chunk);
|
||
thenPromise(
|
||
sinkWritePromise,
|
||
() => {
|
||
WritableStreamFinishInFlightWrite(stream);
|
||
const state = stream[_stateAndFlags] & STATE_MASK;
|
||
DequeueValue(controller);
|
||
if (!WritableStreamCloseQueuedOrInFlight(stream) &&
|
||
state === WRITABLE) {
|
||
const backpressure =
|
||
WritableStreamDefaultControllerGetBackpressure(controller);
|
||
WritableStreamUpdateBackpressure(stream, backpressure);
|
||
}
|
||
WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
|
||
},
|
||
reason => {
|
||
const state = stream[_stateAndFlags] & STATE_MASK;
|
||
if (state === WRITABLE) {
|
||
WritableStreamDefaultControllerClearAlgorithms(controller);
|
||
}
|
||
WritableStreamFinishInFlightWriteWithError(stream, reason);
|
||
});
|
||
}
|
||
function WritableStreamDefaultControllerGetBackpressure(controller) {
|
||
const desiredSize =
|
||
WritableStreamDefaultControllerGetDesiredSize(controller);
|
||
return desiredSize <= 0;
|
||
}
|
||
function WritableStreamDefaultControllerError(controller, error) {
|
||
const stream = controller[_controlledWritableStream];
|
||
WritableStreamDefaultControllerClearAlgorithms(controller);
|
||
WritableStreamStartErroring(stream, error);
|
||
}
|
||
Object.assign(binding, {
|
||
AcquireWritableStreamDefaultWriter,
|
||
IsWritableStream,
|
||
isWritableStreamClosingOrClosed,
|
||
isWritableStreamErrored,
|
||
isWritableStreamWritable,
|
||
IsWritableStreamLocked,
|
||
WritableStreamAbort,
|
||
WritableStreamCloseQueuedOrInFlight,
|
||
WritableStreamDefaultWriterCloseWithErrorPropagation,
|
||
getWritableStreamDefaultWriterClosedPromise,
|
||
WritableStreamDefaultWriterGetDesiredSize,
|
||
getWritableStreamDefaultWriterReadyPromise,
|
||
WritableStreamDefaultWriterRelease,
|
||
WritableStreamDefaultWriterWrite,
|
||
getWritableStreamStoredError,
|
||
createWritableStream,
|
||
internalWritableStreamSymbol,
|
||
WritableStreamSerialize,
|
||
WritableStreamDeserialize,
|
||
CreateWritableStream,
|
||
WritableStream,
|
||
WritableStreamDefaultControllerErrorIfNeeded,
|
||
isWritableStreamErroring,
|
||
getWritableStreamController,
|
||
WritableStreamDefaultControllerClose,
|
||
});
|
||
});
|
||
<TransformStreamMË
|
||
(function(global, binding, v8) {
|
||
'use strict';
|
||
const _backpressure = v8.createPrivateSymbol('[[backpressure]]');
|
||
const _backpressureChangePromise =
|
||
v8.createPrivateSymbol('[[backpressureChangePromise]]');
|
||
const _readable = v8.createPrivateSymbol('[[readable]]');
|
||
const _transformStreamController =
|
||
v8.createPrivateSymbol('[[transformStreamController]]');
|
||
const _writable = v8.createPrivateSymbol('[[writable]]');
|
||
const _controlledTransformStream =
|
||
v8.createPrivateSymbol('[[controlledTransformStream]]');
|
||
const _flushAlgorithm = v8.createPrivateSymbol('[[flushAlgorithm]]');
|
||
const _transformAlgorithm = v8.createPrivateSymbol('[[transformAlgorithm]]');
|
||
const ObjectCreate = global.Object.create;
|
||
const TypeError = global.TypeError;
|
||
const RangeError = global.RangeError;
|
||
const Promise = global.Promise;
|
||
const thenPromise = v8.uncurryThis(Promise.prototype.then);
|
||
const {
|
||
createPromise,
|
||
createRejectedPromise,
|
||
createResolvedPromise,
|
||
hasOwnPropertyNoThrow,
|
||
resolvePromise,
|
||
CreateAlgorithmFromUnderlyingMethod,
|
||
CallOrNoop1,
|
||
MakeSizeAlgorithmFromSizeFunction,
|
||
PromiseCall2,
|
||
ValidateAndNormalizeHighWaterMark
|
||
} = binding.streamOperations;
|
||
const streamErrors = binding.streamErrors;
|
||
const errStreamTerminated = 'The transform stream has been terminated';
|
||
let useCounted = false;
|
||
class TransformStream {
|
||
constructor(transformer = {},
|
||
writableStrategy = {}, readableStrategy = {}) {
|
||
if (!useCounted) {
|
||
binding.countUse('TransformStreamConstructor');
|
||
useCounted = true;
|
||
}
|
||
const writableSizeFunction = writableStrategy.size;
|
||
let writableHighWaterMark = writableStrategy.highWaterMark;
|
||
const readableSizeFunction = readableStrategy.size;
|
||
let readableHighWaterMark = readableStrategy.highWaterMark;
|
||
const writableType = transformer.writableType;
|
||
if (writableType !== undefined) {
|
||
throw new RangeError(streamErrors.invalidType);
|
||
}
|
||
const writableSizeAlgorithm =
|
||
MakeSizeAlgorithmFromSizeFunction(writableSizeFunction);
|
||
if (writableHighWaterMark === undefined) {
|
||
writableHighWaterMark = 1;
|
||
}
|
||
writableHighWaterMark =
|
||
ValidateAndNormalizeHighWaterMark(writableHighWaterMark);
|
||
const readableType = transformer.readableType;
|
||
if (readableType !== undefined) {
|
||
throw new RangeError(streamErrors.invalidType);
|
||
}
|
||
const readableSizeAlgorithm =
|
||
MakeSizeAlgorithmFromSizeFunction(readableSizeFunction);
|
||
if (readableHighWaterMark === undefined) {
|
||
readableHighWaterMark = 0;
|
||
}
|
||
readableHighWaterMark =
|
||
ValidateAndNormalizeHighWaterMark(readableHighWaterMark);
|
||
const startPromise = createPromise();
|
||
InitializeTransformStream(
|
||
this, startPromise, writableHighWaterMark, writableSizeAlgorithm,
|
||
readableHighWaterMark, readableSizeAlgorithm);
|
||
SetUpTransformStreamDefaultControllerFromTransformer(this, transformer);
|
||
const startResult = CallOrNoop1(
|
||
transformer, 'start', this[_transformStreamController],
|
||
'transformer.start');
|
||
resolvePromise(startPromise, startResult);
|
||
}
|
||
get readable() {
|
||
if (!IsTransformStream(this)) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
return this[_readable];
|
||
}
|
||
get writable() {
|
||
if (!IsTransformStream(this)) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
return this[_writable];
|
||
}
|
||
}
|
||
const TransformStream_prototype = TransformStream.prototype;
|
||
function CreateTransformStream(
|
||
startAlgorithm, transformAlgorithm, flushAlgorithm, writableHighWaterMark,
|
||
writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm) {
|
||
if (writableHighWaterMark === undefined) {
|
||
writableHighWaterMark = 1;
|
||
}
|
||
if (writableSizeAlgorithm === undefined) {
|
||
writableSizeAlgorithm = () => 1;
|
||
}
|
||
if (readableHighWaterMark === undefined) {
|
||
readableHighWaterMark = 0;
|
||
}
|
||
if (readableSizeAlgorithm === undefined) {
|
||
readableSizeAlgorithm = () => 1;
|
||
}
|
||
const stream = ObjectCreate(TransformStream_prototype);
|
||
const startPromise = createPromise();
|
||
InitializeTransformStream(
|
||
stream, startPromise, writableHighWaterMark, writableSizeAlgorithm,
|
||
readableHighWaterMark, readableSizeAlgorithm);
|
||
const controller = ObjectCreate(TransformStreamDefaultController_prototype);
|
||
SetUpTransformStreamDefaultController(
|
||
stream, controller, transformAlgorithm, flushAlgorithm);
|
||
const startResult = startAlgorithm();
|
||
resolvePromise(startPromise, startResult);
|
||
return stream;
|
||
}
|
||
function InitializeTransformStream(
|
||
stream, startPromise, writableHighWaterMark, writableSizeAlgorithm,
|
||
readableHighWaterMark, readableSizeAlgorithm) {
|
||
const startAlgorithm = () => startPromise;
|
||
const writeAlgorithm = chunk =>
|
||
TransformStreamDefaultSinkWriteAlgorithm(stream, chunk);
|
||
const abortAlgorithm = reason =>
|
||
TransformStreamDefaultSinkAbortAlgorithm(stream, reason);
|
||
const closeAlgorithm = () =>
|
||
TransformStreamDefaultSinkCloseAlgorithm(stream);
|
||
stream[_writable] = binding.CreateWritableStream(
|
||
startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm,
|
||
writableHighWaterMark, writableSizeAlgorithm);
|
||
const pullAlgorithm = () =>
|
||
TransformStreamDefaultSourcePullAlgorithm(stream);
|
||
const cancelAlgorithm = reason => {
|
||
TransformStreamErrorWritableAndUnblockWrite(stream, reason);
|
||
return createResolvedPromise(undefined);
|
||
};
|
||
stream[_readable] = binding.CreateReadableStream(
|
||
startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark,
|
||
readableSizeAlgorithm, false);
|
||
stream[_backpressure] = undefined;
|
||
stream[_backpressureChangePromise] = undefined;
|
||
TransformStreamSetBackpressure(stream, true);
|
||
stream[_transformStreamController] = undefined;
|
||
}
|
||
function IsTransformStream(x) {
|
||
return hasOwnPropertyNoThrow(x, _transformStreamController);
|
||
}
|
||
function TransformStreamError(stream, e) {
|
||
const readable = stream[_readable];
|
||
if (binding.IsReadableStreamReadable(readable)) {
|
||
binding.ReadableStreamDefaultControllerError(
|
||
binding.getReadableStreamController(readable), e);
|
||
}
|
||
TransformStreamErrorWritableAndUnblockWrite(stream, e);
|
||
}
|
||
function TransformStreamErrorWritableAndUnblockWrite(stream, e) {
|
||
TransformStreamDefaultControllerClearAlgorithms(
|
||
stream[_transformStreamController]);
|
||
binding.WritableStreamDefaultControllerErrorIfNeeded(
|
||
binding.getWritableStreamController(stream[_writable]), e);
|
||
if (stream[_backpressure]) {
|
||
TransformStreamSetBackpressure(stream, false);
|
||
}
|
||
}
|
||
function TransformStreamSetBackpressure(stream, backpressure) {
|
||
if (stream[_backpressureChangePromise] !== undefined) {
|
||
resolvePromise(stream[_backpressureChangePromise], undefined);
|
||
}
|
||
stream[_backpressureChangePromise] = createPromise();
|
||
stream[_backpressure] = backpressure;
|
||
}
|
||
class TransformStreamDefaultController {
|
||
constructor() {
|
||
throw new TypeError(streamErrors.illegalConstructor);
|
||
}
|
||
get desiredSize() {
|
||
if (!IsTransformStreamDefaultController(this)) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
const readableController = binding.getReadableStreamController(
|
||
this[_controlledTransformStream][_readable]);
|
||
return binding.ReadableStreamDefaultControllerGetDesiredSize(
|
||
readableController);
|
||
}
|
||
enqueue(chunk) {
|
||
if (!IsTransformStreamDefaultController(this)) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
TransformStreamDefaultControllerEnqueue(this, chunk);
|
||
}
|
||
error(reason) {
|
||
if (!IsTransformStreamDefaultController(this)) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
TransformStreamDefaultControllerError(this, reason);
|
||
}
|
||
terminate() {
|
||
if (!IsTransformStreamDefaultController(this)) {
|
||
throw new TypeError(streamErrors.illegalInvocation);
|
||
}
|
||
TransformStreamDefaultControllerTerminate(this);
|
||
}
|
||
}
|
||
const TransformStreamDefaultController_prototype =
|
||
TransformStreamDefaultController.prototype;
|
||
function IsTransformStreamDefaultController(x) {
|
||
return hasOwnPropertyNoThrow(x, _controlledTransformStream);
|
||
}
|
||
function SetUpTransformStreamDefaultController(
|
||
stream, controller, transformAlgorithm, flushAlgorithm) {
|
||
controller[_controlledTransformStream] = stream;
|
||
stream[_transformStreamController] = controller;
|
||
controller[_transformAlgorithm] = transformAlgorithm;
|
||
controller[_flushAlgorithm] = flushAlgorithm;
|
||
}
|
||
function SetUpTransformStreamDefaultControllerFromTransformer(
|
||
stream, transformer) {
|
||
const controller = ObjectCreate(TransformStreamDefaultController_prototype);
|
||
let transformAlgorithm;
|
||
const transformMethod = transformer.transform;
|
||
if (transformMethod !== undefined) {
|
||
if (typeof transformMethod !== 'function') {
|
||
throw new TypeError('transformer.transform is not a function');
|
||
}
|
||
transformAlgorithm = chunk =>
|
||
PromiseCall2(transformMethod, transformer, chunk, controller);
|
||
} else {
|
||
transformAlgorithm = chunk => {
|
||
try {
|
||
TransformStreamDefaultControllerEnqueue(controller, chunk);
|
||
return createResolvedPromise();
|
||
} catch (resultValue) {
|
||
return createRejectedPromise(resultValue);
|
||
}
|
||
};
|
||
}
|
||
const flushAlgorithm = CreateAlgorithmFromUnderlyingMethod(
|
||
transformer, 'flush', 1, 'transformer.flush');
|
||
SetUpTransformStreamDefaultController(
|
||
stream, controller, transformAlgorithm, flushAlgorithm);
|
||
}
|
||
function TransformStreamDefaultControllerClearAlgorithms(controller) {
|
||
controller[_transformAlgorithm] = undefined;
|
||
controller[_flushAlgorithm] = undefined;
|
||
}
|
||
function TransformStreamDefaultControllerEnqueue(controller, chunk) {
|
||
const stream = controller[_controlledTransformStream];
|
||
const readableController =
|
||
binding.getReadableStreamController(stream[_readable]);
|
||
if (!binding.ReadableStreamDefaultControllerCanCloseOrEnqueue(
|
||
readableController)) {
|
||
throw binding.getReadableStreamEnqueueError(stream[_readable]);
|
||
}
|
||
try {
|
||
binding.ReadableStreamDefaultControllerEnqueue(readableController, chunk);
|
||
} catch (e) {
|
||
TransformStreamErrorWritableAndUnblockWrite(stream, e);
|
||
throw binding.getReadableStreamStoredError(stream[_readable]);
|
||
}
|
||
const backpressure = binding.ReadableStreamDefaultControllerHasBackpressure(
|
||
readableController);
|
||
if (backpressure !== stream[_backpressure]) {
|
||
TransformStreamSetBackpressure(stream, true);
|
||
}
|
||
}
|
||
function TransformStreamDefaultControllerError(controller, e) {
|
||
TransformStreamError(controller[_controlledTransformStream], e);
|
||
}
|
||
function TransformStreamDefaultControllerPerformTransform(controller, chunk) {
|
||
const transformPromise = controller[_transformAlgorithm](chunk, controller);
|
||
return thenPromise(transformPromise, undefined, r => {
|
||
TransformStreamError(controller[_controlledTransformStream], r);
|
||
throw r;
|
||
});
|
||
}
|
||
function TransformStreamDefaultControllerTerminate(controller) {
|
||
const stream = controller[_controlledTransformStream];
|
||
const readableController =
|
||
binding.getReadableStreamController(stream[_readable]);
|
||
if (binding.ReadableStreamDefaultControllerCanCloseOrEnqueue(
|
||
readableController)) {
|
||
binding.ReadableStreamDefaultControllerClose(readableController);
|
||
}
|
||
const error = new TypeError(errStreamTerminated);
|
||
TransformStreamErrorWritableAndUnblockWrite(stream, error);
|
||
}
|
||
function TransformStreamDefaultSinkWriteAlgorithm(stream, chunk) {
|
||
const controller = stream[_transformStreamController];
|
||
if (stream[_backpressure]) {
|
||
const backpressureChangePromise = stream[_backpressureChangePromise];
|
||
return thenPromise(backpressureChangePromise, () => {
|
||
const writable = stream[_writable];
|
||
if (binding.isWritableStreamErroring(writable)) {
|
||
throw binding.getWritableStreamStoredError(writable);
|
||
}
|
||
return TransformStreamDefaultControllerPerformTransform(controller,
|
||
chunk);
|
||
});
|
||
}
|
||
return TransformStreamDefaultControllerPerformTransform(controller, chunk);
|
||
}
|
||
function TransformStreamDefaultSinkAbortAlgorithm(stream, reason) {
|
||
TransformStreamError(stream, reason);
|
||
return createResolvedPromise();
|
||
}
|
||
function TransformStreamDefaultSinkCloseAlgorithm(stream) {
|
||
const readable = stream[_readable];
|
||
const controller = stream[_transformStreamController];
|
||
const flushPromise = controller[_flushAlgorithm](controller);
|
||
TransformStreamDefaultControllerClearAlgorithms(controller);
|
||
return thenPromise(
|
||
flushPromise,
|
||
() => {
|
||
if (binding.IsReadableStreamErrored(readable)) {
|
||
throw binding.getReadableStreamStoredError(readable);
|
||
}
|
||
const readableController =
|
||
binding.getReadableStreamController(readable);
|
||
if (binding.ReadableStreamDefaultControllerCanCloseOrEnqueue(
|
||
readableController)) {
|
||
binding.ReadableStreamDefaultControllerClose(readableController);
|
||
}
|
||
},
|
||
r => {
|
||
TransformStreamError(stream, r);
|
||
throw binding.getReadableStreamStoredError(readable);
|
||
});
|
||
}
|
||
function TransformStreamDefaultSourcePullAlgorithm(stream) {
|
||
TransformStreamSetBackpressure(stream, false);
|
||
return stream[_backpressureChangePromise];
|
||
}
|
||
function createTransformStreamSimple(transformAlgorithm, flushAlgorithm) {
|
||
return CreateTransformStream(() => createResolvedPromise(),
|
||
transformAlgorithm, flushAlgorithm);
|
||
}
|
||
function createTransformStream(
|
||
transformer, writableStrategy, readableStrategy) {
|
||
if (transformer === undefined) {
|
||
transformer = ObjectCreate(null);
|
||
}
|
||
if (writableStrategy === undefined) {
|
||
writableStrategy = ObjectCreate(null);
|
||
}
|
||
if (readableStrategy === undefined) {
|
||
readableStrategy = ObjectCreate(null);
|
||
}
|
||
return new TransformStream(transformer, writableStrategy, readableStrategy);
|
||
}
|
||
function getTransformStreamReadable(stream) {
|
||
return stream[_readable];
|
||
}
|
||
function getTransformStreamWritable(stream) {
|
||
return stream[_writable];
|
||
}
|
||
Object.assign(binding, {
|
||
createTransformStreamSimple,
|
||
createTransformStream,
|
||
TransformStreamDefaultControllerEnqueue,
|
||
getTransformStreamReadable,
|
||
getTransformStreamWritable
|
||
});
|
||
});
|