Merge pull request #11069 from Snuffleupagus/getoplist-stream
Use streams for OperatorList chunking (issue 10023)
This commit is contained in:
commit
56ae7a6690
@ -195,7 +195,7 @@ class Page {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getOperatorList({ handler, task, intent, renderInteractiveForms, }) {
|
getOperatorList({ handler, sink, task, intent, renderInteractiveForms, }) {
|
||||||
const contentStreamPromise = this.pdfManager.ensure(this,
|
const contentStreamPromise = this.pdfManager.ensure(this,
|
||||||
'getContentStream');
|
'getContentStream');
|
||||||
const resourcesPromise = this.loadResources([
|
const resourcesPromise = this.loadResources([
|
||||||
@ -220,7 +220,7 @@ class Page {
|
|||||||
|
|
||||||
const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
|
const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
|
||||||
const pageListPromise = dataPromises.then(([contentStream]) => {
|
const pageListPromise = dataPromises.then(([contentStream]) => {
|
||||||
const opList = new OperatorList(intent, handler, this.pageIndex);
|
const opList = new OperatorList(intent, sink, this.pageIndex);
|
||||||
|
|
||||||
handler.send('StartRenderPage', {
|
handler.send('StartRenderPage', {
|
||||||
transparency: partialEvaluator.hasBlendModes(this.resources),
|
transparency: partialEvaluator.hasBlendModes(this.resources),
|
||||||
@ -244,7 +244,7 @@ class Page {
|
|||||||
function([pageOpList, annotations]) {
|
function([pageOpList, annotations]) {
|
||||||
if (annotations.length === 0) {
|
if (annotations.length === 0) {
|
||||||
pageOpList.flush(true);
|
pageOpList.flush(true);
|
||||||
return pageOpList;
|
return { length: pageOpList.totalLength, };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect the operator list promises for the annotations. Each promise
|
// Collect the operator list promises for the annotations. Each promise
|
||||||
@ -264,7 +264,7 @@ class Page {
|
|||||||
}
|
}
|
||||||
pageOpList.addOp(OPS.endAnnotations, []);
|
pageOpList.addOp(OPS.endAnnotations, []);
|
||||||
pageOpList.flush(true);
|
pageOpList.flush(true);
|
||||||
return pageOpList;
|
return { length: pageOpList.totalLength, };
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -541,6 +541,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
operatorList.addDependencies(tilingOpList.dependencies);
|
operatorList.addDependencies(tilingOpList.dependencies);
|
||||||
operatorList.addOp(fn, tilingPatternIR);
|
operatorList.addOp(fn, tilingPatternIR);
|
||||||
}, (reason) => {
|
}, (reason) => {
|
||||||
|
if (reason instanceof AbortException) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.options.ignoreErrors) {
|
if (this.options.ignoreErrors) {
|
||||||
// Error(s) in the TilingPattern -- sending unsupported feature
|
// Error(s) in the TilingPattern -- sending unsupported feature
|
||||||
// notification and allow rendering to continue.
|
// notification and allow rendering to continue.
|
||||||
@ -918,8 +921,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new Promise(function promiseBody(resolve, reject) {
|
return new Promise(function promiseBody(resolve, reject) {
|
||||||
var next = function (promise) {
|
let next = function(promise) {
|
||||||
promise.then(function () {
|
Promise.all([promise, operatorList.ready]).then(function () {
|
||||||
try {
|
try {
|
||||||
promiseBody(resolve, reject);
|
promiseBody(resolve, reject);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
@ -1000,6 +1003,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
}
|
}
|
||||||
resolveXObject();
|
resolveXObject();
|
||||||
}).catch(function(reason) {
|
}).catch(function(reason) {
|
||||||
|
if (reason instanceof AbortException) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (self.options.ignoreErrors) {
|
if (self.options.ignoreErrors) {
|
||||||
// Error(s) in the XObject -- sending unsupported feature
|
// Error(s) in the XObject -- sending unsupported feature
|
||||||
// notification and allow rendering to continue.
|
// notification and allow rendering to continue.
|
||||||
@ -1230,6 +1236,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
closePendingRestoreOPS();
|
closePendingRestoreOPS();
|
||||||
resolve();
|
resolve();
|
||||||
}).catch((reason) => {
|
}).catch((reason) => {
|
||||||
|
if (reason instanceof AbortException) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.options.ignoreErrors) {
|
if (this.options.ignoreErrors) {
|
||||||
// Error(s) in the OperatorList -- sending unsupported feature
|
// Error(s) in the OperatorList -- sending unsupported feature
|
||||||
// notification and allow rendering to continue.
|
// notification and allow rendering to continue.
|
||||||
|
@ -541,11 +541,11 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
var CHUNK_SIZE = 1000;
|
var CHUNK_SIZE = 1000;
|
||||||
var CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5; // close to chunk size
|
var CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5; // close to chunk size
|
||||||
|
|
||||||
function OperatorList(intent, messageHandler, pageIndex) {
|
function OperatorList(intent, streamSink, pageIndex) {
|
||||||
this.messageHandler = messageHandler;
|
this._streamSink = streamSink;
|
||||||
this.fnArray = [];
|
this.fnArray = [];
|
||||||
this.argsArray = [];
|
this.argsArray = [];
|
||||||
if (messageHandler && intent !== 'oplist') {
|
if (streamSink && intent !== 'oplist') {
|
||||||
this.optimizer = new QueueOptimizer(this);
|
this.optimizer = new QueueOptimizer(this);
|
||||||
} else {
|
} else {
|
||||||
this.optimizer = new NullOptimizer(this);
|
this.optimizer = new NullOptimizer(this);
|
||||||
@ -555,6 +555,7 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
this.pageIndex = pageIndex;
|
this.pageIndex = pageIndex;
|
||||||
this.intent = intent;
|
this.intent = intent;
|
||||||
this.weight = 0;
|
this.weight = 0;
|
||||||
|
this._resolved = streamSink ? null : Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
OperatorList.prototype = {
|
OperatorList.prototype = {
|
||||||
@ -562,6 +563,10 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
return this.argsArray.length;
|
return this.argsArray.length;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get ready() {
|
||||||
|
return this._resolved || this._streamSink.ready;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {number} The total length of the entire operator list,
|
* @returns {number} The total length of the entire operator list,
|
||||||
* since `this.length === 0` after flushing.
|
* since `this.length === 0` after flushing.
|
||||||
@ -573,7 +578,7 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
addOp(fn, args) {
|
addOp(fn, args) {
|
||||||
this.optimizer.push(fn, args);
|
this.optimizer.push(fn, args);
|
||||||
this.weight++;
|
this.weight++;
|
||||||
if (this.messageHandler) {
|
if (this._streamSink) {
|
||||||
if (this.weight >= CHUNK_SIZE) {
|
if (this.weight >= CHUNK_SIZE) {
|
||||||
this.flush();
|
this.flush();
|
||||||
} else if (this.weight >= CHUNK_SIZE_ABOUT &&
|
} else if (this.weight >= CHUNK_SIZE_ABOUT &&
|
||||||
@ -642,7 +647,7 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
const length = this.length;
|
const length = this.length;
|
||||||
this._totalLength += length;
|
this._totalLength += length;
|
||||||
|
|
||||||
this.messageHandler.send('RenderPageChunk', {
|
this._streamSink.enqueue({
|
||||||
operatorList: {
|
operatorList: {
|
||||||
fnArray: this.fnArray,
|
fnArray: this.fnArray,
|
||||||
argsArray: this.argsArray,
|
argsArray: this.argsArray,
|
||||||
@ -651,7 +656,7 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
},
|
},
|
||||||
pageIndex: this.pageIndex,
|
pageIndex: this.pageIndex,
|
||||||
intent: this.intent,
|
intent: this.intent,
|
||||||
}, this._transfers);
|
}, 1, this._transfers);
|
||||||
|
|
||||||
this.dependencies = Object.create(null);
|
this.dependencies = Object.create(null);
|
||||||
this.fnArray.length = 0;
|
this.fnArray.length = 0;
|
||||||
|
@ -466,10 +466,10 @@ var WorkerMessageHandler = {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
|
handler.on('GetOperatorList', function wphSetupRenderPage(data, sink) {
|
||||||
var pageIndex = data.pageIndex;
|
var pageIndex = data.pageIndex;
|
||||||
pdfManager.getPage(pageIndex).then(function(page) {
|
pdfManager.getPage(pageIndex).then(function(page) {
|
||||||
var task = new WorkerTask('RenderPageRequest: page ' + pageIndex);
|
var task = new WorkerTask(`GetOperatorList: page ${pageIndex}`);
|
||||||
startWorkerTask(task);
|
startWorkerTask(task);
|
||||||
|
|
||||||
// NOTE: Keep this condition in sync with the `info` helper function.
|
// NOTE: Keep this condition in sync with the `info` helper function.
|
||||||
@ -478,55 +478,32 @@ var WorkerMessageHandler = {
|
|||||||
// Pre compile the pdf page and fetch the fonts/images.
|
// Pre compile the pdf page and fetch the fonts/images.
|
||||||
page.getOperatorList({
|
page.getOperatorList({
|
||||||
handler,
|
handler,
|
||||||
|
sink,
|
||||||
task,
|
task,
|
||||||
intent: data.intent,
|
intent: data.intent,
|
||||||
renderInteractiveForms: data.renderInteractiveForms,
|
renderInteractiveForms: data.renderInteractiveForms,
|
||||||
}).then(function(operatorList) {
|
}).then(function(operatorListInfo) {
|
||||||
finishWorkerTask(task);
|
finishWorkerTask(task);
|
||||||
|
|
||||||
if (start) {
|
if (start) {
|
||||||
info(`page=${pageIndex + 1} - getOperatorList: time=` +
|
info(`page=${pageIndex + 1} - getOperatorList: time=` +
|
||||||
`${Date.now() - start}ms, len=${operatorList.totalLength}`);
|
`${Date.now() - start}ms, len=${operatorListInfo.length}`);
|
||||||
}
|
}
|
||||||
}, function(e) {
|
sink.close();
|
||||||
|
}, function(reason) {
|
||||||
finishWorkerTask(task);
|
finishWorkerTask(task);
|
||||||
if (task.terminated) {
|
if (task.terminated) {
|
||||||
return; // ignoring errors from the terminated thread
|
return; // ignoring errors from the terminated thread
|
||||||
}
|
}
|
||||||
|
|
||||||
// For compatibility with older behavior, generating unknown
|
// For compatibility with older behavior, generating unknown
|
||||||
// unsupported feature notification on errors.
|
// unsupported feature notification on errors.
|
||||||
handler.send('UnsupportedFeature',
|
handler.send('UnsupportedFeature',
|
||||||
{ featureId: UNSUPPORTED_FEATURES.unknown, });
|
{ featureId: UNSUPPORTED_FEATURES.unknown, });
|
||||||
|
|
||||||
var minimumStackMessage =
|
sink.error(reason);
|
||||||
'worker.js: while trying to getPage() and getOperatorList()';
|
|
||||||
|
|
||||||
var wrappedException;
|
// TODO: Should `reason` be re-thrown here (currently that casues
|
||||||
|
// "Uncaught exception: ..." messages in the console)?
|
||||||
// Turn the error into an obj that can be serialized
|
|
||||||
if (typeof e === 'string') {
|
|
||||||
wrappedException = {
|
|
||||||
message: e,
|
|
||||||
stack: minimumStackMessage,
|
|
||||||
};
|
|
||||||
} else if (typeof e === 'object') {
|
|
||||||
wrappedException = {
|
|
||||||
message: e.message || e.toString(),
|
|
||||||
stack: e.stack || minimumStackMessage,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
wrappedException = {
|
|
||||||
message: 'Unknown exception type: ' + (typeof e),
|
|
||||||
stack: minimumStackMessage,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
handler.send('PageError', {
|
|
||||||
pageIndex,
|
|
||||||
error: wrappedException,
|
|
||||||
intent: data.intent,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, this);
|
}, this);
|
||||||
@ -563,7 +540,9 @@ var WorkerMessageHandler = {
|
|||||||
return; // ignoring errors from the terminated thread
|
return; // ignoring errors from the terminated thread
|
||||||
}
|
}
|
||||||
sink.error(reason);
|
sink.error(reason);
|
||||||
throw reason;
|
|
||||||
|
// TODO: Should `reason` be re-thrown here (currently that casues
|
||||||
|
// "Uncaught exception: ..." messages in the console)?
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1032,7 +1032,7 @@ class PDFPageProxy {
|
|||||||
};
|
};
|
||||||
|
|
||||||
stats.time('Page Request');
|
stats.time('Page Request');
|
||||||
this._transport.messageHandler.send('RenderPageRequest', {
|
this._pumpOperatorList({
|
||||||
pageIndex: this.pageNumber - 1,
|
pageIndex: this.pageNumber - 1,
|
||||||
intent: renderingIntent,
|
intent: renderingIntent,
|
||||||
renderInteractiveForms: renderInteractiveForms === true,
|
renderInteractiveForms: renderInteractiveForms === true,
|
||||||
@ -1054,6 +1054,11 @@ class PDFPageProxy {
|
|||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
internalRenderTask.capability.reject(error);
|
internalRenderTask.capability.reject(error);
|
||||||
|
|
||||||
|
this._abortOperatorList({
|
||||||
|
intentState,
|
||||||
|
reason: error,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
internalRenderTask.capability.resolve();
|
internalRenderTask.capability.resolve();
|
||||||
}
|
}
|
||||||
@ -1135,7 +1140,7 @@ class PDFPageProxy {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this._stats.time('Page Request');
|
this._stats.time('Page Request');
|
||||||
this._transport.messageHandler.send('RenderPageRequest', {
|
this._pumpOperatorList({
|
||||||
pageIndex: this.pageIndex,
|
pageIndex: this.pageIndex,
|
||||||
intent: renderingIntent,
|
intent: renderingIntent,
|
||||||
});
|
});
|
||||||
@ -1201,19 +1206,25 @@ class PDFPageProxy {
|
|||||||
this._transport.pageCache[this.pageIndex] = null;
|
this._transport.pageCache[this.pageIndex] = null;
|
||||||
|
|
||||||
const waitOn = [];
|
const waitOn = [];
|
||||||
Object.keys(this.intentStates).forEach(function(intent) {
|
Object.keys(this.intentStates).forEach((intent) => {
|
||||||
|
const intentState = this.intentStates[intent];
|
||||||
|
this._abortOperatorList({
|
||||||
|
intentState,
|
||||||
|
reason: new Error('Page was destroyed.'),
|
||||||
|
force: true,
|
||||||
|
});
|
||||||
|
|
||||||
if (intent === 'oplist') {
|
if (intent === 'oplist') {
|
||||||
// Avoid errors below, since the renderTasks are just stubs.
|
// Avoid errors below, since the renderTasks are just stubs.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const intentState = this.intentStates[intent];
|
|
||||||
intentState.renderTasks.forEach(function(renderTask) {
|
intentState.renderTasks.forEach(function(renderTask) {
|
||||||
const renderCompleted = renderTask.capability.promise.
|
const renderCompleted = renderTask.capability.promise.
|
||||||
catch(function() {}); // ignoring failures
|
catch(function() {}); // ignoring failures
|
||||||
waitOn.push(renderCompleted);
|
waitOn.push(renderCompleted);
|
||||||
renderTask.cancel();
|
renderTask.cancel();
|
||||||
});
|
});
|
||||||
}, this);
|
});
|
||||||
this.objs.clear();
|
this.objs.clear();
|
||||||
this.annotationsPromise = null;
|
this.annotationsPromise = null;
|
||||||
this.pendingCleanup = false;
|
this.pendingCleanup = false;
|
||||||
@ -1273,8 +1284,7 @@ class PDFPageProxy {
|
|||||||
* For internal use only.
|
* For internal use only.
|
||||||
* @ignore
|
* @ignore
|
||||||
*/
|
*/
|
||||||
_renderPageChunk(operatorListChunk, intent) {
|
_renderPageChunk(operatorListChunk, intentState) {
|
||||||
const intentState = this.intentStates[intent];
|
|
||||||
// Add the new chunk to the current operator list.
|
// Add the new chunk to the current operator list.
|
||||||
for (let i = 0, ii = operatorListChunk.length; i < ii; i++) {
|
for (let i = 0, ii = operatorListChunk.length; i < ii; i++) {
|
||||||
intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
|
intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
|
||||||
@ -1293,6 +1303,86 @@ class PDFPageProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For internal use only.
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
_pumpOperatorList(args) {
|
||||||
|
assert(args.intent,
|
||||||
|
'PDFPageProxy._pumpOperatorList: Expected "intent" argument.');
|
||||||
|
|
||||||
|
const readableStream =
|
||||||
|
this._transport.messageHandler.sendWithStream('GetOperatorList', args);
|
||||||
|
const reader = readableStream.getReader();
|
||||||
|
|
||||||
|
const intentState = this.intentStates[args.intent];
|
||||||
|
intentState.streamReader = reader;
|
||||||
|
|
||||||
|
const pump = () => {
|
||||||
|
reader.read().then(({ value, done, }) => {
|
||||||
|
if (done) {
|
||||||
|
intentState.streamReader = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this._transport.destroyed) {
|
||||||
|
return; // Ignore any pending requests if the worker was terminated.
|
||||||
|
}
|
||||||
|
this._renderPageChunk(value.operatorList, intentState);
|
||||||
|
pump();
|
||||||
|
}, (reason) => {
|
||||||
|
intentState.streamReader = null;
|
||||||
|
|
||||||
|
if (this._transport.destroyed) {
|
||||||
|
return; // Ignore any pending requests if the worker was terminated.
|
||||||
|
}
|
||||||
|
if (intentState.operatorList) {
|
||||||
|
// Mark operator list as complete.
|
||||||
|
intentState.operatorList.lastChunk = true;
|
||||||
|
|
||||||
|
for (let i = 0; i < intentState.renderTasks.length; i++) {
|
||||||
|
intentState.renderTasks[i].operatorListChanged();
|
||||||
|
}
|
||||||
|
this._tryCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intentState.displayReadyCapability) {
|
||||||
|
intentState.displayReadyCapability.reject(reason);
|
||||||
|
} else if (intentState.opListReadCapability) {
|
||||||
|
intentState.opListReadCapability.reject(reason);
|
||||||
|
} else {
|
||||||
|
throw reason;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
pump();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For internal use only.
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
_abortOperatorList({ intentState, reason, force = false, }) {
|
||||||
|
assert(reason instanceof Error,
|
||||||
|
'PDFPageProxy._abortOperatorList: Expected "reason" argument.');
|
||||||
|
|
||||||
|
if (!intentState.streamReader) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!force && intentState.renderTasks.length !== 0) {
|
||||||
|
// Ensure that an Error occuring in *only* one `InternalRenderTask`, e.g.
|
||||||
|
// multiple render() calls on the same canvas, won't break all rendering.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (reason instanceof RenderingCancelledException) {
|
||||||
|
// Aborting parsing on the worker-thread when rendering is cancelled will
|
||||||
|
// break subsequent rendering operations. TODO: Remove this restriction.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
intentState.streamReader.cancel(
|
||||||
|
new AbortException(reason && reason.message));
|
||||||
|
intentState.streamReader = null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {Object} Returns page stats, if enabled.
|
* @return {Object} Returns page stats, if enabled.
|
||||||
*/
|
*/
|
||||||
@ -1955,15 +2045,6 @@ class WorkerTransport {
|
|||||||
page._startRenderPage(data.transparency, data.intent);
|
page._startRenderPage(data.transparency, data.intent);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
messageHandler.on('RenderPageChunk', function(data) {
|
|
||||||
if (this.destroyed) {
|
|
||||||
return; // Ignore any pending requests if the worker was terminated.
|
|
||||||
}
|
|
||||||
|
|
||||||
const page = this.pageCache[data.pageIndex];
|
|
||||||
page._renderPageChunk(data.operatorList, data.intent);
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
messageHandler.on('commonobj', function(data) {
|
messageHandler.on('commonobj', function(data) {
|
||||||
if (this.destroyed) {
|
if (this.destroyed) {
|
||||||
return; // Ignore any pending requests if the worker was terminated.
|
return; // Ignore any pending requests if the worker was terminated.
|
||||||
@ -2083,33 +2164,6 @@ class WorkerTransport {
|
|||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
messageHandler.on('PageError', function(data) {
|
|
||||||
if (this.destroyed) {
|
|
||||||
return; // Ignore any pending requests if the worker was terminated.
|
|
||||||
}
|
|
||||||
|
|
||||||
const page = this.pageCache[data.pageIndex];
|
|
||||||
const intentState = page.intentStates[data.intent];
|
|
||||||
|
|
||||||
if (intentState.operatorList) {
|
|
||||||
// Mark operator list as complete.
|
|
||||||
intentState.operatorList.lastChunk = true;
|
|
||||||
|
|
||||||
for (let i = 0; i < intentState.renderTasks.length; i++) {
|
|
||||||
intentState.renderTasks[i].operatorListChanged();
|
|
||||||
}
|
|
||||||
page._tryCleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intentState.displayReadyCapability) {
|
|
||||||
intentState.displayReadyCapability.reject(new Error(data.error));
|
|
||||||
} else if (intentState.opListReadCapability) {
|
|
||||||
intentState.opListReadCapability.reject(new Error(data.error));
|
|
||||||
} else {
|
|
||||||
throw new Error(data.error);
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
messageHandler.on('UnsupportedFeature', this._onUnsupportedFeature, this);
|
messageHandler.on('UnsupportedFeature', this._onUnsupportedFeature, this);
|
||||||
|
|
||||||
messageHandler.on('JpegDecode', function(data) {
|
messageHandler.on('JpegDecode', function(data) {
|
||||||
|
@ -320,13 +320,12 @@ describe('evaluator', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('operator list', function () {
|
describe('operator list', function () {
|
||||||
function MessageHandlerMock() { }
|
class StreamSinkMock {
|
||||||
MessageHandlerMock.prototype = {
|
enqueue() { }
|
||||||
send() { },
|
}
|
||||||
};
|
|
||||||
|
|
||||||
it('should get correct total length after flushing', function () {
|
it('should get correct total length after flushing', function () {
|
||||||
var operatorList = new OperatorList(null, new MessageHandlerMock());
|
var operatorList = new OperatorList(null, new StreamSinkMock());
|
||||||
operatorList.addOp(OPS.save, null);
|
operatorList.addOp(OPS.save, null);
|
||||||
operatorList.addOp(OPS.restore, null);
|
operatorList.addOp(OPS.restore, null);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user