Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(241)

Unified Diff: third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp

Issue 2420203002: Implement convertToBlob() in OffscreenCanvas (Closed)
Patch Set: rebase and fix global-interface-listing-service-worker-expected.txt Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp
index 58af50fe0faec277b63645d9c0f4022c0d274dc5..3408d1658e639b13e52d79ef6a94578ff1919a6c 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp
@@ -86,7 +86,11 @@ CanvasAsyncBlobCreator::MimeType convertMimeTypeStringToEnum(
}
void recordIdleTaskStatusHistogram(
+ CanvasAsyncBlobCreator::ToBlobFunctionType functionType,
CanvasAsyncBlobCreator::IdleTaskStatus status) {
+ // TODO(crbug.com/653599): Add histograms for OffscreenCanvas.convertToBlob.
+ if (functionType == CanvasAsyncBlobCreator::OffscreenCanvasToBlobPromise)
+ return;
DEFINE_STATIC_LOCAL(EnumerationHistogram, toBlobIdleTaskStatus,
("Blink.Canvas.ToBlob.IdleTaskStatus",
CanvasAsyncBlobCreator::IdleTaskCount));
@@ -102,9 +106,15 @@ enum ElapsedTimeHistogramType {
NumberOfElapsedTimeHistogramTypes
};
-void recordElapsedTimeHistogram(ElapsedTimeHistogramType type,
- CanvasAsyncBlobCreator::MimeType mimeType,
- double elapsedTime) {
+void recordElapsedTimeHistogram(
+ CanvasAsyncBlobCreator::ToBlobFunctionType functionType,
+ ElapsedTimeHistogramType type,
+ CanvasAsyncBlobCreator::MimeType mimeType,
+ double elapsedTime) {
+ // TODO(crbug.com/653599): Add histograms for OffscreenCanvas.convertToBlob.
+ if (functionType == CanvasAsyncBlobCreator::OffscreenCanvasToBlobPromise)
+ return;
+
if (type == InitiateEncodingDelay) {
if (mimeType == CanvasAsyncBlobCreator::MimeTypePng) {
DEFINE_STATIC_LOCAL(
@@ -156,10 +166,22 @@ CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::create(
const IntSize& size,
BlobCallback* callback,
double startTime,
- Document& document) {
+ Document* document) {
return new CanvasAsyncBlobCreator(unpremultipliedRGBAImageData,
convertMimeTypeStringToEnum(mimeType), size,
- callback, startTime, document);
+ callback, startTime, document, nullptr);
+}
+
+CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::create(
+ DOMUint8ClampedArray* unpremultipliedRGBAImageData,
+ const String& mimeType,
+ const IntSize& size,
+ double startTime,
+ Document* document,
+ ScriptPromiseResolver* resolver) {
+ return new CanvasAsyncBlobCreator(unpremultipliedRGBAImageData,
+ convertMimeTypeStringToEnum(mimeType), size,
+ nullptr, startTime, document, resolver);
}
CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(DOMUint8ClampedArray* data,
@@ -167,21 +189,29 @@ CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(DOMUint8ClampedArray* data,
const IntSize& size,
BlobCallback* callback,
double startTime,
- Document& document)
+ Document* document,
+ ScriptPromiseResolver* resolver)
: m_data(data),
- m_document(&document),
+ m_document(document),
m_size(size),
m_mimeType(mimeType),
- m_callback(callback),
m_startTime(startTime),
m_elapsedTime(0),
- m_parentFrameTaskRunner(
- ParentFrameTaskRunners::create(document.frame())) {
- ASSERT(m_data->length() == (unsigned)(size.height() * size.width() * 4));
+ m_callback(callback),
+ m_scriptPromiseResolver(resolver) {
+ DCHECK(m_data->length() == (unsigned)(size.height() * size.width() * 4));
m_encodedImage = wrapUnique(new Vector<unsigned char>());
m_pixelRowStride = size.width() * NumChannelsPng;
m_idleTaskStatus = IdleTaskNotSupported;
m_numRowsCompleted = 0;
+ if (document) {
+ m_parentFrameTaskRunner = ParentFrameTaskRunners::create(document->frame());
+ }
+ if (m_scriptPromiseResolver) {
+ m_functionType = OffscreenCanvasToBlobPromise;
+ } else {
+ m_functionType = HTMLCanvasToBlobCallback;
+ }
}
CanvasAsyncBlobCreator::~CanvasAsyncBlobCreator() {}
@@ -191,15 +221,46 @@ void CanvasAsyncBlobCreator::dispose() {
// resources while any remaining posted tasks are queued.
m_data.clear();
m_document.clear();
+ m_parentFrameTaskRunner.clear();
m_callback.clear();
+ m_scriptPromiseResolver.clear();
}
-void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation(
- bool canUseIdlePeriodScheduling,
- const double& quality) {
- ASSERT(isMainThread());
+void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation(const double& quality) {
+ if (m_mimeType == MimeTypeWebp) {
+ if (!isMainThread()) {
+ DCHECK(m_functionType == OffscreenCanvasToBlobPromise);
+ // When OffscreenCanvas.convertToBlob() occurs on worker thread,
+ // we do not need to use background task runner to reduce load on main.
+ // So we just directly encode images on the worker thread.
+ if (!ImageDataBuffer(m_size, m_data->data())
+ .encodeImage("image/webp", quality, m_encodedImage.get())) {
+ TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
+ ->postTask(
+ BLINK_FROM_HERE,
+ WTF::bind(&CanvasAsyncBlobCreator::createNullAndReturnResult,
+ wrapPersistent(this)));
- if (canUseIdlePeriodScheduling) {
+ return;
+ }
+ TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
+ ->postTask(
+ BLINK_FROM_HERE,
+ WTF::bind(&CanvasAsyncBlobCreator::createBlobAndReturnResult,
+ wrapPersistent(this)));
+
+ } else {
+ BackgroundTaskRunner::TaskSize taskSize =
+ (m_size.height() * m_size.width() >= LongTaskImageSizeThreshold)
+ ? BackgroundTaskRunner::TaskSizeLongRunningTask
+ : BackgroundTaskRunner::TaskSizeShortRunningTask;
+ BackgroundTaskRunner::postOnBackgroundThread(
+ BLINK_FROM_HERE,
+ crossThreadBind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread,
+ wrapCrossThreadPersistent(this), quality),
+ taskSize);
+ }
+ } else {
m_idleTaskStatus = IdleTaskNotStarted;
if (m_mimeType == MimeTypePng) {
this->scheduleInitiatePngEncoding();
@@ -211,47 +272,41 @@ void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation(
// formats.
// TODO(xlai): Progressive encoding on webp image formats
// (crbug.com/571399)
- ASSERT_NOT_REACHED();
+ NOTREACHED();
+ }
+
+ // TODO: Enforce OffscreenCanvas.convertToBlob to finish within deadline.
+ // See crbug.com/657102.
+ if (m_functionType == HTMLCanvasToBlobCallback) {
+ // We post the below task to check if the above idle task isn't late.
+ // There's no risk of concurrency as both tasks are on main thread.
+ this->postDelayedTaskToMainThread(
+ BLINK_FROM_HERE,
+ WTF::bind(&CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent,
+ wrapPersistent(this), quality),
+ IdleTaskStartTimeoutDelay);
}
- // We post the below task to check if the above idle task isn't late.
- // There's no risk of concurrency as both tasks are on main thread.
- this->postDelayedTaskToMainThread(
- BLINK_FROM_HERE,
- WTF::bind(&CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent,
- wrapPersistent(this), quality),
- IdleTaskStartTimeoutDelay);
- } else if (m_mimeType == MimeTypeWebp) {
- BackgroundTaskRunner::TaskSize taskSize =
- (m_size.height() * m_size.width() >= LongTaskImageSizeThreshold)
- ? BackgroundTaskRunner::TaskSizeLongRunningTask
- : BackgroundTaskRunner::TaskSizeShortRunningTask;
- BackgroundTaskRunner::postOnBackgroundThread(
- BLINK_FROM_HERE,
- crossThreadBind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread,
- wrapCrossThreadPersistent(this), quality),
- taskSize);
}
}
void CanvasAsyncBlobCreator::scheduleInitiateJpegEncoding(
const double& quality) {
m_scheduleInitiateStartTime = WTF::monotonicallyIncreasingTime();
- Platform::current()->mainThread()->scheduler()->postIdleTask(
+ Platform::current()->currentThread()->scheduler()->postIdleTask(
BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::initiateJpegEncoding,
wrapPersistent(this), quality));
}
void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality,
double deadlineSeconds) {
- ASSERT(isMainThread());
recordElapsedTimeHistogram(
- InitiateEncodingDelay, MimeTypeJpeg,
+ m_functionType, InitiateEncodingDelay, MimeTypeJpeg,
WTF::monotonicallyIncreasingTime() - m_scheduleInitiateStartTime);
- if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) {
+ if (m_idleTaskStatus == IdleTaskSwitchedToImmediateTask) {
return;
}
- ASSERT(m_idleTaskStatus == IdleTaskNotStarted);
+ DCHECK(m_idleTaskStatus == IdleTaskNotStarted);
m_idleTaskStatus = IdleTaskStarted;
if (!initializeJpegStruct(quality)) {
@@ -263,22 +318,20 @@ void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality,
void CanvasAsyncBlobCreator::scheduleInitiatePngEncoding() {
m_scheduleInitiateStartTime = WTF::monotonicallyIncreasingTime();
- Platform::current()->mainThread()->scheduler()->postIdleTask(
+ Platform::current()->currentThread()->scheduler()->postIdleTask(
BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::initiatePngEncoding,
wrapPersistent(this)));
}
void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) {
- ASSERT(isMainThread());
recordElapsedTimeHistogram(
- InitiateEncodingDelay, MimeTypePng,
+ m_functionType, InitiateEncodingDelay, MimeTypePng,
WTF::monotonicallyIncreasingTime() - m_scheduleInitiateStartTime);
-
- if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) {
+ if (m_idleTaskStatus == IdleTaskSwitchedToImmediateTask) {
return;
}
- ASSERT(m_idleTaskStatus == IdleTaskNotStarted);
+ DCHECK(m_idleTaskStatus == IdleTaskNotStarted);
m_idleTaskStatus = IdleTaskStarted;
if (!initializePngStruct()) {
@@ -289,8 +342,7 @@ void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) {
}
void CanvasAsyncBlobCreator::idleEncodeRowsPng(double deadlineSeconds) {
- ASSERT(isMainThread());
- if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) {
+ if (m_idleTaskStatus == IdleTaskSwitchedToImmediateTask) {
return;
}
@@ -314,21 +366,20 @@ void CanvasAsyncBlobCreator::idleEncodeRowsPng(double deadlineSeconds) {
m_idleTaskStatus = IdleTaskCompleted;
m_elapsedTime += (WTF::monotonicallyIncreasingTime() - startTime);
- recordElapsedTimeHistogram(IdleEncodeDuration, MimeTypePng, m_elapsedTime);
+ recordElapsedTimeHistogram(m_functionType, IdleEncodeDuration, MimeTypePng,
+ m_elapsedTime);
if (isDeadlineNearOrPassed(deadlineSeconds)) {
TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
- ->postTask(
- BLINK_FROM_HERE,
- WTF::bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback,
- wrapPersistent(this)));
+ ->postTask(BLINK_FROM_HERE,
+ WTF::bind(&CanvasAsyncBlobCreator::createBlobAndReturnResult,
+ wrapPersistent(this)));
} else {
- this->createBlobAndInvokeCallback();
+ this->createBlobAndReturnResult();
}
}
void CanvasAsyncBlobCreator::idleEncodeRowsJpeg(double deadlineSeconds) {
- ASSERT(isMainThread());
- if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) {
+ if (m_idleTaskStatus == IdleTaskSwitchedToImmediateTask) {
return;
}
@@ -339,20 +390,21 @@ void CanvasAsyncBlobCreator::idleEncodeRowsJpeg(double deadlineSeconds) {
m_elapsedTime += (WTF::monotonicallyIncreasingTime() - startTime);
if (m_numRowsCompleted == m_size.height()) {
m_idleTaskStatus = IdleTaskCompleted;
- recordElapsedTimeHistogram(IdleEncodeDuration, MimeTypeJpeg, m_elapsedTime);
+ recordElapsedTimeHistogram(m_functionType, IdleEncodeDuration, MimeTypeJpeg,
+ m_elapsedTime);
if (isDeadlineNearOrPassed(deadlineSeconds)) {
TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
->postTask(
BLINK_FROM_HERE,
- WTF::bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback,
+ WTF::bind(&CanvasAsyncBlobCreator::createBlobAndReturnResult,
wrapPersistent(this)));
} else {
- this->createBlobAndInvokeCallback();
+ this->createBlobAndReturnResult();
}
} else if (m_numRowsCompleted == JPEGImageEncoder::ProgressiveEncodeFailed) {
m_idleTaskStatus = IdleTaskFailed;
- this->createNullAndInvokeCallback();
+ this->createNullAndReturnResult();
} else {
Platform::current()->currentThread()->scheduler()->postIdleTask(
BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::idleEncodeRowsJpeg,
@@ -361,7 +413,7 @@ void CanvasAsyncBlobCreator::idleEncodeRowsJpeg(double deadlineSeconds) {
}
void CanvasAsyncBlobCreator::encodeRowsPngOnMainThread() {
- ASSERT(m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask);
+ DCHECK(m_idleTaskStatus == IdleTaskSwitchedToImmediateTask);
// Continue encoding from the last completed row
unsigned char* inputPixels =
@@ -371,56 +423,65 @@ void CanvasAsyncBlobCreator::encodeRowsPngOnMainThread() {
inputPixels += m_pixelRowStride;
}
PNGImageEncoder::finalizePng(m_pngEncoderState.get());
- this->createBlobAndInvokeCallback();
+ this->createBlobAndReturnResult();
this->signalAlternativeCodePathFinishedForTesting();
}
void CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread() {
- ASSERT(m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask);
+ DCHECK(m_idleTaskStatus == IdleTaskSwitchedToImmediateTask);
// Continue encoding from the last completed row
if (JPEGImageEncoder::encodeWithPreInitializedState(
std::move(m_jpegEncoderState), m_data->data(), m_numRowsCompleted)) {
- this->createBlobAndInvokeCallback();
+ this->createBlobAndReturnResult();
} else {
- this->createNullAndInvokeCallback();
+ this->createNullAndReturnResult();
}
this->signalAlternativeCodePathFinishedForTesting();
}
-void CanvasAsyncBlobCreator::createBlobAndInvokeCallback() {
- ASSERT(isMainThread());
- recordIdleTaskStatusHistogram(m_idleTaskStatus);
-
- recordElapsedTimeHistogram(ToBlobDuration, m_mimeType,
+void CanvasAsyncBlobCreator::createBlobAndReturnResult() {
+ recordIdleTaskStatusHistogram(m_functionType, m_idleTaskStatus);
+ recordElapsedTimeHistogram(m_functionType, ToBlobDuration, m_mimeType,
WTF::monotonicallyIncreasingTime() - m_startTime);
+
Blob* resultBlob =
Blob::create(m_encodedImage->data(), m_encodedImage->size(),
convertMimeTypeEnumToString(m_mimeType));
- TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
- ->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent,
- wrapPersistent(m_callback.get()),
- wrapPersistent(resultBlob)));
+ if (m_functionType == HTMLCanvasToBlobCallback) {
+ TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
+ ->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent,
+ wrapPersistent(m_callback.get()),
+ wrapPersistent(resultBlob)));
+ } else {
+ m_scriptPromiseResolver->resolve(resultBlob);
+ }
// Avoid unwanted retention, see dispose().
dispose();
}
-void CanvasAsyncBlobCreator::createNullAndInvokeCallback() {
- ASSERT(isMainThread());
- recordIdleTaskStatusHistogram(m_idleTaskStatus);
- TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
- ->postTask(BLINK_FROM_HERE,
- WTF::bind(&BlobCallback::handleEvent,
- wrapPersistent(m_callback.get()), nullptr));
+void CanvasAsyncBlobCreator::createNullAndReturnResult() {
+ recordIdleTaskStatusHistogram(m_functionType, m_idleTaskStatus);
+ if (m_functionType == HTMLCanvasToBlobCallback) {
+ DCHECK(isMainThread());
+ recordIdleTaskStatusHistogram(m_functionType, m_idleTaskStatus);
+ TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
+ ->postTask(BLINK_FROM_HERE,
+ WTF::bind(&BlobCallback::handleEvent,
+ wrapPersistent(m_callback.get()), nullptr));
+ } else {
+ Blob* blob = nullptr;
+ m_scriptPromiseResolver->reject(blob);
+ }
// Avoid unwanted retention, see dispose().
dispose();
}
void CanvasAsyncBlobCreator::encodeImageOnEncoderThread(double quality) {
- ASSERT(!isMainThread());
- ASSERT(m_mimeType == MimeTypeWebp);
+ DCHECK(!isMainThread());
+ DCHECK(m_mimeType == MimeTypeWebp);
if (!ImageDataBuffer(m_size, m_data->data())
.encodeImage("image/webp", quality, m_encodedImage.get())) {
@@ -435,7 +496,7 @@ void CanvasAsyncBlobCreator::encodeImageOnEncoderThread(double quality) {
m_parentFrameTaskRunner->get(TaskType::CanvasBlobSerialization)
->postTask(
BLINK_FROM_HERE,
- crossThreadBind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback,
+ crossThreadBind(&CanvasAsyncBlobCreator::createBlobAndReturnResult,
wrapCrossThreadPersistent(this)));
}
@@ -443,7 +504,7 @@ bool CanvasAsyncBlobCreator::initializePngStruct() {
m_pngEncoderState =
PNGImageEncoderState::create(m_size, m_encodedImage.get());
if (!m_pngEncoderState) {
- this->createNullAndInvokeCallback();
+ this->createNullAndReturnResult();
return false;
}
return true;
@@ -453,7 +514,7 @@ bool CanvasAsyncBlobCreator::initializeJpegStruct(double quality) {
m_jpegEncoderState =
JPEGImageEncoderState::create(m_size, quality, m_encodedImage.get());
if (!m_jpegEncoderState) {
- this->createNullAndInvokeCallback();
+ this->createNullAndReturnResult();
return false;
}
return true;
@@ -471,7 +532,7 @@ void CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent(double quality) {
// If the idle task does not start after a delay threshold, we will
// force it to happen on main thread (even though it may cause more
// janks) to prevent toBlob being postponed forever in extreme cases.
- m_idleTaskStatus = IdleTaskSwitchedToMainThreadTask;
+ m_idleTaskStatus = IdleTaskSwitchedToImmediateTask;
signalTaskSwitchInStartTimeoutEventForTesting();
if (m_mimeType == MimeTypePng) {
@@ -486,7 +547,7 @@ void CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent(double quality) {
this->signalAlternativeCodePathFinishedForTesting();
}
} else {
- ASSERT(m_mimeType == MimeTypeJpeg);
+ DCHECK(m_mimeType == MimeTypeJpeg);
if (initializeJpegStruct(quality)) {
TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
->postTask(
@@ -499,18 +560,18 @@ void CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent(double quality) {
}
}
} else {
- ASSERT(m_idleTaskStatus == IdleTaskFailed ||
+ DCHECK(m_idleTaskStatus == IdleTaskFailed ||
m_idleTaskStatus == IdleTaskCompleted);
this->signalAlternativeCodePathFinishedForTesting();
}
}
void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent() {
- ASSERT(m_idleTaskStatus != IdleTaskNotStarted);
+ DCHECK(m_idleTaskStatus != IdleTaskNotStarted);
if (m_idleTaskStatus == IdleTaskStarted) {
// It has taken too long to complete for the idle task.
- m_idleTaskStatus = IdleTaskSwitchedToMainThreadTask;
+ m_idleTaskStatus = IdleTaskSwitchedToImmediateTask;
signalTaskSwitchInCompleteTimeoutEventForTesting();
if (m_mimeType == MimeTypePng) {
@@ -520,7 +581,7 @@ void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent() {
WTF::bind(&CanvasAsyncBlobCreator::encodeRowsPngOnMainThread,
wrapPersistent(this)));
} else {
- ASSERT(m_mimeType == MimeTypeJpeg);
+ DCHECK(m_mimeType == MimeTypeJpeg);
TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
->postTask(
BLINK_FROM_HERE,
@@ -528,7 +589,7 @@ void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent() {
wrapPersistent(this)));
}
} else {
- ASSERT(m_idleTaskStatus == IdleTaskFailed ||
+ DCHECK(m_idleTaskStatus == IdleTaskFailed ||
m_idleTaskStatus == IdleTaskCompleted);
this->signalAlternativeCodePathFinishedForTesting();
}
@@ -548,6 +609,7 @@ DEFINE_TRACE(CanvasAsyncBlobCreator) {
visitor->trace(m_data);
visitor->trace(m_callback);
visitor->trace(m_parentFrameTaskRunner);
+ visitor->trace(m_scriptPromiseResolver);
}
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698