Commit ef0fc520 authored by Adam Rice's avatar Adam Rice Committed by Commit Bot

Mark all streams-created promises with isSettled flag

Wrap v8.createPromise() in a createPromise() function which always sets
the isSettled flag to false. Make resolvePromise() and rejectPromise()
ignore promises that don't have the isSettled flag present. Replace
Promise_resolve() and Promise_reject() with createResolvedPromise() and
createRejectedPromise() functions that also set the isSettled flag.

Strictly speaking, the createR*Promise() functions only need to be used
when a promise is stored and might be resolved or rejected later. But to
avoid confusion about where they are needed, always use them in place of
Promise_resolve() and Promise_reject().

BUG=931640

Change-Id: I5472cb4a78f7b970ab256084b819ae28ffda6a33
Reviewed-on: https://chromium-review.googlesource.com/c/1481178Reviewed-by: default avatarYutaka Hirano <yhirano@chromium.org>
Commit-Queue: Adam Rice <ricea@chromium.org>
Cr-Commit-Position: refs/heads/master@{#635449}
parent afc1d6a7
...@@ -73,12 +73,27 @@ ...@@ -73,12 +73,27 @@
throw new RangeError('Stream API Internal Error'); throw new RangeError('Stream API Internal Error');
} }
// For safety, this must always be used in place of calling v8.createPromise()
// directly.
function createPromise() {
const p = v8.createPromise();
p[_isSettled] = false;
return p;
}
// Calling v8.rejectPromise() directly is very dangerous. Always use this
// wrapper.
function rejectPromise(p, reason) { function rejectPromise(p, reason) {
if (!v8.isPromise(p)) { if (!v8.isPromise(p)) {
streamInternalError(); streamInternalError();
} }
if (p[_isSettled]) { // assert(typeof p[_isSettled] === 'boolean',
// 'Type(p.[[isSettled]]) is `"boolean"`');
// Note that this makes the function a no-op for promises that were not
// created via createPromise(). This is critical for security.
if (p[_isSettled] !== false) {
return; return;
} }
p[_isSettled] = true; p[_isSettled] = true;
...@@ -86,12 +101,27 @@ ...@@ -86,12 +101,27 @@
v8.rejectPromise(p, reason); v8.rejectPromise(p, reason);
} }
// This must always be used instead of Promise.reject().
function createRejectedPromise(reason) {
const p = createPromise();
rejectPromise(p, reason);
return p;
}
// Calling v8.resolvePromise() directly is very dangerous. Always use this
// wrapper. If |value| is an object this will look up Object.prototype.then
// and so may be re-entrant.
function resolvePromise(p, value) { function resolvePromise(p, value) {
if (!v8.isPromise(p)) { if (!v8.isPromise(p)) {
streamInternalError(); streamInternalError();
} }
if (p[_isSettled]) { // assert(typeof p[_isSettled] === 'boolean',
// 'Type(p.[[isSettled]]) is `"boolean"`');
// Note that this makes the function a no-op for promises that were not
// created via createPromise(). This is critical for security.
if (p[_isSettled] !== false) {
return; return;
} }
p[_isSettled] = true; p[_isSettled] = true;
...@@ -99,6 +129,20 @@ ...@@ -99,6 +129,20 @@
v8.resolvePromise(p, value); v8.resolvePromise(p, value);
} }
// This must always be used instead of Promise.resolve(). If |value| is an
// object this will look up Object.prototype.then and so may be re-entrant.
function createResolvedPromise(value) {
if (v8.isPromise(value)) {
// This case applies when an underlying method returns a promise. Promises
// that are passed through in this way are not used with resolvePromise()
// or rejectPromise().
return value;
}
const p = createPromise();
resolvePromise(p, value);
return p;
}
function markPromiseAsHandled(p) { function markPromiseAsHandled(p) {
if (!v8.isPromise(p)) { if (!v8.isPromise(p)) {
streamInternalError(); streamInternalError();
...@@ -207,8 +251,6 @@ ...@@ -207,8 +251,6 @@
const callFunction = v8.uncurryThis(global.Function.prototype.call); const callFunction = v8.uncurryThis(global.Function.prototype.call);
const errTmplMustBeFunctionOrUndefined = name => const errTmplMustBeFunctionOrUndefined = name =>
`${name} must be a function or undefined`; `${name} must be a function or undefined`;
const Promise_resolve = Promise.resolve.bind(Promise);
const Promise_reject = Promise.reject.bind(Promise);
const Function_bind = v8.uncurryThis(global.Function.prototype.bind); const Function_bind = v8.uncurryThis(global.Function.prototype.bind);
function resolveMethod(O, P, nameForError) { function resolveMethod(O, P, nameForError) {
...@@ -237,7 +279,7 @@ ...@@ -237,7 +279,7 @@
// The implementation uses bound functions rather than lambdas where // The implementation uses bound functions rather than lambdas where
// possible to give the compiler the maximum opportunity to optimise. // possible to give the compiler the maximum opportunity to optimise.
if (method === undefined) { if (method === undefined) {
return () => Promise_resolve(); return () => createResolvedPromise();
} }
if (algoArgCount === 0) { if (algoArgCount === 0) {
...@@ -263,7 +305,7 @@ ...@@ -263,7 +305,7 @@
const method = const method =
resolveMethod(underlyingObject, methodName, methodNameForError); resolveMethod(underlyingObject, methodName, methodNameForError);
if (method === undefined) { if (method === undefined) {
return () => Promise_resolve(); return () => createResolvedPromise();
} }
if (algoArgCount === 0) { if (algoArgCount === 0) {
...@@ -288,9 +330,9 @@ ...@@ -288,9 +330,9 @@
// assert(typeof F === 'function', 'IsCallable(F) is true.'); // assert(typeof F === 'function', 'IsCallable(F) is true.');
// assert(V !== undefined, 'V is not undefined.'); // assert(V !== undefined, 'V is not undefined.');
try { try {
return Promise_resolve(callFunction(F, V)); return createResolvedPromise(callFunction(F, V));
} catch (e) { } catch (e) {
return Promise_reject(e); return createRejectedPromise(e);
} }
} }
...@@ -298,9 +340,9 @@ ...@@ -298,9 +340,9 @@
// assert(typeof F === 'function', 'IsCallable(F) is true.'); // assert(typeof F === 'function', 'IsCallable(F) is true.');
// assert(V !== undefined, 'V is not undefined.'); // assert(V !== undefined, 'V is not undefined.');
try { try {
return Promise_resolve(callFunction(F, V, arg0)); return createResolvedPromise(callFunction(F, V, arg0));
} catch (e) { } catch (e) {
return Promise_reject(e); return createRejectedPromise(e);
} }
} }
...@@ -308,9 +350,9 @@ ...@@ -308,9 +350,9 @@
// assert(typeof F === 'function', 'IsCallable(F) is true.'); // assert(typeof F === 'function', 'IsCallable(F) is true.');
// assert(V !== undefined, 'V is not undefined.'); // assert(V !== undefined, 'V is not undefined.');
try { try {
return Promise_resolve(callFunction(F, V, arg0, arg1)); return createResolvedPromise(callFunction(F, V, arg0, arg1));
} catch (e) { } catch (e) {
return Promise_reject(e); return createRejectedPromise(e);
} }
} }
...@@ -408,7 +450,7 @@ ...@@ -408,7 +450,7 @@
} }
function CreateCrossRealmTransformWritable(port) { function CreateCrossRealmTransformWritable(port) {
let backpressurePromise = v8.createPromise(); let backpressurePromise = createPromise();
callFunction(binding.EventTarget_addEventListener, port, 'message', evt => { callFunction(binding.EventTarget_addEventListener, port, 'message', evt => {
const {type, value} = callFunction(binding.MessageEvent_data_get, evt); const {type, value} = callFunction(binding.MessageEvent_data_get, evt);
...@@ -446,7 +488,7 @@ ...@@ -446,7 +488,7 @@
callFunction(binding.MessagePort_start, port); callFunction(binding.MessagePort_start, port);
function doWrite(chunk) { function doWrite(chunk) {
backpressurePromise = v8.createPromise(); backpressurePromise = createPromise();
try { try {
callFunction( callFunction(
binding.MessagePort_postMessage, port, binding.MessagePort_postMessage, port,
...@@ -473,14 +515,14 @@ ...@@ -473,14 +515,14 @@
binding.MessagePort_postMessage, port, binding.MessagePort_postMessage, port,
{type: kClose, value: undefined}); {type: kClose, value: undefined});
callFunction(binding.MessagePort_close, port); callFunction(binding.MessagePort_close, port);
return Promise_resolve(); return createResolvedPromise();
}, },
reason => { reason => {
callFunction( callFunction(
binding.MessagePort_postMessage, port, binding.MessagePort_postMessage, port,
{type: kAbort, value: packReason(reason)}); {type: kAbort, value: packReason(reason)});
callFunction(binding.MessagePort_close, port); callFunction(binding.MessagePort_close, port);
return Promise_resolve(); return createResolvedPromise();
}); });
const controller = binding.getWritableStreamController(stream); const controller = binding.getWritableStreamController(stream);
...@@ -488,7 +530,7 @@ ...@@ -488,7 +530,7 @@
} }
function CreateCrossRealmTransformReadable(port) { function CreateCrossRealmTransformReadable(port) {
let backpressurePromise = v8.createPromise(); let backpressurePromise = createPromise();
let finished = false; let finished = false;
callFunction(binding.EventTarget_addEventListener, port, 'message', evt => { callFunction(binding.EventTarget_addEventListener, port, 'message', evt => {
...@@ -502,7 +544,7 @@ ...@@ -502,7 +544,7 @@
case kChunk: case kChunk:
binding.ReadableStreamDefaultControllerEnqueue(controller, value); binding.ReadableStreamDefaultControllerEnqueue(controller, value);
resolvePromise(backpressurePromise); resolvePromise(backpressurePromise);
backpressurePromise = v8.createPromise(); backpressurePromise = createPromise();
break; break;
case kClose: case kClose:
...@@ -547,7 +589,7 @@ ...@@ -547,7 +589,7 @@
binding.MessagePort_postMessage, port, binding.MessagePort_postMessage, port,
{type: kCancel, value: packReason(reason)}); {type: kCancel, value: packReason(reason)});
callFunction(binding.MessagePort_close, port); callFunction(binding.MessagePort_close, port);
return Promise_resolve(); return createResolvedPromise();
}, },
/* highWaterMark = */ 0); /* highWaterMark = */ 0);
...@@ -558,6 +600,9 @@ ...@@ -558,6 +600,9 @@
binding.streamOperations = { binding.streamOperations = {
_queue, _queue,
_queueTotalSize, _queueTotalSize,
createPromise,
createRejectedPromise,
createResolvedPromise,
hasOwnPropertyNoThrow, hasOwnPropertyNoThrow,
rejectPromise, rejectPromise,
resolvePromise, resolvePromise,
......
...@@ -63,13 +63,14 @@ ...@@ -63,13 +63,14 @@
const Promise = global.Promise; const Promise = global.Promise;
const thenPromise = v8.uncurryThis(Promise.prototype.then); const thenPromise = v8.uncurryThis(Promise.prototype.then);
const Promise_resolve = Promise.resolve.bind(Promise);
const Promise_reject = Promise.reject.bind(Promise);
// From CommonOperations.js // From CommonOperations.js
const { const {
_queue, _queue,
_queueTotalSize, _queueTotalSize,
createPromise,
createRejectedPromise,
createResolvedPromise,
hasOwnPropertyNoThrow, hasOwnPropertyNoThrow,
rejectPromise, rejectPromise,
resolvePromise, resolvePromise,
...@@ -175,7 +176,7 @@ ...@@ -175,7 +176,7 @@
const reader = AcquireReadableStreamDefaultReader(readable); const reader = AcquireReadableStreamDefaultReader(readable);
const writer = binding.AcquireWritableStreamDefaultWriter(dest); const writer = binding.AcquireWritableStreamDefaultWriter(dest);
let shuttingDown = false; let shuttingDown = false;
const promise = v8.createPromise(); const promise = createPromise();
let reading = false; let reading = false;
let lastWrite; let lastWrite;
...@@ -366,7 +367,7 @@ ...@@ -366,7 +367,7 @@
// rejects. // rejects.
return thenPromise(lastWrite, () => undefined, () => undefined); return thenPromise(lastWrite, () => undefined, () => undefined);
} }
return Promise_resolve(undefined); return createResolvedPromise(undefined);
} }
return promise; return promise;
...@@ -430,7 +431,7 @@ ...@@ -430,7 +431,7 @@
let canceled2 = false; let canceled2 = false;
let reason1; let reason1;
let reason2; let reason2;
const cancelPromise = v8.createPromise(); const cancelPromise = createPromise();
function pullAlgorithm() { function pullAlgorithm() {
return thenPromise( return thenPromise(
...@@ -515,7 +516,7 @@ ...@@ -515,7 +516,7 @@
// //
function ReadableStreamAddReadRequest(stream, forAuthorCode) { function ReadableStreamAddReadRequest(stream, forAuthorCode) {
const promise = v8.createPromise(); const promise = createPromise();
stream[_reader][_readRequests].push({promise, forAuthorCode}); stream[_reader][_readRequests].push({promise, forAuthorCode});
return promise; return promise;
} }
...@@ -525,10 +526,10 @@ ...@@ -525,10 +526,10 @@
const state = ReadableStreamGetState(stream); const state = ReadableStreamGetState(stream);
if (state === STATE_CLOSED) { if (state === STATE_CLOSED) {
return Promise_resolve(undefined); return createResolvedPromise(undefined);
} }
if (state === STATE_ERRORED) { if (state === STATE_ERRORED) {
return Promise_reject(stream[_storedError]); return createRejectedPromise(stream[_storedError]);
} }
ReadableStreamClose(stream); ReadableStreamClose(stream);
...@@ -631,7 +632,8 @@ ...@@ -631,7 +632,8 @@
get closed() { get closed() {
if (IsReadableStreamDefaultReader(this) === false) { if (IsReadableStreamDefaultReader(this) === false) {
return Promise_reject(new TypeError(streamErrors.illegalInvocation)); return createRejectedPromise(
new TypeError(streamErrors.illegalInvocation));
} }
return this[_closedPromise]; return this[_closedPromise];
...@@ -639,11 +641,12 @@ ...@@ -639,11 +641,12 @@
cancel(reason) { cancel(reason) {
if (IsReadableStreamDefaultReader(this) === false) { if (IsReadableStreamDefaultReader(this) === false) {
return Promise_reject(new TypeError(streamErrors.illegalInvocation)); return createRejectedPromise(
new TypeError(streamErrors.illegalInvocation));
} }
if (this[_ownerReadableStream] === undefined) { if (this[_ownerReadableStream] === undefined) {
return Promise_reject(new TypeError(errCancelReleasedReader)); return createRejectedPromise(new TypeError(errCancelReleasedReader));
} }
return ReadableStreamReaderGenericCancel(this, reason); return ReadableStreamReaderGenericCancel(this, reason);
...@@ -651,11 +654,12 @@ ...@@ -651,11 +654,12 @@
read() { read() {
if (IsReadableStreamDefaultReader(this) === false) { if (IsReadableStreamDefaultReader(this) === false) {
return Promise_reject(new TypeError(streamErrors.illegalInvocation)); return createRejectedPromise(
new TypeError(streamErrors.illegalInvocation));
} }
if (this[_ownerReadableStream] === undefined) { if (this[_ownerReadableStream] === undefined) {
return Promise_reject(new TypeError(errReadReleasedReader)); return createRejectedPromise(new TypeError(errReadReleasedReader));
} }
return ReadableStreamDefaultReaderRead(this, true); return ReadableStreamDefaultReaderRead(this, true);
...@@ -707,13 +711,13 @@ ...@@ -707,13 +711,13 @@
switch (ReadableStreamGetState(stream)) { switch (ReadableStreamGetState(stream)) {
case STATE_READABLE: case STATE_READABLE:
reader[_closedPromise] = v8.createPromise(); reader[_closedPromise] = createPromise();
break; break;
case STATE_CLOSED: case STATE_CLOSED:
reader[_closedPromise] = Promise_resolve(undefined); reader[_closedPromise] = createResolvedPromise(undefined);
break; break;
case STATE_ERRORED: case STATE_ERRORED:
reader[_closedPromise] = Promise_reject(stream[_storedError]); reader[_closedPromise] = createRejectedPromise(stream[_storedError]);
markPromiseAsHandled(reader[_closedPromise]); markPromiseAsHandled(reader[_closedPromise]);
break; break;
} }
...@@ -738,7 +742,7 @@ ...@@ -738,7 +742,7 @@
new TypeError(errReleasedReaderClosedPromise)); new TypeError(errReleasedReaderClosedPromise));
} else { } else {
reader[_closedPromise] = reader[_closedPromise] =
Promise_reject(new TypeError(errReleasedReaderClosedPromise)); createRejectedPromise(new TypeError(errReleasedReaderClosedPromise));
} }
markPromiseAsHandled(reader[_closedPromise]); markPromiseAsHandled(reader[_closedPromise]);
...@@ -752,11 +756,11 @@ ...@@ -752,11 +756,11 @@
switch (ReadableStreamGetState(stream)) { switch (ReadableStreamGetState(stream)) {
case STATE_CLOSED: case STATE_CLOSED:
return Promise_resolve(ReadableStreamCreateReadResult(undefined, true, return createResolvedPromise(
forAuthorCode)); ReadableStreamCreateReadResult(undefined, true, forAuthorCode));
case STATE_ERRORED: case STATE_ERRORED:
return Promise_reject(stream[_storedError]); return createRejectedPromise(stream[_storedError]);
default: default:
return ReadableStreamDefaultControllerPull(stream[_controller], return ReadableStreamDefaultControllerPull(stream[_controller],
...@@ -854,8 +858,8 @@ ...@@ -854,8 +858,8 @@
ReadableStreamDefaultControllerCallPullIfNeeded(controller); ReadableStreamDefaultControllerCallPullIfNeeded(controller);
} }
return Promise_resolve(ReadableStreamCreateReadResult(chunk, false, return createResolvedPromise(
forAuthorCode)); ReadableStreamCreateReadResult(chunk, false, forAuthorCode));
} }
const pendingPromise = ReadableStreamAddReadRequest(stream, forAuthorCode); const pendingPromise = ReadableStreamAddReadRequest(stream, forAuthorCode);
...@@ -1008,7 +1012,7 @@ ...@@ -1008,7 +1012,7 @@
controller[_cancelAlgorithm] = cancelAlgorithm; controller[_cancelAlgorithm] = cancelAlgorithm;
stream[_controller] = controller; stream[_controller] = controller;
thenPromise(Promise_resolve(startAlgorithm()), () => { thenPromise(createResolvedPromise(startAlgorithm()), () => {
controller[_readableStreamDefaultControllerBits] |= STARTED; controller[_readableStreamDefaultControllerBits] |= STARTED;
ReadableStreamDefaultControllerCallPullIfNeeded(controller); ReadableStreamDefaultControllerCallPullIfNeeded(controller);
}, r => ReadableStreamDefaultControllerError(controller, r)); }, r => ReadableStreamDefaultControllerError(controller, r));
......
...@@ -42,11 +42,12 @@ ...@@ -42,11 +42,12 @@
const Promise = global.Promise; const Promise = global.Promise;
const thenPromise = v8.uncurryThis(Promise.prototype.then); const thenPromise = v8.uncurryThis(Promise.prototype.then);
const Promise_resolve = Promise.resolve.bind(Promise);
const Promise_reject = Promise.reject.bind(Promise);
// From CommonOperations.js // From CommonOperations.js
const { const {
createPromise,
createRejectedPromise,
createResolvedPromise,
hasOwnPropertyNoThrow, hasOwnPropertyNoThrow,
resolvePromise, resolvePromise,
CreateAlgorithmFromUnderlyingMethod, CreateAlgorithmFromUnderlyingMethod,
...@@ -103,7 +104,7 @@ ...@@ -103,7 +104,7 @@
readableHighWaterMark = readableHighWaterMark =
ValidateAndNormalizeHighWaterMark(readableHighWaterMark); ValidateAndNormalizeHighWaterMark(readableHighWaterMark);
const startPromise = v8.createPromise(); const startPromise = createPromise();
InitializeTransformStream( InitializeTransformStream(
this, startPromise, writableHighWaterMark, writableSizeAlgorithm, this, startPromise, writableHighWaterMark, writableSizeAlgorithm,
readableHighWaterMark, readableSizeAlgorithm); readableHighWaterMark, readableSizeAlgorithm);
...@@ -159,7 +160,7 @@ ...@@ -159,7 +160,7 @@
// readableHighWaterMark >= 0, // readableHighWaterMark >= 0,
// '! IsNonNegativeNumber(_readableHighWaterMark_) is true'); // '! IsNonNegativeNumber(_readableHighWaterMark_) is true');
const stream = ObjectCreate(TransformStream_prototype); const stream = ObjectCreate(TransformStream_prototype);
const startPromise = v8.createPromise(); const startPromise = createPromise();
InitializeTransformStream( InitializeTransformStream(
stream, startPromise, writableHighWaterMark, writableSizeAlgorithm, stream, startPromise, writableHighWaterMark, writableSizeAlgorithm,
readableHighWaterMark, readableSizeAlgorithm); readableHighWaterMark, readableSizeAlgorithm);
...@@ -188,7 +189,7 @@ ...@@ -188,7 +189,7 @@
TransformStreamDefaultSourcePullAlgorithm(stream); TransformStreamDefaultSourcePullAlgorithm(stream);
const cancelAlgorithm = reason => { const cancelAlgorithm = reason => {
TransformStreamErrorWritableAndUnblockWrite(stream, reason); TransformStreamErrorWritableAndUnblockWrite(stream, reason);
return Promise_resolve(undefined); return createResolvedPromise(undefined);
}; };
stream[_readable] = binding.CreateReadableStream( stream[_readable] = binding.CreateReadableStream(
startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark, startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark,
...@@ -234,7 +235,7 @@ ...@@ -234,7 +235,7 @@
resolvePromise(stream[_backpressureChangePromise], undefined); resolvePromise(stream[_backpressureChangePromise], undefined);
} }
stream[_backpressureChangePromise] = v8.createPromise(); stream[_backpressureChangePromise] = createPromise();
stream[_backpressure] = backpressure; stream[_backpressure] = backpressure;
} }
...@@ -316,9 +317,9 @@ ...@@ -316,9 +317,9 @@
transformAlgorithm = chunk => { transformAlgorithm = chunk => {
try { try {
TransformStreamDefaultControllerEnqueue(controller, chunk); TransformStreamDefaultControllerEnqueue(controller, chunk);
return Promise_resolve(); return createResolvedPromise();
} catch (resultValue) { } catch (resultValue) {
return Promise_reject(resultValue); return createRejectedPromise(resultValue);
} }
}; };
} }
...@@ -415,7 +416,7 @@ ...@@ -415,7 +416,7 @@
function TransformStreamDefaultSinkAbortAlgorithm(stream, reason) { function TransformStreamDefaultSinkAbortAlgorithm(stream, reason) {
TransformStreamError(stream, reason); TransformStreamError(stream, reason);
return Promise_resolve(); return createResolvedPromise();
} }
function TransformStreamDefaultSinkCloseAlgorithm(stream) { function TransformStreamDefaultSinkCloseAlgorithm(stream) {
...@@ -458,7 +459,7 @@ ...@@ -458,7 +459,7 @@
// blink::TransformStream needs. |transformAlgorithm| and |flushAlgorithm| are // blink::TransformStream needs. |transformAlgorithm| and |flushAlgorithm| are
// passed the controller, unlike in the standard. // passed the controller, unlike in the standard.
function createTransformStreamSimple(transformAlgorithm, flushAlgorithm) { function createTransformStreamSimple(transformAlgorithm, flushAlgorithm) {
return CreateTransformStream(() => Promise_resolve(), return CreateTransformStream(() => createResolvedPromise(),
transformAlgorithm, flushAlgorithm); transformAlgorithm, flushAlgorithm);
} }
function createTransformStream( function createTransformStream(
......
...@@ -73,13 +73,14 @@ ...@@ -73,13 +73,14 @@
const Promise = global.Promise; const Promise = global.Promise;
const thenPromise = v8.uncurryThis(Promise.prototype.then); const thenPromise = v8.uncurryThis(Promise.prototype.then);
const Promise_resolve = Promise.resolve.bind(Promise);
const Promise_reject = Promise.reject.bind(Promise);
// From CommonOperations.js // From CommonOperations.js
const { const {
_queue, _queue,
_queueTotalSize, _queueTotalSize,
createPromise,
createRejectedPromise,
createResolvedPromise,
hasOwnPropertyNoThrow, hasOwnPropertyNoThrow,
rejectPromise, rejectPromise,
resolvePromise, resolvePromise,
...@@ -211,7 +212,7 @@ ...@@ -211,7 +212,7 @@
function WritableStreamAbort(stream, reason) { function WritableStreamAbort(stream, reason) {
const state = stream[_stateAndFlags] & STATE_MASK; const state = stream[_stateAndFlags] & STATE_MASK;
if (state === CLOSED || state === ERRORED) { if (state === CLOSED || state === ERRORED) {
return Promise_resolve(undefined); return createResolvedPromise(undefined);
} }
if (stream[_pendingAbortRequest] !== undefined) { if (stream[_pendingAbortRequest] !== undefined) {
return stream[_pendingAbortRequest].promise; return stream[_pendingAbortRequest].promise;
...@@ -225,7 +226,7 @@ ...@@ -225,7 +226,7 @@
reason = undefined; reason = undefined;
} }
const promise = v8.createPromise(); const promise = createPromise();
stream[_pendingAbortRequest] = {promise, reason, wasAlreadyErroring}; stream[_pendingAbortRequest] = {promise, reason, wasAlreadyErroring};
if (!wasAlreadyErroring) { if (!wasAlreadyErroring) {
...@@ -241,7 +242,7 @@ ...@@ -241,7 +242,7 @@
// '! IsWritableStreamLocked(writer) is true.'); // '! IsWritableStreamLocked(writer) is true.');
// assert((stream[_stateAndFlags] & STATE_MASK) === WRITABLE, // assert((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
// 'stream.[[state]] is "writable".'); // 'stream.[[state]] is "writable".');
const promise = v8.createPromise(); const promise = createPromise();
stream[_writeRequests].push(promise); stream[_writeRequests].push(promise);
return promise; return promise;
} }
...@@ -448,7 +449,7 @@ ...@@ -448,7 +449,7 @@
if (writer !== undefined && if (writer !== undefined &&
backpressure !== Boolean(stream[_stateAndFlags] & BACKPRESSURE_FLAG)) { backpressure !== Boolean(stream[_stateAndFlags] & BACKPRESSURE_FLAG)) {
if (backpressure) { if (backpressure) {
writer[_readyPromise] = v8.createPromise(); writer[_readyPromise] = createPromise();
} else { } else {
// assert(!backpressure, '_backpressure_ is *false*.'); // assert(!backpressure, '_backpressure_ is *false*.');
resolvePromise(writer[_readyPromise], undefined); resolvePromise(writer[_readyPromise], undefined);
...@@ -552,33 +553,33 @@ ...@@ -552,33 +553,33 @@
case WRITABLE: { case WRITABLE: {
if (!WritableStreamCloseQueuedOrInFlight(stream) && if (!WritableStreamCloseQueuedOrInFlight(stream) &&
stream[_stateAndFlags] & BACKPRESSURE_FLAG) { stream[_stateAndFlags] & BACKPRESSURE_FLAG) {
this[_readyPromise] = v8.createPromise(); this[_readyPromise] = createPromise();
} else { } else {
this[_readyPromise] = Promise_resolve(undefined); this[_readyPromise] = createResolvedPromise(undefined);
} }
this[_closedPromise] = v8.createPromise(); this[_closedPromise] = createPromise();
break; break;
} }
case ERRORING: { case ERRORING: {
this[_readyPromise] = Promise_reject(stream[_storedError]); this[_readyPromise] = createRejectedPromise(stream[_storedError]);
markPromiseAsHandled(this[_readyPromise]); markPromiseAsHandled(this[_readyPromise]);
this[_closedPromise] = v8.createPromise(); this[_closedPromise] = createPromise();
break; break;
} }
case CLOSED: { case CLOSED: {
this[_readyPromise] = Promise_resolve(undefined); this[_readyPromise] = createResolvedPromise(undefined);
this[_closedPromise] = Promise_resolve(undefined); this[_closedPromise] = createResolvedPromise(undefined);
break; break;
} }
default: { default: {
// assert(state === ERRORED, '_state_ is `"errored"`.'); // assert(state === ERRORED, '_state_ is `"errored"`.');
const storedError = stream[_storedError]; const storedError = stream[_storedError];
this[_readyPromise] = Promise_reject(storedError); this[_readyPromise] = createRejectedPromise(storedError);
markPromiseAsHandled(this[_readyPromise]); markPromiseAsHandled(this[_readyPromise]);
this[_closedPromise] = Promise_reject(storedError); this[_closedPromise] = createRejectedPromise(storedError);
markPromiseAsHandled(this[_closedPromise]); markPromiseAsHandled(this[_closedPromise]);
break; break;
} }
...@@ -587,7 +588,8 @@ ...@@ -587,7 +588,8 @@
get closed() { get closed() {
if (!IsWritableStreamDefaultWriter(this)) { if (!IsWritableStreamDefaultWriter(this)) {
return Promise_reject(new TypeError(streamErrors.illegalInvocation)); return createRejectedPromise(
new TypeError(streamErrors.illegalInvocation));
} }
return this[_closedPromise]; return this[_closedPromise];
} }
...@@ -604,31 +606,36 @@ ...@@ -604,31 +606,36 @@
get ready() { get ready() {
if (!IsWritableStreamDefaultWriter(this)) { if (!IsWritableStreamDefaultWriter(this)) {
return Promise_reject(new TypeError(streamErrors.illegalInvocation)); return createRejectedPromise(
new TypeError(streamErrors.illegalInvocation));
} }
return this[_readyPromise]; return this[_readyPromise];
} }
abort(reason) { abort(reason) {
if (!IsWritableStreamDefaultWriter(this)) { if (!IsWritableStreamDefaultWriter(this)) {
return Promise_reject(new TypeError(streamErrors.illegalInvocation)); return createRejectedPromise(
new TypeError(streamErrors.illegalInvocation));
} }
if (this[_ownerWritableStream] === undefined) { if (this[_ownerWritableStream] === undefined) {
return Promise_reject(createWriterLockReleasedError(verbAborted)); return createRejectedPromise(
createWriterLockReleasedError(verbAborted));
} }
return WritableStreamDefaultWriterAbort(this, reason); return WritableStreamDefaultWriterAbort(this, reason);
} }
close() { close() {
if (!IsWritableStreamDefaultWriter(this)) { if (!IsWritableStreamDefaultWriter(this)) {
return Promise_reject(new TypeError(streamErrors.illegalInvocation)); return createRejectedPromise(
new TypeError(streamErrors.illegalInvocation));
} }
const stream = this[_ownerWritableStream]; const stream = this[_ownerWritableStream];
if (stream === undefined) { if (stream === undefined) {
return Promise_reject(createWriterLockReleasedError(verbClosed)); return createRejectedPromise(createWriterLockReleasedError(verbClosed));
} }
if (WritableStreamCloseQueuedOrInFlight(stream)) { if (WritableStreamCloseQueuedOrInFlight(stream)) {
return Promise_reject(new TypeError(errCloseCloseRequestedStream)); return createRejectedPromise(
new TypeError(errCloseCloseRequestedStream));
} }
return WritableStreamDefaultWriterClose(this); return WritableStreamDefaultWriterClose(this);
} }
...@@ -648,10 +655,12 @@ ...@@ -648,10 +655,12 @@
write(chunk) { write(chunk) {
if (!IsWritableStreamDefaultWriter(this)) { if (!IsWritableStreamDefaultWriter(this)) {
return Promise_reject(new TypeError(streamErrors.illegalInvocation)); return createRejectedPromise(
new TypeError(streamErrors.illegalInvocation));
} }
if (this[_ownerWritableStream] === undefined) { if (this[_ownerWritableStream] === undefined) {
return Promise_reject(createWriterLockReleasedError(verbWrittenTo)); return createRejectedPromise(
createWriterLockReleasedError(verbWrittenTo));
} }
return WritableStreamDefaultWriterWrite(this, chunk); return WritableStreamDefaultWriterWrite(this, chunk);
} }
...@@ -675,7 +684,7 @@ ...@@ -675,7 +684,7 @@
// assert(stream !== undefined, 'stream is not undefined.'); // assert(stream !== undefined, 'stream is not undefined.');
const state = stream[_stateAndFlags] & STATE_MASK; const state = stream[_stateAndFlags] & STATE_MASK;
if (state === CLOSED || state === ERRORED) { if (state === CLOSED || state === ERRORED) {
return Promise_reject( return createRejectedPromise(
createCannotActionOnStateStreamError('close', state)); createCannotActionOnStateStreamError('close', state));
} }
...@@ -683,7 +692,7 @@ ...@@ -683,7 +692,7 @@
// '_state_ is `"writable"` or `"erroring"`.'); // '_state_ is `"writable"` or `"erroring"`.');
// assert(!WritableStreamCloseQueuedOrInFlight(stream), // assert(!WritableStreamCloseQueuedOrInFlight(stream),
// '! WritableStreamCloseQueuedOrInFlight(_stream_) is *false*.'); // '! WritableStreamCloseQueuedOrInFlight(_stream_) is *false*.');
const promise = v8.createPromise(); const promise = createPromise();
stream[_closeRequest] = promise; stream[_closeRequest] = promise;
if ((stream[_stateAndFlags] & BACKPRESSURE_FLAG) && state === WRITABLE) { if ((stream[_stateAndFlags] & BACKPRESSURE_FLAG) && state === WRITABLE) {
...@@ -698,10 +707,10 @@ ...@@ -698,10 +707,10 @@
// assert(stream !== undefined, 'stream is not undefined.'); // assert(stream !== undefined, 'stream is not undefined.');
const state = stream[_stateAndFlags] & STATE_MASK; const state = stream[_stateAndFlags] & STATE_MASK;
if (WritableStreamCloseQueuedOrInFlight(stream) || state === CLOSED) { if (WritableStreamCloseQueuedOrInFlight(stream) || state === CLOSED) {
return Promise_resolve(undefined); return createResolvedPromise(undefined);
} }
if (state === ERRORED) { if (state === ERRORED) {
return Promise_reject(stream[_storedError]); return createRejectedPromise(stream[_storedError]);
} }
// assert(state === WRITABLE || state === ERRORING, // assert(state === WRITABLE || state === ERRORING,
...@@ -715,7 +724,7 @@ ...@@ -715,7 +724,7 @@
if (promiseState(writer[_closedPromise]) === v8.kPROMISE_PENDING) { if (promiseState(writer[_closedPromise]) === v8.kPROMISE_PENDING) {
rejectPromise(writer[_closedPromise], error); rejectPromise(writer[_closedPromise], error);
} else { } else {
writer[_closedPromise] = Promise_reject(error); writer[_closedPromise] = createRejectedPromise(error);
} }
markPromiseAsHandled(writer[_closedPromise]); markPromiseAsHandled(writer[_closedPromise]);
} }
...@@ -726,7 +735,7 @@ ...@@ -726,7 +735,7 @@
if (promiseState(writer[_readyPromise]) === v8.kPROMISE_PENDING) { if (promiseState(writer[_readyPromise]) === v8.kPROMISE_PENDING) {
rejectPromise(writer[_readyPromise], error); rejectPromise(writer[_readyPromise], error);
} else { } else {
writer[_readyPromise] = Promise_reject(error); writer[_readyPromise] = createRejectedPromise(error);
} }
markPromiseAsHandled(writer[_readyPromise]); markPromiseAsHandled(writer[_readyPromise]);
} }
...@@ -766,22 +775,23 @@ ...@@ -766,22 +775,23 @@
const chunkSize = const chunkSize =
WritableStreamDefaultControllerGetChunkSize(controller, chunk); WritableStreamDefaultControllerGetChunkSize(controller, chunk);
if (stream !== writer[_ownerWritableStream]) { if (stream !== writer[_ownerWritableStream]) {
return Promise_reject(createWriterLockReleasedError(verbWrittenTo)); return createRejectedPromise(
createWriterLockReleasedError(verbWrittenTo));
} }
const state = stream[_stateAndFlags] & STATE_MASK; const state = stream[_stateAndFlags] & STATE_MASK;
if (state === ERRORED) { if (state === ERRORED) {
return Promise_reject(stream[_storedError]); return createRejectedPromise(stream[_storedError]);
} }
if (WritableStreamCloseQueuedOrInFlight(stream)) { if (WritableStreamCloseQueuedOrInFlight(stream)) {
return Promise_reject(new TypeError( return createRejectedPromise(new TypeError(
templateErrorCannotActionOnStateStream('write to', 'closing'))); templateErrorCannotActionOnStateStream('write to', 'closing')));
} }
if (state === CLOSED) { if (state === CLOSED) {
return Promise_reject( return createRejectedPromise(
createCannotActionOnStateStreamError('write to', CLOSED)); createCannotActionOnStateStreamError('write to', CLOSED));
} }
if (state === ERRORING) { if (state === ERRORING) {
return Promise_reject(stream[_storedError]); return createRejectedPromise(stream[_storedError]);
} }
// assert(state === WRITABLE, '_state_ is `"writable"`'); // assert(state === WRITABLE, '_state_ is `"writable"`');
const promise = WritableStreamAddWriteRequest(stream); const promise = WritableStreamAddWriteRequest(stream);
...@@ -871,7 +881,7 @@ ...@@ -871,7 +881,7 @@
WritableStreamDefaultControllerGetBackpressure(controller); WritableStreamDefaultControllerGetBackpressure(controller);
WritableStreamUpdateBackpressure(stream, backpressure); WritableStreamUpdateBackpressure(stream, backpressure);
const startResult = startAlgorithm(); const startResult = startAlgorithm();
const startPromise = Promise_resolve(startResult); const startPromise = createResolvedPromise(startResult);
thenPromise( thenPromise(
startPromise, startPromise,
() => { () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment