Bug 1546603 - Don't finalize stream sources from JS if creating the stream object failed, r=arai.

Differential Revision: https://phabricator.services.mozilla.com/D28931

--HG--
extra : rebase_source : 558bd2bfdba22088906449c3388f25edc8c62786
extra : histedit_source : 643d9c253e5d00159c571651cf85e61956f1eca5
This commit is contained in:
Brian Hackett 2019-04-25 12:13:30 -10:00
Родитель 4a8df2e83e
Коммит 0e926d34f6
2 изменённых файлов: 30 добавлений и 2 удалений

Просмотреть файл

@ -3467,6 +3467,28 @@ bool ReadableByteStreamController::constructor(JSContext* cx, unsigned argc,
return false;
}
// Disconnect the source from a controller without calling finalize() on it,
// unless this class is reset(). This ensures that finalize() will not be called
// on the source if setting up the controller fails.
class MOZ_RAII AutoClearUnderlyingSource {
Rooted<ReadableStreamController*> controller_;
public:
AutoClearUnderlyingSource(JSContext* cx, ReadableStreamController* controller)
: controller_(cx, controller) {}
~AutoClearUnderlyingSource() {
if (controller_) {
ReadableStreamController::clearUnderlyingSource(
controller_, /* finalizeSource */ false);
}
}
void reset() {
controller_ = nullptr;
}
};
/**
* Version of SetUpReadableByteStreamController that's specialized for handling
* external, embedding-provided, underlying sources.
@ -3481,6 +3503,8 @@ static MOZ_MUST_USE bool SetUpExternalReadableByteStreamController(
return false;
}
AutoClearUnderlyingSource autoClear(cx, controller);
// Step 1: Assert: stream.[[readableStreamController]] is undefined.
MOZ_ASSERT(!stream->hasController());
@ -3556,6 +3580,7 @@ static MOZ_MUST_USE bool SetUpExternalReadableByteStreamController(
return false;
}
autoClear.reset();
return true;
}

Просмотреть файл

@ -317,9 +317,12 @@ class ReadableStreamController : public StreamController {
addFlags(Flag_ExternalSource);
}
static void clearUnderlyingSource(
JS::Handle<ReadableStreamController*> controller) {
JS::Handle<ReadableStreamController*> controller,
bool finalizeSource = true) {
if (controller->hasExternalSource()) {
controller->externalSource()->finalize();
if (finalizeSource) {
controller->externalSource()->finalize();
}
controller->setFlags(controller->flags() & ~Flag_ExternalSource);
}
controller->setUnderlyingSource(JS::UndefinedHandleValue);