2601 lines
81 KiB
Plaintext
2601 lines
81 KiB
Plaintext
|
@CommonOperationsU<73>
|
|||
|
(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<EFBFBD>
|
|||
|
(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<75>
|
|||
|
(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<16>
|
|||
|
(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<EFBFBD>
|
|||
|
(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<6D>
|
|||
|
(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
|
|||
|
});
|
|||
|
});
|